Упражнение 09 на этой странице http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/ просит создать предикат, который содержит повторяющиеся элементы в подсписках.`var (A)` и порядок выполнения
Простое решения является прямым
pack([], []).
pack([H|T], [I|U]) :-
split(H, T, I, P),
pack(P, U).
где раскол split(Head, Tail, HeadGroup, Rest)
определяется как
split(A, [], [A], []).
split(A, [B|T], [A], [B|T]) :- A \= B.
split(A, [A|T], [A|U], B) :- split(A, T, U, B).
, который отлично работает и в значительной степени в соответствии с примерным решением, представленным на указанной выше странице ,
Если это решение не удается, такие запросы, как pack(X, [[a], [b, b]]).
. Соответствие между двумя наборами решений является биективным (для каждого A
в pack(A, B)
существует один и только один B
), поэтому должно быть лучшее решение.
Один из способов ее решения, чтобы изменить порядок оценки, помогая пролог выбрать нон бесконечную ветвь в зависимости от типа аргумента, как следующий
pack([], []).
pack(A, B) :-
(var(A) ->
A = [H|T],
B = [I|U],
pack(P, U),
split(H, T, I, P)
; A = [H|T],
B = [I|U],
split(H, T, I, P),
pack(P, U)
).
Два вопроса в связи с этим.
Во-первых, это невероятно уродливо, так может быть лучший способ выбрать порядок правил в зависимости от типа аргумента?
Во-вторых, возможно, гораздо более сложный вопрос, есть ли способ переписать решение без var(A)
, а если нет, то почему?
Чистый гений! С 'dif' он теперь может даже решить сумасшедшие вещи, такие как' pack (A, [X, [b]]). – vasily
Перепробовай все мои предыдущие решения. – vasily
Да, это так. 'dif/2' был доступен даже в самой первой системе Prolog, а затем по большому счету игнорировался разработчиками, и теперь становится все более распространенным в реализации снова. Рассуждение во всех направлениях - это, в конце концов, одна из главных достопримечательностей реляционного программирования, поэтому используйте 'dif/2', чтобы выразить беспорядок по срокам в здравом и общем смысле. – mat