Вы получили ответы. Prolog - это язык, который часто предлагает несколько «правильных» способов решения проблемы. Из вашего ответа неясно, настаиваете ли вы на каком-либо порядке в своих ответах. Таким образом, игнорируя приказ, один из способов сделать это будет:
- Сортировка списка, используя стабильную сортировку (тот, который не падает дубликатов)
- Нанести кодирование длин серий на отсортированном списке
Главным достоинством этого подхода является то, что он деконструирует вашу проблему до двух четко определенных (и решенных) под-проблем.
Первый легко: msort(List, Sorted)
Второй один немного сложнее, но по-прежнему прямо вперед, если вы хотите, чтобы предикат работать только в одну сторону, то есть, список -> Кодировка. Одним из возможных вариантов (довольно явный):
list_to_rle([], []).
list_to_rle([X|Xs], RLE) :-
list_to_rle_1(Xs, [[X, 1]], RLE).
list_to_rle_1([], RLE, RLE).
list_to_rle_1([X|Xs], [[Y, N]|Rest], RLE) :-
( dif(X, Y)
-> list_to_rle_1(Xs, [[X, 1],[Y, N]|Rest], RLE)
; succ(N, N1),
list_to_rle_1(Xs, [[X, N1]|Rest], RLE)
).
Так что теперь, с верхнего уровня:
?- msort([a,b,c,a,b,c,d], Sorted), list_to_rle(Sorted, RLE).
Sorted = [a, a, b, b, c, c, d],
RLE = [[d, 1], [c, 2], [b, 2], [a, 2]].
На стороне записки, это почти всегда лучше предпочесть «пары», как и в X-N
, вместо списков с двумя элементами точно, как в [X, N]
. Кроме того, вы должны сохранить первоначальный порядок элементов в списке, если вы хотите быть верным. От this answer:
rle([], []).
rle([First|Rest],Encoded):-
rle_1(Rest, First, 1, Encoded).
rle_1([], Last, N, [Last-N]).
rle_1([H|T], Prev, N, Encoded) :-
( dif(H, Prev)
-> Encoded = [Prev-N|Rest],
rle_1(T, H, 1, Rest)
; succ(N, N1),
rle_1(T, H, N1, Encoded)
).
Почему это лучше?
мы избавились от 4-х пара ненужных скобок в коде
мы избавились от беспорядка в отчётном растворе
мы избавились от всего много ненужных вложенных терминов: сравните .(a, .(1, []))
с -(a, 1)
Мы сделали программу более понятной для читателя (это обычный способ представления пар в Prolog)
С верхнего уровня:
?- msort([a,b,c,a,b,c,d], Sorted), rle(Sorted, RLE).
Sorted = [a, a, b, b, c, c, d],
RLE = [a-2, b-2, c-2, d-1].
Представленных длинами кодера очень четко в своем определении, что имеет, конечно, свои плюсы и минусы. См. this answer для более сжатого способа сделать это.
Где 'd' в' [a, b, c] '? Почему он включен? Почему 'a',' b' и 'c' получают количество' 2'? – dasblinkenlight
sry my fault Я пытался много возможностей. – Nik
У вас есть конкретный вопрос?Есть несколько способов подойти к проблеме. Во-первых, если вы не возражаете сначала сортировать, вы можете сделать 'msort/2', который собирает как элементы вместе, что упрощает их рекурсию. Или вы можете создать предикаты, которые обновляют ваш счетный список (который в конечном итоге становится вашим результатом), а другой, который проходит через каждый элемент в исходном списке и обновляет список подсчета с помощью первого предиката. – lurker