Prolog - Matrix equation - prolog
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].
Related
How to obtain ALL the combinations with repetition of the elements of a list - prolog
I'm trying to get all the combinations with repetition of all the elements in a list L . These elements need to be returned in a size N list. (L, N, CWR). The expected result would be something like: ?-([red,blue,green], 2 , X). X = [red, red] ; X = [red, blue] ; X = [red, green] ; X = [blue, blue] ; X = [blue, green] ; X = [blue, red] ; X = [green, green] ; X = [green, blue] ; X = [green, red] ; false.
Taking a higher-level view: combinations_( L, N, R) :- length( R, N), maplist( flip(member,L), R). flip( P, L, X):- call(P, X, L). We just create a list of length N and fill it up with all the elements of L one after another. I first saw flip on RosettaCode's Zebra Puzzle page.
This works in SWI-Prolog: all_combos(_, 0, []). all_combos(L, N, [H|T]) :- length([H|T], N), N1 is N - 1, member(H, L), all_combos(L, N1, T).
This is a good start : ?- [user] . % consulting user_input... :- op(2'1,'yfx','of') . ( _yO_ of _Xs_ ) :- ( ( [] = _Xs_ ; ) ; ( [_yO_|_xS_] = _Xs_ ) ; ( [_|_xS_] = _Xs_ , _yO_ of _xS_ ) ) . %^D% % consulting user_query... ?- _Xs_ = ['red','green','blue'] , _pO_ of _Xs_ , _qO_ of _Xs_ , Ys = [_pO_,_qO_] . Ys = [red,red] ? ; Ys = [red,green] ? ; Ys = [red,blue] ? ; Ys = [red,_qO_] ? ; Ys = [green,red] ? ; Ys = [green,green] ? ; Ys = [green,blue] ? ; Ys = [green,_qO_] ? ; Ys = [blue,red] ? ; Ys = [blue,green] ? ; Ys = [blue,blue] ? ; Ys = [blue,_qO_] ? ; Ys = [_pO_,red] ? ; Ys = [_pO_,green] ? ; Ys = [_pO_,blue] ? ; Ys = [_pO_,_qO_] ? ; false ?-
recursive Prolog predicate?
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.
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