2017-01-18 5 views
4

Я много обманул и не мог понять. Можно ли сделать скрипт, который с отступаться генерирует списки в этом формате:Prolog - Генерирование чередующихся символов на обратном пути: [a]; [А, Ь]; [А, Ь, а]; [a, b, a, b]

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

Я сделал один, который генерирует одновременно два элемента, но моя голова начала болеть, пытаясь сделать тот, который генерирует «а »и в следующий раз« b », а затем« a »и так далее.

Вот сценарий одновременно двух элементов:

ab([a]). 
ab([b,a|T]):-ab([a|T]). 
ab([a,b|T]):-ab([b|T]). 

ответ

7

При описании списков, всегда рекомендуется использовать DCG обозначения.

Это очень удобно сфокусировать суть сути того, что вы хотите описать, без большого количества дополнительных переменных и аргументов.

Для примера рассмотрим:

 
abs --> [a], abs_rest. 

abs_rest --> []. 
abs_rest --> [b], ([] | abs). 

Пример запроса и ответа:

 
?- phrase(abs, ABs). 
ABs = [a] ; 
ABs = [a, b] ; 
ABs = [a, b, a] ; 
ABs = [a, b, a, b] ; 
ABs = [a, b, a, b, a] ; 
ABs = [a, b, a, b, a, b] . 

См для получения дополнительной информации об этом удобном формализма!

+0

Спасибо! Это интересно, не наткнуться на него раньше, и мы, конечно, не узнаем его в нашем курсе в моем университете, это ценная информация! В любом случае, я тренирую свои рекурсионные убийства и создаю сценарии генерации, и я не уверен, будут ли DCG приняты на моем экзамене, поэтому я все еще ищу решение по традиционному пути :) –

+1

Если «традиционным способом», вы имеете в виду «менее читаемым способом», просто используйте следующий запрос, чтобы получить простой код Пролога, соответствующий DCG: '? - listing (abs // 0), список (abs_rest // 0). Вы можете взять свой вывод , передайте его своему инструктору и знайте, что есть лучшее решение, которое вам, вероятно, не разрешено использовать, потому что зачем использовать подходящий формализм, когда есть более сложный способ выразить одно и то же? – mat

+0

Традиционное не было подходящим словом для описания того, что мне нужно. Я пытаюсь понять это, используя только функции Head, Tail и recursion в списках. Таким образом: ab ([a]). ab ([b, a | T]): - ab ([a | T]). ab ([a, b | T]): - ab ([b | T]). –

3

Я согласен с @mat, что следует использовать , когда это возможно для этих типов задач.

Это - другие правила.

abs --> [a]. 
abs --> [a,b]. 
abs --> [a,b], abs. 

?- phrase(abs, Ls). 
Ls = [a] ; 
Ls = [a, b] ; 
Ls = [a, b, a] ; 
Ls = [a, b, a, b] ; 
Ls = [a, b, a, b, a] ; 
Ls = [a, b, a, b, a, b] ; 
Ls = [a, b, a, b, a, b, a] ; 
Ls = [a, b, a, b, a, b, a, b] ; 
Ls = [a, b, a, b, a, b, a, b, a] 

Интересно эти правила начали с этого изменения

abs2 --> []. 
abs2 --> [a]. 
abs2 --> [a,b], abs2. 

?- phrase(abs2, Ls). 
Ls = [] ; 
Ls = [a] ; 
Ls = [a, b] ; 
Ls = [a, b, a] ; 
Ls = [a, b, a, b] ; 
Ls = [a, b, a, b, a] ; 
Ls = [a, b, a, b, a, b] ; 
Ls = [a, b, a, b, a, b, a] ; 
Ls = [a, b, a, b, a, b, a, b] 

, который является одним из упражнений из Using Definite Clause Grammars in SWI-Prolog

Если вы предпочитаете не использовать DCG, то я согласен с @mat и предположить, что вы используете listing/1, чтобы увидеть DCG в стандартном синтаксисе Prolog.

listing(abs). 

abs([a|A], A). 
abs([a, b|A], A). 
abs([a, b|A], B) :- 
     abs(A, B). 

listing(abs2). 

abs2(A, A). 
abs2([a|A], A). 
abs2([a, b|A], B) :- 
     abs2(A, B). 

В нормальных правил Пролога они могут быть использованы в качестве таковых:

abs(X,[]). 
X = [a] ; 
X = [a, b] ; 
X = [a, b, a] ; 
X = [a, b, a, b] ; 
X = [a, b, a, b, a] ; 
X = [a, b, a, b, a, b] ; 
X = [a, b, a, b, a, b, a] 

abs2(X,[]). 
X = [] ; 
X = [a] ; 
X = [a, b] ; 
X = [a, b, a] ; 
X = [a, b, a, b] ; 
X = [a, b, a, b, a] ; 
X = [a, b, a, b, a, b] 
+1

Текст, на который вы ссылаетесь, использует устаревшую терминологию, пожалуйста, используйте лучше поддерживаемый документ. – mat

+0

@mat Я понимаю, что вы имеете в виду: «Использование грамотных маркеров в SWI-Prolog'. Я добавил ссылку для этого, чтобы показать, что есть другие подобные проблемы, в основном это причина ссылки. –

+0

Спасибо, товарищ, для дальнейшего объяснения этого, оценили! –

1

Предикат Вы писали слишком общо:

?- ab([b,a]). 
true 

Причиной является следующее правило

ab([b,a|T]) :- 
    ab([a|T]). 

Можно сказать, что вы cribe промежуточный результат, который не является решением вашей реальной проблемы.Чтобы исправить это, можно утверждать, чем ab последовательности начинается с a, а остальные бюстами быть ba последовательностью, где ba последовательность снова определена в терминах ab последовательностей:

ab([a]). 
ab([a|Xs]) :- 
    ba(Xs). 

ba([b]). 
ba([b|Xs]) :- 
    ab(Xs). 

В качестве альтернативы, вы можете думать о abs, как конечный автомат, который производит a всякий раз, когда последний элемент был b и наоборот. Если ввести дополнительный аргумент, чтобы проследить историю, мы приходим:

abs(a,[a]). 
abs(b,[b]). 
abs(a,[a|Xs]) :- 
    abs(b,Xs). 
abs(b,[b|Xs]) :- 
    abs(a,Xs). 

Теперь определим ab последовательность, как тот, который последний предварённое a:

ab(Xs) :- 
    abs(a,Xs). 

Удачи :)