Как удалить каждый второй вхождение элемента во вложенном списке - PROLOG - PullRequest
1 голос
/ 08 января 2020

Предположим, у меня есть список типа [1,[2,1,[2],[3,1,1,[[3]],1,[1]],1],2,1,2,1,3], и я хочу удалить из него каждое второе вхождение '1' для результирующего списка [1,[2,[2],[3,1,[[3]],1,[]],1],2,2,1,3]. Пока что я придумал вот что:

delete_second_occurrence([], [], _, _).
delete_second_occurrence([X|L], [X|R], X, N) :-
   0 is mod(N, 2),
   N1 is N + 1,
   delete_second_occurrence(L, R, X, N1).
delete_second_occurrence([X|L], R, X, N) :-
   1 is mod(N, 2),
   N1 is N + 1,
   delete_second_occurrence(L, R, X, N1).
delete_second_occurrence([E|L], [E|R], X, N) :-
   is_list(E),
   delete_second_occurrence(E, R, X, N),
   delete_second_occurrence(L, R, X, N).
delete_second_occurrence([E|L], [E|R], X, N) :-
   delete_second_occurrence(L, R, X, N).

Чтобы уточнить,

  • R - результирующий список
  • L - список ввода
  • X - это элемент, который я хочу удалить
  • N - это количество раз, когда X встречался

Он удаляет каждое второе вхождение на самом нижнем уровне, но не ничего для вложенных списков. Как мне go удалить также дубликаты во вложенных списках?

1 Ответ

1 голос
/ 10 января 2020

Основной проблемой является четвертое предложение:

delete_second_occurrence([E|L], [E|R], X, N) :-
    is_list(E),
    delete_second_occurrence(E, R, X, N),
    delete_second_occurrence(L, R, X, N).

Второе условие истинно, если R является результатом удаления каждого второго вхождения X в E. Третье условие истинно, если R является результатом удаления каждого второго вхождения X в L. Кроме того, N должно иметь одинаковое значение после вызова delete_second_occurrence для E и L. Не многие списки имеют эти свойства. Необходимо решить две проблемы:

  1. Выберите другое имя переменной в первом вызове delete_second_occurrence и соответствующим образом обновите заголовок предложения.
  2. Введите другой аргумент, представляющий состояние аккумулятора после рекурсивного вызова.

Вместо того, чтобы считать количество раз, с которыми встречалось X, вы можете использовать логическую переменную. Нет необходимости выполнять модульную арифметику c. После этого вы заметите, что ваша программа генерирует одно правильное решение и несколько неправильных. Например, рассмотрим пятое предложение:

delete_second_occurrence([E|L], [E|R], X, N) :-
   delete_second_occurrence(L, R, X, N).

В этом пункте указывается, что [E|R] является результатом удаления каждого второго вхождения X в [E|L], если R является результатом удаления каждого второе вхождение X в L. Это не всегда верно. Например, если N равно 1 и E объединено с X, вы, конечно, не хотите включать E в список вывода. Точно так же, если E является списком, который содержит X, вы, вероятно, не должны генерировать решения, которые просто добавляют E к результату рекурсивного вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...