Ответ в теме: Преобразовать список в множество — удалить повторы элементов

      Комментарии к записи Ответ в теме: Преобразовать список в множество — удалить повторы элементов отключены
#1952

В этой задаче необходимо на каждом шаге рассматривать список в виде совокупности обработанных элементов, текущего элемента и необработанной части списка, т.к. необходимо выполнять проверку наличия текущего элемента в обработанной части.

Нужно использовать метод накапливающего параметра чтобы на i-том шаге был построен результат для предыдущих i-1 шагов, однако в этом случае результат окажется перевернутым. Функции используют стандартные предикаты member и reverse для поиска элемента в списка и реверса списка.

list_to_set(List, Set):-
  list_to_set(List, [], ReverseSet),
  reverse(ReverseSet, Set).

Правило вызывает вспомогательную функцию, использующую накаливающий параметр, передавая в качестве начального значения буфера пустой список, а затем, выполняет реверс результата.

list_to_set([], Buffer, Buffer):-!.
list_to_set([Head|Tail], Buffer, Set):-
  member(Head, Buffer), !, list_to_set(Tail, Buffer, Set);
  list_to_set(Tail, [Head|Buffer], Set).

Если исходный список пуст, значит все элементы уже обработаны — функция возвращает накопленный в буфере результат.
В остальных случаях выполняется поиск первого элемента списка в накопленном результате — если элемент удается найти, то первый элемент списка не будет добавлен в буфер, используемый при рекурсивной обработке остальных элементов списка.