Prolog kenken solver 4 by 4 - prolog

so i am trying to solve kenken using prolog but i ran into several problems from the start, first of all lets say i run it like kenken([X1,X2,X3,.....X16]). and i want to solve for this x's with rules i defined before. so lets say the first cell has 3 values X1,X2,and X3 and i want to get 2 by using multiplication meaning that X1*X2*X3=2, now how do i set up a rule to see all posible solutions if i had something like that.
also how would i tell my x's to only use a range of values 1-4.
i tried to do something like
:- use_module(library(clpr)).
solve([X1,X2,X3]):-
{X1*X2*X3=2}.
but its gives me a really weird output.

Since you reason over integers, not floats, consider using library(clpfd) instead of CLP(R). In SICStus, SWI and YAP, you can constrain a finite domain variable X to the integer range 1-4 with:
X in 1..4
You can use the built-in predicate label/1 to search for concrete solutions. Example with SWI-Prolog:
?- Vars = [A,B,C], A*B*C #= 2, Vars ins 1..4, label(Vars).
yielding:
Vars = [1, 1, 2], A = B, B = 1, C = 2 ;
Vars = [1, 2, 1], A = C, C = 1, B = 2 ;
Vars = [2, 1, 1], A = 2, B = C, C = 1.

You need the is operator to do arithmetic:
2 is X1*X2*X3
Note that this will not work unless the X's are all bound to numbers.

Related

Prolog list of list n number with condition

I'm studying prolog language and i have an issue regarding this problem.
I've already created a program that, given a number N, returns a list with elements between 0 and N:
list2val(N,L):- list2val(0,N,L).
list2val(N,N,[N]).
list2val(C,N,[C|T]):-
C<N,
N1 is C+1,
list2val(N1,N,T).
?- list2val(5,X).
X = [0,1,2,3,4,5]
Now i'm trying to give an extension that, given a list, returns a list of lists in which every list is list2val only if the next number is greater than current number. In this case:
?- newFuction([1,5,2,3,9],L).
L = [[0,1],[0,1,2,],[0,1,2,3]]
My code is this, but somethings is wrong:
array(X):- array(X,_L).
array([],_L).
array([H|[T|Ts]],L1):-
H<T,
list2val(H,L2),
array([T|Ts],[L1|[L2]]).
array([T|Ts],L1).
Maybe could be too much difficult to understand but using a list L = [1,5,2,3,9] i do those steps:
check 1<5 so i create a 1 list2val until 1..in this case [0,1]
check 5<2 i dont create nothing.
check 2<3 i create list2val of 2 ...[0,1,2]
and so on...
I don't want use a standard predicates, by implement with standard terms.
A solution for your problem could be:
list2val(N,L):- list2val(0,N,L).
list2val(N,N,[N]):- !.
list2val(C,N,[C|T]):-
C<N,
N1 is C+1,
list2val(N1,N,T).
simulate([_],[]).
simulate([A,B|T],[H|T1]):-
( A < B ->
list2val(A,H),
simulate([B|T],T1);
simulate([B|T],[H|T1])
).
Using a predicate like simulate/2, you can solve your problem: it compares two numbers of the list and then create a new list in case the condition is satisfied.
?- simulate([1,5,2,3,9],LO).
LO = [[0, 1], [0, 1, 2], [0, 1, 2, 3]]
false

How can I replace a list in Prolog?

I think it's very easy but I have no idea how to do that.
I tried by attribuition, doing a list receive another list but don't work.
% H is the head of a coordenate and T the tail
% E is the element that will be placed in the position T
findLine([L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10],H,T,E,NewTray) :-
H is 1,replace(L1,T,E,N),L1 = N;
H is 2,replace(L2,T,E,N),L2 = N;
...
H is 10,replace(L10,T,E,N),L10 = N;
NewTray = [L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10].
I need that L1 be the N in this clause, I don't know how I can create a clause to modify the L1 inside the clause findLine. I thought in create clause to remove all elements and add the new ones one by one and call this at the attribuition place:
%L is the list, C a counter and N the new list
rewrite(L,C,N) :-
Q is C,
removeByIndex(Q,L,R),
(Q \== 0 -> rewrite(R,Q-1,N), !.
removeByIndex(0,[_|T],T):- !.
removeByIndex(I,[H|T],R):- X is I - 1, removeByIndex(X, T, Y), insert(H, Y, R).
But I continous with the same problem: the L1 are not modified :(
The idea is modify a line and replace on the tray.
PS: I'm sorry for my english, but the prolog topics are almost inative in the portuguese forum
I'm really unsure what you're trying to accomplish here, but I can point to a few things that strike me as symptoms of a misunderstanding.
First of all, you bind all the variables at the top and then you have essentially a bottom-out else case that looks like this:
NewTray = [L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10].
Well, you never assign to NewTray in any of your other cases, so NewTray is going to be uninstantiated most of the time. That does not seem likely to be what you intend to me.
Second, your cases have this structure:
H is 1,replace(L1,T,E,N),L1 = N;
First mistake here is that H is 1; is/2 is for evaluating arithmetic expressions; there's no difference between this and H = 1, and the equivalence of L1 and N means that this whole predicate could probably be written as:
findLine([L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10],1,T,E,_) :-
replace(L1,T,E,L1).
findLine([L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10],2,T,E,_) :-
replace(L2,T,E,L2).
findLine(Line, _, _, Line).
I'm still confused by what you're trying to do, looking at that.
I suspect that you think L1 will have some value on the way into the relation and suddenly have a new, different value after the relation is used. That is emphatically not the case: variables in Prolog are bound exactly once; your assignment L1 = N or whatever is not going to cause L1 to "receive a new value" (because such a thing cannot happen in Prolog); instead it informs Prolog that L1 and N should be bound to the same value. What this means depends on circumstances; if they are both ground and not equal it will cause your predicate to fail, for instance, but if either of them is non-ground they will accept the value of the other.
I'm looking at what you're doing here and I can't help but think that you're essentially trying to do this:
replace([], _, _, []).
replace([H|T], 1, X, [X|T]).
replace([H|T], N, X, [H|Replaced]) :-
N > 1, succ(N0, N), replace(T, N0, X, Replaced).
Use it like this:
?- replace([1,2,3,4,5], 3, foo, Result).
Result = [1, 2, foo, 4, 5]
I just can't for the life of me figure out what you're trying to do, and I don't know why you're bothering to bind all the variables in your list at once if you don't need them all at once.
Anyway, I hope this helps! Maybe if you show us more of what you're trying to do it will be more clear how we can help.
Edit: Elaboration on = and unification
Let's mess around with = and see what happens:
?- X = 3.
X = 3.
Probably nothing surprising about this.
?- 3 = X.
X = 3.
Unification is different from assignment. As you can see, it is not directional. This line would not have worked in any other language.
?- X = [1,Y,3].
X = [1, Y, 3].
Notice that Prolog has no issues with having variables remain free.
?- X = [1,Y,3], Y = 2.
X = [1, 2, 3],
Y = 2.
Now, because Y is the same in both positions, when you bound Y to 2, the middle value in X became 2 as well. There are data structures unique to Prolog that make use of this feature (difference lists).
?- X = [1,Y,3], Q = X, Q = [1,2,3].
X = Q, Q = [1, 2, 3],
Y = 2.
Now what makes this interesting is that we did not explicitly tell Prolog that Y is 2. Prolog inferred this by unification. You can see some more examples of that here:
?- X = [H|T], H = 3, T = [4,5].
X = [3, 4, 5],
H = 3,
T = [4, 5].
So here we said, X is composed of H and T and then told it what H and T are. But Prolog's unification doesn't care much about the order you do things:
?- X = [H|T], X = [1,2,3].
X = [1, 2, 3],
H = 1,
T = [2, 3].
Unification is transitive.
So what happens when Prolog cannot unify?
?- X = [1,Y,3], Q = X, Q = [1,2,3], Y = 4.
false.
Y has to be 2 for the first step, but it has to be 4 for the last step. Once a variable is bound, there's no changing it. This is just a more complex way of saying:
?- X = 2, X = 4.
false.
Prolog does not have "assignables", just variables.

Define the predicate Prolog

I'm reviewing some exercise for the coming test and having difficulty at this.
Given a list of integers L, define the predicate: add(L,S) which returns a list of integers S in which each element is the sum of all the elements in L up to the same position.
Example:
?- add([1,2,3,4,5],S).
S = [1,3,6,10,15].
So my question is what define the predicate means? It looks pretty general. I've read some threads but they did not provide much. Thanks!
This is a good exercise to familiarize yourself with two important Prolog concepts:
declarative integer arithmetic to reason about integers in all directions
meta-predicates to shorten your code.
We start with a very simple relation, relating an integer I and a sum of integers S0 to a new sum S:
sum_(I, S0, S) :- S #= S0 + I.
Depending on your Prolog system, you may need a directive like:
:- use_module(library(clpfd)).
to use declarative integer arithmetic.
Second, there is a powerful family of meta-predicates (see meta-predicate) called scanl/N, which are described in Richard O'Keefe's Prolog library proposal, and already implemented in some systems. In our case, we only need scanl/4.
Example query:
?- scanl(sum_, [1,2,3,4,5], 0, Sums).
Sums = [0, 1, 3, 6, 10, 15].
Done!
In fact, more than done, because we can use this in all directions, for example:
?- scanl(sum_, Is, 0, Sums).
Is = [],
Sums = [0] ;
Is = [_2540],
Sums = [0, _2540],
_2540 in inf..sup ;
Is = [_3008, _3014],
Sums = [0, _3008, _3044],
_3008+_3014#=_3044 ;
etc.
This is what we expect from a truly relational solution!
Note also the occurrence of 0 as the first element in the list of partial sums. It satisfies your textual description of the task, but not the example you posted. I leave aligning these as an exercise.
Define the predicate simply means write a predicate that does what the question requires.
In your question you have to write the definition of add/2 predicate( "/2" means that it has two arguments). You could write the definition below:
add(L,S):- add1(L,0,S).
add1([],_,[]).
add1([H|T],Sum,[H1|T1]):- H1 is Sum+H,NSum is Sum+H,add1(T,NSum,T1).
The above predicate gives you the desired output. A simple example:
?- add([1,2,3,4,5],S).
S = [1, 3, 6, 10, 15].
I think the above or something similar predicate is what someone would wait to see in a test.
Some additional information-issues
The problem with the predicate above is that if you query for example:
?- add(S,L).
S = L, L = [] ;
ERROR: is/2: Arguments are not sufficiently instantiated
As you see when you try to ask when your predicate succeeds it gives an obvious solutions and for further solutions it throws an error. This is not a very good-desired property. You could improve that by using module CLPFD:
:- use_module(library(clpfd)).
add(L,S):- add1(L,0,S).
add1([],_,[]).
add1([H|T],Sum,[H1|T1]):- H1 #= Sum+H,NSum #= Sum+H,add1(T,NSum,T1).
Now some querying:
?- add([1,2,3,4,5],S).
S = [1, 3, 6, 10, 15].
?- add(S,[1,3,6]).
S = [1, 2, 3].
?- add(S,L).
S = L, L = [] ;
S = L, L = [_G1007],
_G1007 in inf..sup ;
S = [_G1282, _G1285],
L = [_G1282, _G1297],
_G1282+_G1285#=_G1307,
_G1282+_G1285#=_G1297 ;
...and goes on..
As you can see now the predicate is in the position to give any information you ask! That's because now it has a more relational behavior instead of the functional behavior that it had before due to is/2 predicate. (These are some more information to improve the predicate's behavior. For the test you might not be allowed to use libraries etc... so you may write just a simple solution that at least answers the question).

Deep Reverse in PROLOG - Lists

Hey I'm trying to create a predicate for the generating of a deep reverse on nested Lists in PROLOG.
Currently I got this predicate
reverse(L,A) :- rev(L,[], A).
rev([],A,A).
rev([H|L],R,A) :- rev(L,[H|R],A).
The result looks like this:
reverse([1,2,3],A).
A = [3, 2, 1].
reverse([[0,1],2,3],A).
A = [3, 2, [0, 1]].
The problem is, that the inner List is not reversed. It should look like this:
reverse([[0,1],2,3],A).
A = [3, 2, [1, 0]].
reverse([1,2,[3,4,5,[6,7],8],[9,10],11,12],A).
A = [12,11,[10,9],[8,[7,6],5,4,3],2,1].
Thanks for any help.
The way you represent your data is called defaulty, because you need a default case when reasoning over it:
is it a list? &rightarrow; something holds
otherwise &rightarrow; something else holds.
Such a representation is a rich source of troubles. Consider for example my_reverse/2 from the other answer. The main problem with it is that it prematurely and incorrectly commits to one of the cases, although both cases are still possible:
?- my_reverse([X], Ls).
Ls = [X].
But this answer only holds for the case where X is not a list! This problem leads to the following strange behaviour of the predicate:
?- my_reverse([X], Ls), X = [1,2,3].
Ls = [[1, 2, 3]],
X = [1, 2, 3].
This mean that even though X is a list, its elements are not reversed!
You should always aim for cleaner representations to distinguish the cases that can arise.
For example, what would you say about the following way to represent your data:
list(Ls) represents the list Ls
n(N) represents the number N.
With such a representations, we can distinguish the cases symbolically. I leave this as the starting point for a more declarative solution.
To keep things as simple as possible, we could add a test if the current element being checked is a list or not. If it is indeed a list, then its elements should be reversed as well. So in code:
my_reverse(L,R) :- rev(L,[],R).
rev([],A,A).
rev([H|T],A,R) :-
( is_list(H) -> % If H is a list
rev(H,[],X), % then reverse H as well
rev(T,[X|A],R)
;
rev(T,[H|A],R)
).
Also, not that it really matters, just to try and avoid confusion, note how I used A and R for respectively Accumulator and Result. In your code they are currently swapped, which -for me personally- can be a bit confusing, especially when predicates become longer and more complex.
Anyway, let's look at the queries you provided:
?- my_reverse([[0,1],2,3],R).
R = [3, 2, [1, 0]].
?- my_reverse([1,2,[3,4,5,[6,7],8],[9,10],11,12],R).
R = [12, 11, [10, 9], [8, [7, 6], 5, 4, 3], 2, 1].
And some general queries:
?- my_reverse(L,R).
L = R, R = [] ;
L = R, R = [_G2437] ;
L = [_G2437, _G2443],
R = [_G2443, _G2437] ;
L = [_G2437, _G2443, _G2449],
R = [_G2449, _G2443, _G2437] ;
L = [_G2437, _G2443, _G2449, _G2455],
R = [_G2455, _G2449, _G2443, _G2437]
...
?- my_reverse([[X,Y]|T],R), member(a,T), length(X,2).
X = [_G2588, _G2591],
T = [a],
R = [a, [Y, [_G2588, _G2591]]]
;
X = [_G2594, _G2597],
T = [a, _G2588],
R = [_G2588, a, [Y, [_G2594, _G2597]]]
;
X = [_G2594, _G2597],
T = [_G2582, a],
R = [a, _G2582, [Y, [_G2594, _G2597]]]
...
Note however that using this predicate, no termination occurs after finding the first answer to the query:
?- my_reverse(X,[X]).
X = [X] ;
...
But since this wasn't a requirement/demand in OP's question, I assumed it to be okay.
EDIT:
Please read #mat's answer as a follow-up to this problem.
an additional solution for your problem is to use cut and the built-in predicate "is_list/1" to check if you treat a simple term or a list in the current call.
here is the code:
deepReverse(List,R):-deepReverseTail(List,[],R).
deepReverseTail([],Acc,Acc).
deepReverseTail([H|T],Acc,R):- % when H is a list
is_list(H), % check if it's a list.
!, % cut the process if not.
deepReverseTail(H,[],Hrev), % reverse this current list
deepReverseTail(T,[Hrev|Acc],R). % continue the general recursion
deepReverseTail([H|T],Acc,R):- deepReverseTail(T,[H|Acc],R). % when H is a simple term
the "cut" in the third line make sure you treat only list in this definition, while treating simple terms will be in the next definitions.
an output example:
7 ?- deepReverse([a,[d,f],[],[[k],g]],R)
R = [[g, [k]], [], [f, d], a].

Prolog - descending order list

I am trying to write a function - decListRange(X,List) which give a list in range [X-1:1] by descending order. For example -
decListRange(9,List).
Will give -
List = [8,7,6,5,4,3,2,1].
I tried the following but it goes into infinite loop -
decListRange(1,[]) :- !.
decListRange(X,[H|Rest]) :-
H = X-1, NextX = X - 1 ,decListRange(NextX,Rest).
You have two problems. The first real one is that you need to use is instead of =:
H is X-1
This is needed to trigger arithmetic evaluation. Your second problem isn't a real problem but speaks to a bigger misunderstanding, which is that H and NextX are equivalent. Because Prolog only has bindings and not "assignables" as it were, you should never really need to create two "variables" with the same binding. There's no state being kept around for you to modify later.
Cleaning up both you get this:
decListRange(1, []) :- !.
decListRange(X, [H|Rest]) :-
X > 1,
H is X-1,
decListRange(H, Rest).
Edit 2: a clpfd implementation
:- use_module(library(clpfd)).
declist(N, L) :- N == 1, !, L = []. % green cut
declist(1, []).
declist(N, [N1|Ns]) :-
N #> 1,
N1 #= N - 1,
declist(N1, Ns).
This one has the properties #false mentions below in the comments:
?- declist(3, L).
L = [2, 1] ;
false.
?- declist(3, [2,1]).
true ;
false.
?- declist(N, [3,2,1]).
N = 4.
?- declist(N, X).
N = 1,
X = [] ;
N = 2,
X = [1] ;
N = 3,
X = [2, 1] ;
N = 4,
X = [3, 2, 1] ;
N = 5,
X = [4, 3, 2, 1] .
Edit: a short interlude on the difference between = and is.
In procedural languages = is almost always syntax for assigning a particular value to a variable. In Prolog, variables are bindings, and once established they cannot be directly modified by reassigning the variable a different value. Instead they work more like variables in math and logic, where the variable "stands in" for interesting values, but those values are themselves basically immutable. In Prolog, = essentially asks the unification engine to establish bindings. So if you were to do something like this:
?- name(X, Y) = name(bob, tony).
Prolog responds with variable bindings:
X = bob,
Y = tony.
Once those bindings exist, contradictory bindings will fail and affirmative bindings will succeed:
?- name(X, Y) = name(bob, tony), X = bob.
X = bob,
Y = tony.
?- name(X, Y) = name(bob, tony), X = william.
false.
The unification algorithm itself doesn't know anything about arithmetic. This has the pleasant side-effect that you can use any expression raw. For instance:
?- Expr = X + 3, Z + Q = Expr.
Expr = Z+3,
X = Z,
Q = 3.
This is probably really surprising looking. You may expect that somehow Prolog was smart enough to keep the expression around because it noticed X was a variable or something, but that isn't true either:
?- X = 4, Expr = X + 3, Z + Q = Expr.
X = 4,
Expr = 4+3,
Z = 4,
Q = 3.
Another way of looking at this is that Prolog is considering + to be just another operator, so X+3 is a fact just like add(X, 3) that doesn't necessarily have any special meaning. Whichever way you look at it, the is/2 operator exists to apply arithmetic reasoning and produce a value:
?- X = 4, Expr is X + 3.
X = 4,
Expr = 7.
Notice that Expr has the computed value but none of the original structure:
?- X = 4, Expr is X + 3, Z + Q = Expr.
false.
In practice, if you need to do a lot of reasoning with arithmetic, you will want to use a library like clpfd or clpqr depending on whether you're interested in integers or reals. This library enables you to do more interesting things more easily, like specify that an equation holds for values in a certain range and get those values out.

Resources