К нему можно подойти очень похоже на your other problem. Вот связанные с этим идеи.
Вам нужно будет сохранить список повторяющихся элементов, так как ваши результаты имеют счетчики. Поэтому рассмотрим вспомогательный предикат, который включает текущий текущий список повторов. Этот «список запуска» обычно используется в Prolog и называется аккумулятором .
split(L, C) :-
split(L, [], C). % Start repeat list accumulator at []
Теперь вам необходимо рассмотреть несколько различных случаев:
split([], _, []). % This is an easy one!
Это говорит о том, что если сжать пустой список, я получаю пустой список.
split([H], A, [[H|A]]). % This is an easy one!
Это один говорит, что если бы я собрать список из одного элемента, и мой текущий список бегущего повтора A
, то результат [[H|A]]
.
split([H, H|T], A, TC) :-
...
Это тот случай, когда у меня есть список бегущий повтора, A
, а элемент все еще повторяется. Результатом будет список TC
, но я не знаю, как он выглядит, поскольку мы все еще находимся в повторяющемся цикле, и его нужно будет определить путем рекурсии. Каким должен быть этот предикат? Рекурсивный вызов split1
, который будет необходим в этом разделе, будет иметь новый список аккумуляторов. На что это похоже?.
split([H1, H2|T], A, [[H1|A]|TC]) :-
dif(H1, H2),
...
Это тот случай, когда у меня есть список бегущий повтора, A
и повторяющиеся остановки в H1
. Поскольку повторение текущего цикла заканчивается H1
, мы знаем, что результат выглядит как [[H1|A]|TC]
, потому что цикл повторения завершен с H1
, а весь повторяющийся список равен H1
с хвостом A
(который только что добавляет H1
в A
, и все они один и тот же элемент). Мы просто еще не определили остальную часть списка TC
через рекурсию. Как должна выглядеть эта предикатная реализация?
Существуют и другие способы выполнения вышеуказанной логики (например, с конструкцией ->
и ;
и т. Д.), Но это будет оставаться простым.
Постарайтесь думать об этом как о правилах, где глава предложения предиката является утверждением, которое будет истинным, если следующие элементы предложения истинны. И подумайте рекурсивно.
Подумав, это может быть сделано без отдельного аккумулятора, используя результат для переноса аккумулятора:
split([], []).
split([H], [[H]]).
split([H1,H2|T], [[H1]|R]) :-
dif(H1, H2),
split(...). % left as an exercise
split([H,H|T], [[H|TH]|R]) :-
split(...). % left as an exercise
Что происходит, когда вы пытаетесь оценить свой предикат? Чего вы ожидали? Вы пытались отследить свою программу, чтобы увидеть, где она пойдет не так (если это так)? –
Какой ответ вы ожидаете для '[a, a, a, b, b, a, b, a, a]'? – repeat
[[a, a, a], [b, b], [a], [b], [a, a]] –