Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prolog - Generate alternating symbols on backtrack: [a] ; [a,b]; [a,b,a]; [a,b,a,b]

Tags:

list

prolog

dcg

I've wrapped my mind a lot and couldn't figure it out. Is it possible to make a script that with backtrack generates lists in this format:

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

I've made one that generates two elements at a time but my head started to hurt trying to make one that generates "a" and the next time "b" and the next "a" and so on.

Here is the script for two elements at a time:

ab([a]).
ab([b,a|T]):-ab([a|T]).
ab([a,b|T]):-ab([b|T]).
like image 516
Dimitur Epitropov Avatar asked Jan 18 '17 19:01

Dimitur Epitropov


People also ask

What does \+ mean in Prolog?

Because of the problems of negation-as-failure, negation in Prolog is represented in modern Prolog interpreters using the symbol \+ , which is supposed to be a mnemonic for not provable with the \ standing for not and the + for provable.

What does symbol mean in Prolog?

symbol represents the cut . You can read more about cut here. Also, an example in prolog can be found here.

How do I copy a list to another list in Prolog?

When you call copy , it works its way down to the base case, where it sets R to an empty list. Then, as it works back up, it keeps appending the head H of known list [H|T1] to the beginning of variable list [H|T2] . It does that until the original case is reached, at which point R contains a full copy of L .

What does pipe do in Prolog?

The pipe operator in prolog returns one or more atomic Heads and a Tail list. ?- [a,b,c] = [a,b|[c]].


2 Answers

When describing lists, always consider using DCG notation.

This makes it very convenient to focus an the essence of what you want to describe, without so many additional variables and arguments.

For example, consider:

abs --> [a], abs_rest.

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

Sample query and answer:

?- 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] .

See dcg for more information about this convenient formalism!

like image 145
mat Avatar answered Sep 21 '22 14:09

mat


I agree with @mat that one should use dcg when possible for these type of problems.

Here is a different set of rules.

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] 

Interestingly those rules started from this variation

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] 

which is one of the exercises from Using Definite Clause Grammars in SWI-Prolog

If you prefer not to use DCG, then I agree with @mat and suggest that you use listing/1 to see the DCG in standard Prolog syntax.

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).

As normal Prolog rules they can be used as such:

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] 
like image 38
Guy Coder Avatar answered Sep 20 '22 14:09

Guy Coder