Я знаю, что оригинальный вопрос был опубликован довольно давно, но я совсем недавно работал над некоторыми проблемами в Art Of Prolog и продумывал проблему четной / нечетной перестановки длянесколько дней.Я не хотел открывать дублирующую проблему, поэтому выкладываю свое решение здесь.
Проблема в книге спрашивает:
Написание программ для even_permutation(Xs, Ys)
и odd_permutation(Xs,
Ys)
, которые находят Ys
, четную и нечетную перестановки списка Xs
соответственно.Например, even_permutation([1,2,3], [2,3,1])
и odd_permutation([1,2,3], [2,1,3])
имеют значение true.
Таким образом, он запрашивает генераторы перестановок, а не только верификаторы.@hardmath предоставил ссылку на правильное определение четной или нечетной перестановки.Авторы книги привели два простых примера для иллюстрации.
Для меня ключом было выяснение рекурсивного определения четной или нечетной перестановки.Для всех перестановок в классическом генераторе перестановок в Прологе используется следующее понятие:
- Каждая перестановка из N + 1 элементов - это список, представляющий перестановку из N элементов с (N + 1) -ымэлемент, вставленный в список.
Предикат select
или insert
используется для вставки.
Для четных и нечетных перестановок я рассмотрел аналогичную идею:
Каждая четная перестановка N + 1 элементов представляет собой либо список, представляющий четную перестановку N элементов с (N + 1)) st элемент, вставленный в нечетное положение в списке, или список, представляющий нечетное перестановку N элементов с (N + 1) st элементом, вставленным в четная позиция в списке.
Каждая нечетная перестановка из N + 1 элементов является либо списком, представляющим нечетную перестановкуиз N элементов с (N + 1) -м элементом, вставленным в odd позиция в списке или список, представляющий четную перестановку N элементов с (N + 1) -ым элементом, вставленным в четную позицию в списке.
Рациональным является то, что вставка элемента в нечетную позицию представляет собой четное число перестановок относительно исходного списка (передняя часть списка, являющаяся первой позицией, требуетбез свопов, так что это даже).Точно так же вставка элемента в четную позицию представляет нечетное количество перестановок относительно исходного списка.
Если я добавлю к этому правило, что пустой список - это его собственная четная перестановка, то я могу определитьследующие предикаты для генерации четных и нечетных перестановок:
even_permutation( [], [] ).
even_permutation( [X|T], Perm ) :-
even_permutation( T, Perm1 ),
insert_odd( X, Perm1, Perm ).
even_permutation( [X|T], Perm ) :-
odd_permutation( T, Perm1 ),
insert_even( X, Perm1, Perm ).
odd_permutation( [X|T], Perm ) :-
odd_permutation( T, Perm1 ),
insert_odd( X, Perm1, Perm ).
odd_permutation( [X|T], Perm ) :-
even_permutation( T, Perm1 ),
insert_even( X, Perm1, Perm ).
insert_odd( X, InList, [X|InList] ).
insert_odd( X, [Y,Z|InList], [Y,Z|OutList] ) :-
insert_odd( X, InList, OutList ).
insert_even( X, [Y|InList], [Y,X|InList] ).
insert_even( X, [Y,Z|InList], [Y,Z|OutList] ) :-
insert_even( X, InList, OutList ).