2015-11-09 3 views
0

У меня есть списокРасщепление в прологе на основе состояния

[a,a,a,a,b,b] 

Моя цель состоит, чтобы разделить его на

[[a,a,a,a],[b,b]] 

предиката я реализовали до сих пор

split1([],[]). 
split1([A1|T],[[H1,H2]|B]):- 
A1=[H1,H2], 
H1=H2, 
split(T,B). 

split1([],[]). 
split1([A1|T],[[H1,H2]|B]):- 
A1=[H1,H2], 
H1\=H2, 
split(T,B). 

К сожалению для noob вопрос обучения пролог.

+1

Что происходит, когда вы пытаетесь оценить свой предикат? Чего вы ожидали? Вы пытались отследить свою программу, чтобы увидеть, где она пойдет не так (если это так)? –

+0

Какой ответ вы ожидаете для '[a, a, a, b, b, a, b, a, a]'? – repeat

+0

[[a, a, a], [b, b], [a], [b], [a, a]] –

ответ

3

К нему можно подойти очень похоже на 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 
+1

s (X): «... , но это будет просто ». Не просто, но * правильно *. – repeat

+0

... вы знаете, этот 'dif/2' всегда оставит точку выбора. – false

1

Вы должны взглянуть на SWI-Prolog implementation of group_pairs_by_key/2. Это немного больше, чем вам нужно, но я думаю, что легко отказаться от ненужных частей.

С предикатом, как это есть на данный момент, вы можете сделать:

?- L = [a,a,b,b,a,b,b], 
    keys_values_pairs(L, L, P), 
    group_pairs_by_key(P, G), 
    keys_values_pairs(_, Result, G). 
L = [a, a, b, b, a, b, b], 
P = [a-a, a-a, b-b, b-b, a-a, b-b, b-b], 
G = [a-[a, a], b-[b, b], a-[a], b-[b, b]], 
Result = [[a, a], [b, b], [a], [b, b]]. 

Так что вам просто нужно понять, что оставить, чтобы получить предикат, который не нуждается в паре из ключ и значение, но только одно значение. Поскольку это, очевидно, домашнее задание, и поскольку вы даже не приложили достаточных усилий в ответ, я оставлю это упражнением.

2

Все, что вам нужно, это splitlistIfAdj/3 and dif/3. Использование образца:

?- splitlistIfAdj(dif, [a,a,a,b,b,c,a,a,a,a], Xss). 
Xss = [[a,a,a],[b,b],[c],[a,a,a,a]]. 
+4

Если только одному не нужно было дополнительно определять 'splitlistIfAdj/3',' dif/3' и 'if_/3' .... И что случилось с camelCase btw? –

+3

Что касается camelCase ... Плохая привычка, я знаю. – repeat

+0

Я не слишком обеспокоен дополнительными определениями. Мы также используем другие предикаты библиотеки, даже если их реализация часто * довольно хрупкая *. – repeat

1

легко определение:

groups([X|Xs],[G|Gs]) :- take(X,Xs,G,Rs), groups(Rs, Gs). 
groups([],[]). 

take(X,[X|R],[X|G],S) :- !, take(X,R,G,S). 
take(X,R,[X],R). 

взять/4 поглощает и хранит соответствующие элементы, в результате чего остаток в группе

+0

@repeat: как это могло произойти? объединение 123 со списком? – CapelliC

+0

Мой плохой! Я повторил тест, и он сработал. Я сделал ошибку, вставив ваш код в интерпретатор Prolog ... Извините за пух. – repeat

+1

@repeat: спасибо. Пожалуйста, простите наивность моего ответа, его предназначение для новичка, что, по моему мнению, нужно понять основную часть Пролога, прежде чем копать в передовых проблемах – CapelliC

Смежные вопросы