Related
I have made a function which in it I call several functions, but when one of them returns false the main function stops and returns false. So is there a way to tell Prolog if the function returns false then skip it and check the rest?
In detail: I am trying to make the 15 puzzle game as a project,
and I want to make function that gives me all the possible next moves.
I end up with calling all the previous functions that controls the blank tile.
next_move(Board, Moves):-
swapup(Board,Result),
swapdown(Board,Result),
swapright(Board,Result),
swapleft(Board,Result).
I want this function to return all the next possible moves
Here is the full code:
position([Tile|_], Tile, 0).
position([_|Tail], Tile, Index):-
position(Tail, Tile, Index1),
Index is Index1+1.
swap(Board,I,J,R) :-
same_length(Board,R),
append(BeforeI,[AtI|PastI],Board),
append(BeforeI,[AtJ|PastI],Bs),
append(BeforeJ,[AtJ|PastJ],Bs),
append(BeforeJ,[AtI|PastJ],R),
length(BeforeI,I),
length(BeforeJ,J).
swapup(Board,Result):-
position(Board,0,Index),
Index \=0,
Index \=1,
Index \=2,
Index \=3,
Up is Index-4,
swap(Board,Up,Index,Result).
swapdown(Board,Result):-
position([],0,Index),
Index \=12,
Index \=13,
Index \=14,
Index \=15,
Down is Index+4,
swap(Board, Down, Index, Result).
swapright(Board,Result):-
position([],0,Index),
Index \=3,
Index \=7,
Index \=11,
Index \=15,
Right is Index+1,
swap(Board, Right, Index, Result).
swapleft(Board,Result):-
position([],0,Index),
Index \=0,
Index \=4,
Index \=8,
Index \=12,
Left is Index-1,
swap(Board, Left, Index, Result).
swap(Board,Result) :- swapup(Board,Result).
swap(Board,Result) :- swapdown(Board,Result).
swap(Board,Result) :- swapright(Board,Result).
swap(Board,Result) :- swapleft(Board,Result).
next_move(Board,Moves) :- findall(Result,swap(Board,Result),Moves).
Here's a simple program:
a.
b :- fail.
c.
g :- a, b, c.
I can ask if g succeeds:
?- g.
false.
It does not.
I can solve this two ways.
(1)
g :- a, b, c.
g :- a, c.
(2)
g :- a, (b; true), c.
Either way, g succeeds now:
?- g.
true.
Update
This is the code you've posted:
next_move(Board, Moves) :-
swapup(Board,Result),
swapdown(Board,Result),
swapright(Board,Result),
swapleft(Board,Result).
On the LHS you have a variable Moves that is not on the RHS. Moves can never be unified and will always remain a variable.
Let's ignore that for a minute and look at the swap predicates.
If I assume that Result is a valid move given the current state of the Board then what your code is saying next_move(Board, Moves) succeeds when each of the swap predicates succeed and that can't happen unless the move you get from each of the swap predicates is the same.
Once swapup(Board,Result) succeeds it will have unified Result with the "swap up" move. Then you ask if swapdown(Board,Result) succeeds. Well, Result isn't a variable anymore so you're asking if the Result you get from swapdown is the same as the Result you get from swapup. I'm guessing it's not.
It's possible that you need something like this:
next_move(Board,[U,D,R,L]):-
swapup(Board,U),
swapdown(Board,D),
swapright(Board,R),
swapleft(Board,L).
But that's not clear because I don't know what value you get when your open space on your board is already at an edge.
It's probably more likely that you need this:
swap(Board,Result) :- swapup(Board,Result).
swap(Board,Result) :- swadown(Board,Result).
swap(Board,Result) :- swapright(Board,Result).
swap(Board,Result) :- swapleft(Board,Result).
next_move(Board,Moves) :- findall(Result,swap(Board,Result),Moves).
But all of this is guessing without seeing your full code.
Here's your code working now. There were a number of issues.
position/3 just simply didn't work.
Here's a version that does:
position(List,Element,Index) :-
position(List,Element,0,Index).
position([Element|_],Element,Index,Index).
position([_|Tail],Element,Counter,Index) :-
Next is Counter + 1,
position(Tail,Element,Next,Index).
You were always calling swap/4 with the same order of the two indices. You have to make sure they go in in ascending order. swap/4 didn't work in any case. Here's the new version:
swap(BoardIn,I,J,BoardOut) :-
position(BoardIn,X,I), % find the value `X` at position `I`
position(BoardIn,Y,J), % find the value `Y` at position `J`
append(Left,[X|MiddleEnd1],BoardIn), % find the list that is `Left` of `X`
append(Middle,[Y|End],MiddleEnd1), % find the `Middle` that is left of `Y` and the list `End` that is to the right of `Y`
append(Middle,[X|End],MiddleEnd2), % put `X` between `Middle` and `End`.
append(Left,[Y|MiddleEnd2],BoardOut). % put the `Y` between `Left` & `Middle`.
I cleaned up the swap*/2 predicates.
swapup(BoardIn,BoardOut):-
position(BoardIn,0,Index),
Up is Index - 4,
Up >= 0,
swap(BoardIn,Up,Index,BoardOut).
swapdown(BoardIn,BoardOut):-
position(BoardIn,0,Index),
Down is Index + 4,
Down =< 15,
swap(BoardIn,Index,Down,BoardOut).
swapright(BoardIn,BoardOut):-
position(BoardIn,0,Index),
Index mod 4 =\= 3,
Right is Index + 1,
swap(BoardIn,Index,Right,BoardOut).
swapleft(BoardIn,BoardOut):-
position(BoardIn,0,Index),
Index mod 4 =\= 0,
Left is Index - 1,
swap(BoardIn,Left,Index,BoardOut).
swap(BoardIn,BoardOut) :- swapup(BoardIn,BoardOut).
swap(BoardIn,BoardOut) :- swapdown(BoardIn,BoardOut).
swap(BoardIn,BoardOut) :- swapright(BoardIn,BoardOut).
swap(BoardIn,BoardOut) :- swapleft(BoardIn,BoardOut).
And finally, here's the next_move/2 predicate:
next_move(BoardIn,Moves) :-
length(BoardIn,16),
position(BoardIn,0,_),
findall(BoardOut,swap(BoardIn,BoardOut),Moves).
Now I can call this query:
?- next_move([1,0,2,3,4,5,6,7,8,9,10,11,12,13,14,15],Result),write(Result).
I get this result:
[[1,5,2,3,4,0,6,7,8,9,10,11,12,13,14,15],[1,2,0,3,4,5,6,7,8,9,10,11,12,13,14,15],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]]
I have two lists:
L1 = [[a,b,c], [e,b,d], [f,g,a]]
L2 = [a,e]
I want to compare L2 with each list in L1 and find the number of common items. I am trying following code:
common([],L).
common([H|T], L, Out):-
intersection(H,L,Out), common(T, L, Out),
length(Out,Len).
However, it is not working:
?- common([[a,b,c], [e,b,d], [f,g,a]], [a,e], Outlist).
false.
The main list remains list in list (as seen after debugging with writeln statements):
L is:
[a,e]
H|T is:
[[f,g,a]]
Outlist = [] .
Where is the problem and how can I correct this?
I edited the code to debug and found that somehow it has started working:
common([],L,Out).
common([H|T], L, Out):-
writeln('------------in common--------------'),
writeln('L is:'), writeln(L),
writeln('H is:'), writeln(H),
intersection(L,H,Out2list),
writeln('Out2list is:'), writeln(Out2list),
common(T, L, Out2).
41 ?- common([[a,b,c], [e,b,d], [f,g,a]], [a,e], Outlist).
------------in common--------------
L is:
[a,e]
H is:
[a,b,c]
Out2list is:
[a]
------------in common--------------
L is:
[a,e]
H is:
[e,b,d]
Out2list is:
[e]
------------in common--------------
L is:
[a,e]
H is:
[f,g,a]
Out2list is:
[a]
true.
First let's observe that you have written a predicate common/2 and a predicate common/3. Reading your question, I assume you intend the former to be the base case for common/3. Thinking about the relation you want to describe, it would make sense to define that the intersection of the empty list and any other list is the empty list:
common([],_,[]).
However, it is not entirely clear what you expect the third argument to be. In your question you write that it should be the number of common items. The use of length/2 in your predicate common/3 supports this interpretation. In this case you want to have the lengths of the respective intersections in the third list:
common([],_,[]).
common([H|T], L, [Len|Out]):- % Len is in the 3rd list
intersection(H,L,I), % I is intersection of H and L
length(I,Len), % Len is length of I
common(T, L, Out). % the same for T, L and Out
With this version your example query yields:
?- common([[a,b,c], [e,b,d], [f,g,a]],[a,e],I).
I = [1,1,1]
In your first comment however, you write that you want Outlist to be [a]. That suggests that you want lists instead of numbers in the third argument. But looking at your example query [a] can not be the answer. On the one hand, if you mean that you want to see all the intersections of the elements of the first list with the second argument, you might like to write something like:
common2([],_,[]).
common2([H|T], L, [I|Out]):- % I is in the third list
intersection(H,L,I), % I is intersection of H and L
common2(T, L, Out). % the same for T, L and Out
This yields with your example:
?- common2([[a,b,c], [e,b,d], [f,g,a]],[a,e],I).
I = [[a],[e],[a]]
On the other hand, if you mean that you want to see the intersection of all the lists of the first argument with the second argument, you might like to go with something like this:
common3([],_,[]). % special case empty list
common3([H|T],L,I) :- % if 1st list not empty
common3_([H|T],L,I). % I is described in common3_/3
common3_([],I,I). % if the list is empty I = Outlist
common3_([H|T], L, O) :-
intersection(H,L,I), % I is intersection of H and L
common3_(T,I,O). % only the elements in I can be in O
With your example lists this yields
?- common3([[a,b,c], [e,b,d], [f,g,a]],[a,e],I).
I = []
since neither a nor e occur in all three lists. But if you add a to the second list:
?- common3([[a,b,c], [e,b,d,a], [f,g,a]],[a,e],I).
I = [a]
puzzling over a problem of trying to return the second to last element in a list written in Prolog. This language is interesting to use but I'm having trouble getting my head wrapped around it. Here is what I have:
secondLast([X], X).
secondLast(X, [Y], X) :- secondLast(Y, K).
secondLast(X, [Y|Z], K) :- secondLast(Y, Z, K).
secondLast([X|Z], Ans) :- secondLast(X, Z, Ans).
so calling secondLast([a, b, c, d], X).
X should equal c.
Any ideas?
Thanks!
you should apply pattern matching:
secondLast([X,_], X).
secondLast([_|T], X) :- secondLast(T, X).
Can be just:
secondLast(L, X) :-
append(_, [X, _], L).
Sergey and CapelliC have offered two nice solutions to the problem. Let's have a look to see what's wrong with the original:
1) secondLast([X], X).
2) secondLast(X, [Y], X) :- secondLast(Y, K).
3) secondLast(X, [Y|Z], K) :- secondLast(Y, Z, K).
4) secondLast([X|Z], Ans) :- secondLast(X, Z, Ans).
In Prolog, since it is about defining relations between entities with predicates, not defining functions, it helps to describe what a predicate means in terms of, "Something is true if some other things are true". The if in Prolog is expressed as :-.
We'll look at clause #4 since this appears to be your main clause. This one says, Ans is the second to last element of [X|Z] if Ans is the second to last element of Z with X as the head. It's unclear what this 3-argument version of secondLast means. However, if the list is 3 or more elements, it seems clear that X will become irrelevant (as will be seen in clauses 2 and 3).
Clause #1 says, X is the second to last element in list [X]. However, the element X is the last and only element in the list [X]. So this clause is logically incorrect.
Clauses #2 is a bit confusing. It introduces a variable in the clause, K, which is only used once and not defined or used anywhere else in the clause. It also ignores X because, as described above, it has become irrelevant since it's no longer a candidate for second-to-last element. Prolog has given you a warning about singleton elements K and X, which is similar to the warning in C that a variable is "defined but never used" or "is assigned a value that is never used". Clause #3 has the same issue.
In all that, I think I can see what you were trying to do, which is to say that, Ans is second to last element of [X|Z] if there's one more element after X, which would be true, but would be limited to being correct if the list [X|Z] is a 2-element list. In other words, your main clause almost assumes that the answer is ultimately X. If it isn't, it attempts to introduce a new candidate, Y in clauses 2 and 3, but this candidate has no way to "make it back" to the original, main clause.
I'll go back now to CapelliC's solution and describe how one comes to it:
1) secondLast([X,_], X).
2) secondLast([_|T], X) :- secondLast(T, X).
The first clause says, X is the second to last element in the 2-element list, [X,_] which is true. And we don't care what the last element is so we just call it, _. We could have called it Y ([X,Y]), but then Prolog would warn about a singleton variable since we don't need or use Y.
The second clause says, X is the second to last element of list [_|T] if X is the second to last element of the tail, T. This is also true of any list that is 3 or more elements. That's fine since the base case, clause one, takes care of the 2-element list. Clause two will, recursively, reduce down to clause one and finally succeed with the right answer. In this second clause, if X is taken from T, then we don't care what the head of the list is since it has become irrelevant, so we use _ as the head in this case (this corresponds to the X in your original clause #4).
In Sergey's answer:
secondLast(L, X) :-
append(_, [X, _], L).
This says, X is second to last element in list L if L is a two element list with X as the first element ([X,_]) appended to the end of some other list (_). Note again that we're using _ for the variables which will have values but we don't care what those values are in this case. So, for example: 2 is the second to last element of [1,2,3] if [1,2,3] is [2,_] appended to some other list and it is: if you append [2,3] to [1] you get [1,2,3].
I am new to prolog , I have a list in prolog like A=[1,2,3,4], and than I accessed nth element using nth(N,[_|T],R). Now I have Nth element in R, than I have done some calculation on R. Now what I want is to update that nth element in list.
Because of I am doing a lot of calculations with each element in list I can't make a new list each time.
I didn't find any method to update list.
With regard to our conversation, you can add two lists together, creating a third, by specifying that the two head elements of the source lists, added together, make the head element of the result list, and that this applies to the remainder of the lists.
There is also a need for a base case, that is, when the two source lists are empty, so should the result list.
addLists([X|A], [Y|B], [Z|C]) :- Z is X+Y, addLists(A, B, C).
addLists([], [], []).
Remember you are always aiming to specify the constraints of the answer, more than the method of answering it. Prolog is very different to other programming languages in that you do not tell it how to do something, you simply tell it conditions that are true for the answer and let it extrapolate it.
From the comments you exchanged with #Orbling seems that what you need is a kind of maplist/4
process_list(A, B, C) :-
maplist(process_elem, A, B, C).
process_elem(A, B, C) :- C is A + B. % or whatever needed
If you are using the index in process_elem then this is not appropriate. Then make a recursive visit of list, passing down the index
process_list(A, B, C) :-
process_list(1, A, B, C).
process_list(I, [A|As], [B|Bs], [C|Cs]) :-
C is A + B * I, % or whatever needed
J is I + 1,
!, process_list(J, As, Bs, Cs).
process_list(_, [], [], []).
edit Just to add to the various ways exposed in answers to the question #Orbling suggests, here a way using nth0/4
?- I = 6, nth0(I,"hello world",_,T), nth0(I,U,0'W,T), format('~s',[U]).
hello World
I am trying to define a function in prolog that takes arguments of the form combination(3,[a,b,c,d],L) , the result returns
L=a,b,c
L=a,b,d
L=a,c,d
L=b,c,d
My implementation is as follows:
combination(K,argList,L):-
unknown(X,argList,Y),
Z is select(X,argList),
length(Z,K),
L is Z,
combination(K,Z,L).
unknown(X,[X|L],L).
unknown(X,[_|L],R) :- unknown(X,L,R).
The unknown predicate behaves as follows:
![enter image description here][1]
Please help.
The simplest solution that comes to mind using your definition of unknown/3 is:
combination(0, _, []) :-
!.
combination(N, L, [V|R]) :-
N > 0,
NN is N - 1,
unknown(V, L, Rem),
combination(NN, Rem, R).
unknown(X,[X|L],L).
unknown(X,[_|L],R) :-
unknown(X,L,R).
Explanation: the second clause of combination/3 looks to select an element from the list L, which the predicate unknown/3 does in a linear manner, returning the remainder, Rem. Once the number of elements selected out of list L exceeds N, the base case is triggered (the first clause of combination/3) which terminates the branch. Note that the definition of combination/3 relies on the non-deterministic nature of unknown/3 which leaves choice-points for selecting alternate list elements.