Захват значений из одного списка в Прологе и добавление в другой список

Я пытаюсь разработать код в прологе для захвата элементов с частотой 0. Посмотрите на пример, кортеж:

[[1,31],[2,0],[3,21],[4,0],[5,0]]

Где каждый элемент представляет собой что-то еще с 2 элементами в каждом, поэтому элементы, которые должны быть захвачены, — это 2, 4 и 5 для частоты 0. Код ниже представляет идею:

match([],_).
match([[A,Y]|Tail],[A|Tail2]):- Y==0,match(Tail,[Tail2|A]),!.
match([[_,_]|Tail],X):- match(Tail,X).

Передаются два параметра: кортеж, содержащий набор целевых значений и частот,

(["Target value", "frequency"], ["target value", "frequency"], ...]

И второй параметр, который является переменной, получает целевые элементы. Однако абстракция, которую я должен был разработать, неверна, потому что результаты не такие, как ожидалось. Я прошел шаг за шагом, чтобы понять, изменил несколько вещей, и результат всегда один и тот же ... В любом случае возвращается список только из 2 элементов (даже если есть только одна цель с частотой 0).

Пример с 3 целями частоты 0:

?- match([[1,31],[2,0],[3,312],[4,0],[5,0]],X).
X = [2|4].

Ожидаемый результат для этого случая: X = [2,4,5].

Пример с 1 целевой частотой 0:

?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X).
X = [2|_9998].

Ожидаемый результат для этого случая: X = [2].

Кто-нибудь может мне помочь?


person Fellipe Peixoto    schedule 08.05.2017    source источник


Ответы (2)


Ты очень близко! Всего две маленькие проблемы:

  • В настоящее время, когда передается пустой список, вы говорите, что результатом может быть что угодно (_). Я очень сомневаюсь, что это то, что вы хотите; вывод для пустого списка также должен быть пустым списком.
  • Рекурсивный вызов во втором предложении неверен. Вы хотите, чтобы результат был A, за которым следует результат рекурсивного вызова (Tail2). Однако по какой-то причине вы написали рекурсивный вызов с A в нем. Я не могу точно сказать, как вы к этому пришли, но вы должны просто получить Tail2 самостоятельно.

Кроме того, вы можете избежать написания Y==0, написав его прямо в заголовке предложения. Результирующий код выглядит следующим образом:

match([],[]).
match([[A,0]|Tail], [A|Tail2]) :- match(Tail, Tail2), !.
match([[_,_]|Tail], X) :- match(Tail, X).

?- match([[1,31],[2,0],[3,312],[4,0],[5,0]],X).
X = [2, 4, 5]

?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X).
X = [2]
person Steven    schedule 08.05.2017
comment
Вау, большое спасибо! Я пока начинаю с пролога, и использование рекурсии в логическом программировании для меня что-то новое. Иногда так трудно понять, что я должен делать. - person Fellipe Peixoto; 08.05.2017

Вы можете описать полученный список с помощью DCG следующим образом:

match(Pairs,ZFs) :-           % the items with frequency 0
   phrase(zeros(Pairs),ZFs).  % are described by zeros//1

zeros([]) -->                 % the empty list
   [].                        % contains no items
zeros([[I,0]|Is]) -->         % if the frequency is 0
   [I],                       % the item is in the list
   zeros(Is).                 % the same for the remaining items
zeros([[I,F]|Is]) -->         % if the frequency
   {dif(F,0)},                % is not 0, the item isn't in the list
   zeros(Is).                 % the same for the remaining items

Таким образом, два примера запросов в вашем сообщении дают желаемые результаты:

   ?- match([[1,31],[2,0],[3,21],[4,0],[5,0]],X).
X = [2,4,5] ? ;
no
   ?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X).
X = [2] ? ;
no
person tas    schedule 09.05.2017