Вы правы, что, несмотря на то, что ваше решение работает, оно не очень чистое и непригодное для использования, поскольку оно работает только для списков длины 4. Попробуем определить рекурсивный предикат, который работает для списков любого размера.
Если посмотреть на оба списка по одному элементу за раз, на самом деле есть только два случая: либо те же элементы, либо они не являются.
Если они одинаковы, это означает, что остальные оба списка должны иметь ровно один другой элемент, чтобы добиться успеха. И это именно тот предикат, который мы пишем в первую очередь!
compare([H|T1], [H|T2]) :- compare(T1, T2).
Теперь для второго случая. Если первые элементы списка различны, то остальные в обоих списках должны быть точно такой же (как мы уже столкнулись с другой элемент
compare([H1|T1], [H2|T1]) :- H1 \= H2.
Там, вот и все! Теперь вы можете заметить выход, такие как это:
Это происходит потому, что есть еще пункт выбора открытый:. для первых элементов первой пункт спичек, но второй пункт не был рассмотрен еще в этом случае, хотя мы знаем, что оба положения являются взаимоисключающими, поэтому мы можем добавить разрез (!
), чтобы не оставалось никакой точки выбора.
Это также позволяет нам упростить второе закрытие: если мы достигнем этого, мы знаем, что первые элементы не совпадают, поэтому нет необходимости проверять это снова.
Собираем все вместе и код становится:
compare([H|T1], [H|T2]) :- !, compare(T1, T2).
compare([_|T], [_|T]).
Это то, что нужно! Спасибо! – KonaKona
Работает нормально (+1), но с оговоркой: оба списка должны быть без переменных, иначе код ведет себя немонотонно ... – repeat