recursive Prolog predicate? - prolog

i am currently working on a project and i want to implement helper predicate in Prolog
break_down(N, L)
which works as follows
?- break_down(1,L).
L = [1] ;
false.
?- break_down(4,L).
L = [1, 1, 1, 1] ;
L = [1, 1, 2] ;
L = [1, 3] ;
L = [2, 2] ;
L = [4] ;
false.
and so on for any positive integer N .
i have tried and implemented a code which generates only the first result and i cannot get the rest of the results , and this is my code
break_down(1,[1]).
break_down(N,L):-
N>0,
N1 is N-1,
break_down(N1,L1),
append(L1,[1],L).
which generates only the first output result :
L = [1, 1, 1, 1] ;
any suggestion how to edit my code to get the rest ?

Here's a straight-forward recursive implementation using plain integer arithmetic and backtracking:
break_down(N,L) :-
break_ref_down(N,1,L). % reference item is initially 1
break_ref_down(0,_,[]).
break_ref_down(N,Z0,[Z|Zs]) :-
between(Z0,N,Z), % multiple choices
N0 is N-Z,
break_ref_down(N0,Z,Zs). % pass on current item as reference
Sample query:
?- break_down(8,Zs).
Zs = [1,1,1,1,1,1,1,1]
; Zs = [1,1,1,1,1,1,2]
; Zs = [1,1,1,1,1,3]
; Zs = [1,1,1,1,2,2]
; Zs = [1,1,1,1,4]
; Zs = [1,1,1,2,3]
; Zs = [1,1,1,5]
; Zs = [1,1,2,2,2]
; Zs = [1,1,2,4]
; Zs = [1,1,3,3]
; Zs = [1,1,6]
; Zs = [1,2,2,3]
; Zs = [1,2,5]
; Zs = [1,3,4]
; Zs = [1,7]
; Zs = [2,2,2,2]
; Zs = [2,2,4]
; Zs = [2,3,3]
; Zs = [2,6]
; Zs = [3,5]
; Zs = [4,4]
; Zs = [8]
; false.

Here's an implementation based on clpfd.
:- use_module(library(clpfd)).
As the predicate break_downFD/2 is non-recursive, the code is both readable and simple:
break_downFD(N,Zs) :-
length(Max,N), % multiple choices
append(_,Zs,Max),
Zs ins 1..N,
sum(Zs,#=,N),
chain(Zs,#=<), % enforce sequence is non-descending
labeling([],Zs). % multiple choices, possibly
Sample query using SWI-Prolog:
?- break_downFD(6,Zs).
Zs = [1,1,1,1,1,1]
; Zs = [1,1,1,1,2]
; Zs = [1,1,1,3]
; Zs = [1,1,2,2]
; Zs = [1,1,4]
; Zs = [1,2,3]
; Zs = [2,2,2]
; Zs = [1,5]
; Zs = [2,4]
; Zs = [3,3]
; Zs = [6]
; false.

Related

Prolog - Matrix equation

I'm new to Prolog and I want to do something like this, but don't know where to start. Already made the matrix and how to verify the numbers are under 9 with Bounds library, but that's about it, have been struggling with this for days.
It should look like this:
2+7-4=5
+ - *
9-5*2=8
- + -
4*3-8=4
= = =
7 5 0
The main idea is to give Prolog a semi-filled matrix so he can complete it. Thanks for any info or ideas you can give me in advance.
A code for resolving equations by placing operators with given numbers:
:- use_module(library(bounds)).
lista([X]) --> [X].
lista([H|T]) --> [H], op, lista(T).
op --> [+].
op --> [-].
op --> [*].
op --> [/].
op --> [''].
puzzle(Num, Res) :-
permutation(Num, Numbperm),
lista(Numbperm, Lista, []),
concat_atom([Res, =:=|Lista], At),
term_to_atom(Ev, At),
call(Ev),
write(Ev), nl.
To utilize clpfd, let's use library(clpfd)), not library(bounds)!
:- use_module(library(clpfd)).
We can state the constraints that must hold like this:
m3x3_zs(Mss,Zs) :-
Mss = [[M11,M12,M13], [M21,M22,M23], [M31,M32,M33]],
Zs = [ M11,M12,M13 , M21,M22,M23 , M31,M32,M33 ],
Zs ins 0..9,
5 #= M11+M12-M13, % row constraints
8 #= (M21-M22)*M23, % (see text below for details)
4 #= M31*M32-M33,
7 #= M11+M21-M31, % column constraints
5 #= M12-M22+M23,
0 #= M13*M23-M33.
Note the highlighted goal 8 #= <b>(M21-M22)*M23</b> above! If we had used the common precedence rules for A-B*C we would have had 8 #= M21-(M22*M23), but that would have excluded the sample solution [[2,7,4],[9,5,2],[4,3,8]] you gave in the OP.
Now let's search all solutions by using the enumeration predicate
labeling/2!
?- m3x3_zs(Mss,Zs), labeling([],Zs).
Mss = [[0,5,0],[9,1,1],[2,2,0]], Zs = [0,5,0,9,1,1,2,2,0]
; Mss = [[0,5,0],[9,8,8],[2,2,0]], Zs = [0,5,0,9,8,8,2,2,0]
; Mss = [[0,7,2],[8,4,2],[1,8,4]], Zs = [0,7,2,8,4,2,1,8,4]
; Mss = [[0,8,3],[9,5,2],[2,5,6]], Zs = [0,8,3,9,5,2,2,5,6]
; Mss = [[1,4,0],[8,0,1],[2,2,0]], Zs = [1,4,0,8,0,1,2,2,0]
; Mss = [[1,4,0],[8,7,8],[2,2,0]], Zs = [1,4,0,8,7,8,2,2,0]
; Mss = [[1,5,1],[9,8,8],[3,4,8]], Zs = [1,5,1,9,8,8,3,4,8]
; Mss = [[1,6,2],[7,3,2],[1,8,4]], Zs = [1,6,2,7,3,2,1,8,4]
; Mss = [[1,7,3],[8,4,2],[2,5,6]], Zs = [1,7,3,8,4,2,2,5,6]
; Mss = [[1,8,4],[9,5,2],[3,4,8]], Zs = [1,8,4,9,5,2,3,4,8]
; Mss = [[2,3,0],[7,6,8],[2,2,0]], Zs = [2,3,0,7,6,8,2,2,0]
; Mss = [[2,4,1],[8,7,8],[3,4,8]], Zs = [2,4,1,8,7,8,3,4,8]
; Mss = [[2,5,2],[6,2,2],[1,8,4]], Zs = [2,5,2,6,2,2,1,8,4]
; Mss = [[2,6,3],[7,3,2],[2,5,6]], Zs = [2,6,3,7,3,2,2,5,6]
; Mss = [[2,7,4],[8,4,2],[3,4,8]], Zs = [2,7,4,8,4,2,3,4,8]
; Mss = [[3,2,0],[6,5,8],[2,2,0]], Zs = [3,2,0,6,5,8,2,2,0]
; Mss = [[3,3,1],[7,6,8],[3,4,8]], Zs = [3,3,1,7,6,8,3,4,8]
; Mss = [[3,4,2],[5,1,2],[1,8,4]], Zs = [3,4,2,5,1,2,1,8,4]
; Mss = [[3,5,3],[6,2,2],[2,5,6]], Zs = [3,5,3,6,2,2,2,5,6]
; Mss = [[3,6,4],[7,3,2],[3,4,8]], Zs = [3,6,4,7,3,2,3,4,8]
; Mss = [[4,1,0],[5,4,8],[2,2,0]], Zs = [4,1,0,5,4,8,2,2,0]
; Mss = [[4,2,1],[6,5,8],[3,4,8]], Zs = [4,2,1,6,5,8,3,4,8]
; Mss = [[4,3,2],[4,0,2],[1,8,4]], Zs = [4,3,2,4,0,2,1,8,4]
; Mss = [[4,4,3],[5,1,2],[2,5,6]], Zs = [4,4,3,5,1,2,2,5,6]
; Mss = [[4,5,4],[6,2,2],[3,4,8]], Zs = [4,5,4,6,2,2,3,4,8]
; Mss = [[5,0,0],[4,3,8],[2,2,0]], Zs = [5,0,0,4,3,8,2,2,0]
; Mss = [[5,1,1],[5,4,8],[3,4,8]], Zs = [5,1,1,5,4,8,3,4,8]
; Mss = [[5,3,3],[4,0,2],[2,5,6]], Zs = [5,3,3,4,0,2,2,5,6]
; Mss = [[5,4,4],[5,1,2],[3,4,8]], Zs = [5,4,4,5,1,2,3,4,8]
; Mss = [[6,0,1],[4,3,8],[3,4,8]], Zs = [6,0,1,4,3,8,3,4,8]
; Mss = [[6,3,4],[4,0,2],[3,4,8]], Zs = [6,3,4,4,0,2,3,4,8]
; false.
How about a little more specific? Which solutions have 4 in the middle?
?- m3x3_zs(Mss,Zs), Mss=[_,[_,4,_],_], labeling([],Zs).
Mss = [[0,7,2],[8,4,2],[1,8,4]], Zs = [0,7,2,8,4,2,1,8,4]
; Mss = [[1,7,3],[8,4,2],[2,5,6]], Zs = [1,7,3,8,4,2,2,5,6]
; Mss = [[2,7,4],[8,4,2],[3,4,8]], Zs = [2,7,4,8,4,2,3,4,8]
; Mss = [[4,1,0],[5,4,8],[2,2,0]], Zs = [4,1,0,5,4,8,2,2,0]
; Mss = [[5,1,1],[5,4,8],[3,4,8]], Zs = [5,1,1,5,4,8,3,4,8].

Instantiating L to a list of digits Prolog

If I have the following database:
digit(0).
digit(1).
digit(2).
digit(3).
digit(4).
digit(5).
digit(6).
digit(7).
digit(8).
digit(9).
I want the query
digits([X,Y]).
to succeed by instantiating X and Y to 10*10 = 100 different combinations of digits, how would I go about this?
Would I need to use finite domain constraints for this and something like
L ins 0..9
Thank you in advance
you don't need clpfd to do that. You can use higher order to obtain an expressive solution:
digits(L) :- maplist(digit, L).
You can also do the recursion yourself:
digits([]) :- [].
digits([H|T]) :- digit(H), digits(T).
Using clpfd is straight-forward:
?- use_module(library(clpfd)).
true.
?- length(Zs, 3), Zs ins 1..2, labeling([], Zs).
Zs = [1,1,1]
; Zs = [1,1,2]
; Zs = [1,2,1]
; Zs = [1,2,2]
; Zs = [2,1,1]
; Zs = [2,1,2]
; Zs = [2,2,1]
; Zs = [2,2,2].

Prolog. Fill out lists

I have to fill out a list of length n digits.
I know that n-1 is in the range from 1 to 9, and one digit can be in the range from 1 to 99.
I did it this way:
generate([First|Next],Czynniki):-
between(1,99,First),
generate2(Next).
generate2(Next):-
sublist([1,2,3,4,5,6,7,8,9],Next).
sublist([],[]).
sublist([H|T],[H|S]):-
sublist(T,S).
sublist([_|T],S):-
sublist(T,S).
Doing it this way I generate some of the same solutions.
Maybe you have some idea ​​how I can generate lists without repetition?
Edit
For the sake of clarity, I (#repeat) have added the following relevant comment by the OP:
At the entrance I have list of length N of undefined variables. And want fill out my list: N-1 numbers from the interval 1-9 and one number in the range 1-99.
Example: N=5, L=[56,2,3,4,8] ...
Use clpfd!
:- use_module(library(clpfd)).
Let's define digits10plusdigit100_n/2 like this:
digits10plusdigit100_n(Zs,N) :-
Zs = [CentDigit|DecDigits],
length(Zs,N),
CentDigit in 1..99,
DecDigits ins 1..9,
labeling([],Zs).
Sample queries:
?- digits10plusdigit100_n(Zs,1).
Zs = [1]
; Zs = [2]
; Zs = [3]
...
; Zs = [98]
; Zs = [99]
; false.
?- digits10plusdigit100_n(Zs,3).
Zs = [1,1,1]
; Zs = [1,1,2]
; Zs = [1,1,3]
...
; Zs = [1,2,1]
; Zs = [1,2,2]
...
; Zs = [1,9,8]
; Zs = [1,9,9]
; Zs = [2,1,1]
; Zs = [2,1,2]
...
; Zs = [2,1,3]
; Zs = [2,1,4]
...
; Zs = [98,9,9]
; Zs = [99,1,1]
; Zs = [99,1,2]
...
; Zs = [99,9,8]
; Zs = [99,9,9]
; false.
maybe change to between(10,99,X)
so reverse your predicates, generate numbers less then 10 and then generate last variable wich will be greater then 10
Isn't this just a variation of what #false very elegantly did in here ?
gen(Xs) :-
between(1, 9, L),
length(Xs, L),
maplist(between(1,99), Xs).
?- gen(Xs).
Xs = [1] ;
Xs = [2] ;
Xs = [3] ;
Xs = [4] ;
Xs = [5] ;
..
Xs = [99] ;
Xs = [1, 1] ;
Xs = [1, 2] ;
Xs = [1, 3] ;
Xs = [1, 4] ;
..
Xs = [1, 98] ;
Xs = [1, 99] ;
Xs = [2, 1] ;
Xs = [2, 2] ;
Xs = [2, 3] ;
Xs = [2, 4] ;
Xs = [2, 5] ;
Xs = [2, 6] ;

Get all sets of list in prolog

How can I generate all the possible sets of the elements of a list with current length?
?- get_set(X, [1,2,3]).
X = [1,1,1] ;
X = [1,1,2] ;
X = [1,1,3] ;
X = [1,2,1] ;
X = [1,2,2] ;
X = [1,2,3] ;
X = [1,3,1] ;
X = [1,3,2] ;
X = [1,3,3] ;
.....
X = [3,3,2] ;
X = [3,3,3].
UPD: there is good answer given by Sharky.
But maybe it's not the best. Here is another:
get_set(X,L) :- get_set(X,L,L).
get_set([],[],_).
get_set([X|Xs],[_|T],L) :- member(X,L), get_set(Xs,T,L).
Consider:
get_set(L0, L) :-
length(L, Len),
length(L0, Len),
apply_elem(L0, L).
apply_elem([], _).
apply_elem([X|Xs], L) :-
member(X, L),
apply_elem(Xs, L).
Explanation:
Determining the length of the input list L as Len allows us to generate a list of unique variables, L0, via length/2. Then, we simply apply elements of L to all members of L0 via member/2, which leaves choicepoints for options, should they exist (i.e., if the list L is of length > 1). Prolog will backtrack to generate all possible combinations of elements of L into the list L0, as required.
Based on library predicate same_length/2, we can make it work safely in "both" directions!
Simply define get_set/2 like this, using meta-predicate maplist/2:
get_set(Xs,Ys) :-
same_length(Xs,Ys),
maplist(list_member(Ys),Xs).
list_member(Xs,X) :-
member(X,Xs).
First, the sample query suggested by the OP:
?- get_set(Xs,[1,2,3]).
Xs = [1,1,1] ;
Xs = [1,1,2] ;
Xs = [1,1,3] ;
Xs = [1,2,1] ;
Xs = [1,2,2] ;
Xs = [1,2,3] ;
Xs = [1,3,1] ;
Xs = [1,3,2] ;
Xs = [1,3,3] ;
Xs = [2,1,1] ;
Xs = [2,1,2] ;
Xs = [2,1,3] ;
Xs = [2,2,1] ;
Xs = [2,2,2] ;
Xs = [2,2,3] ;
Xs = [2,3,1] ;
Xs = [2,3,2] ;
Xs = [2,3,3] ;
Xs = [3,1,1] ;
Xs = [3,1,2] ;
Xs = [3,1,3] ;
Xs = [3,2,1] ;
Xs = [3,2,2] ;
Xs = [3,2,3] ;
Xs = [3,3,1] ;
Xs = [3,3,2] ;
Xs = [3,3,3] ;
false. % terminates universally
Let's try the other way round!
?- get_set([1,2,3],Ys).
Ys = [1,2,3] ;
Ys = [1,3,2] ;
Ys = [2,1,3] ;
Ys = [3,1,2] ;
Ys = [2,3,1] ;
Ys = [3,2,1] ;
false. % terminates universally

Permuted combinations of the elements of a list - Prolog

How can I generate all the possible combinations of the elements of a list?
For example, given the list [1,2,3], I want to design a predicate with the form comb([1,2,3], L). which should return the following answer for L:
[1]
[2]
[3]
[1,2]
[2,1]
[1,3]
[3,1]
[2,3]
[3,2]
[1,2,3]
[1,3,2]
[2,1,3]
[2,3,1]
[3,1,2]
[3,2,1]
What you are asking for involves both combinations (selecting a subset) and permutations (rearranging the order) of a list.
Your example output implies that the empty list is not considered a valid solution, so we will exclude it in the implementation that follows. Reconsider if this was an oversight. Also this implementation produces the solutions in a different order than your example output.
comb(InList,Out) :-
splitSet(InList,_,SubList),
SubList = [_|_], /* disallow empty list */
permute(SubList,Out).
splitSet([ ],[ ],[ ]).
splitSet([H|T],[H|L],R) :-
splitSet(T,L,R).
splitSet([H|T],L,[H|R]) :-
splitSet(T,L,R).
permute([ ],[ ]) :- !.
permute(L,[X|R]) :-
omit(X,L,M),
permute(M,R).
omit(H,[H|T],T).
omit(X,[H|L],[H|R]) :-
omit(X,L,R).
Tested with Amzi! Prolog:
?- comb([1,2,3],L).
L = [3] ;
L = [2] ;
L = [2, 3] ;
L = [3, 2] ;
L = [1] ;
L = [1, 3] ;
L = [3, 1] ;
L = [1, 2] ;
L = [2, 1] ;
L = [1, 2, 3] ;
L = [1, 3, 2] ;
L = [2, 1, 3] ;
L = [2, 3, 1] ;
L = [3, 1, 2] ;
L = [3, 2, 1] ;
no
Stay pure by defining comb/2 based on same_length/2, prefix/2, foldl/4 and
select/3:
comb(As,Bs) :-
same_length(As,Full),
Bs = [_|_],
prefix(Bs,Full),
foldl(select,Bs,As,_).
Here's the sample query given by the OP:
?- comb([1,2,3],Xs).
Xs = [1]
; Xs = [2]
; Xs = [3]
; Xs = [1,2]
; Xs = [1,3]
; Xs = [2,1]
; Xs = [2,3]
; Xs = [3,1]
; Xs = [3,2]
; Xs = [1,2,3]
; Xs = [1,3,2]
; Xs = [2,1,3]
; Xs = [2,3,1]
; Xs = [3,1,2]
; Xs = [3,2,1]
; false.
Ok! But what if the list given as the first argument contains duplicates?
?- comb([1,1,2],Xs).
Xs = [1]
; Xs = [1] % (redundant)
; Xs = [2]
; Xs = [1,1]
; Xs = [1,2]
; Xs = [1,1] % (redundant)
; Xs = [1,2] % (redundant)
; Xs = [2,1]
; Xs = [2,1] % (redundant)
; Xs = [1,1,2]
; Xs = [1,2,1]
; Xs = [1,1,2] % (redundant)
; Xs = [1,2,1] % (redundant)
; Xs = [2,1,1]
; Xs = [2,1,1] % (redundant)
; false.
Not quite! Can we get rid of above redundant answers? Yes, simply use selectd/3!
comb(As,Bs) :-
same_length(As,Full),
Bs = [_|_],
prefix(Bs,Full),
foldl(selectd,Bs,As,_).
So let's re-run above query again with the improved implementation of comb/2!
?- comb([1,1,2],Xs).
Xs = [1]
; Xs = [2]
; Xs = [1,1]
; Xs = [1,2]
; Xs = [2,1]
; Xs = [1,1,2]
; Xs = [1,2,1]
; Xs = [2,1,1]
; false.
there is a predefined predicate called permutation ...
1 ?- permutation([1,2,3],L).
L = [1, 2, 3] ;
L = [2, 1, 3] ;
L = [2, 3, 1] ;
L = [1, 3, 2] ;
L = [3, 1, 2] ;
L = [3, 2, 1] .
2 ?- listing(permutation).
lists:permutation([], [], []).
lists:permutation([C|A], D, [_|B]) :-
permutation(A, E, B),
select(C, D, E).
lists:permutation(A, B) :-
permutation(A, B, B).
true.
hope this helps ..
Hint: This is easy to do if you have written a predicate inselt(X,Y,Z), which holds if any insertion of Y into X gives Z:
inselt([E|X], Y, [E|Z]) :- inselt(X,Y,Z).
inselt(X, Y, [Y|X]).
Then comb/3 can be coded recursively using inselt/3.

Resources