finding depth of object without use of arithmetics - recursion

Without using arithmetics (=< , =>, etc.)!
I have a few separate piles of blocks, for example two piles.
I need a way to figure out if block A sits Higher on any pile than block B.
For example:
is_on_top(Block1,Pile,Block2). %relations of blocks in a particular pile
for example:
is_bellow(a,1,b). % a is bellow b in pile number 1
is_bellow(r,2,e).
is_bellow(f,2,null). % is at top.
....
and so on.
I'm trying to figure out how to write the predicate:
is_higher(Block1,Block2):- %block1 is higher than block2 in Any line.
% to check for the same line if a block is higher than another I'm this
% is Block1 higher than Block2 in THE SAME pile.
taller(Block1, Block2) :-
is_bellow(Block2,_,Block1).
taller(Block1, Block2) :-
is_bellow(Y, I,Block1),
taller(Y, Block2).
is it possible to do it without using arithmetics?
I think I have the terminating condition.
is_higher(Block1,Block2):-
is_bellow(Block1,_,null), is_bellow(Block2,_,X).
X \= null.
is_higher(Block1,Block2):- % don't know how to continue.

From the comments:
I thought something along the lines of digging deeper on both blocks till block one is paired with null, but I cant quite get my head around it.
You are thinking along the correct lines, but your representation of the world seems to confuse you a bit. It becomes easier if we define a cleaner language for talking about blocks and their relationships.
It would have been good if you had posted a complete example. Here is the one I will be using:
is_below(a, 1, b).
is_below(b, 1, null). % topmost on pile
is_below(c, 2, d).
is_below(d, 2, e).
is_below(e, 2, f).
is_below(f, 2, null). % topmost on pile
I understand this to model the following world:
f
e
b d
a c
-----------------
pile 1 pile 2
Now let's talk about concepts related to this world. First... what even is a block? The representation is implicit, but it appears that a block is something that is on a pile. Being "on a pile" is somewhat implicit too, but it means being below something -- another block, or the special non-block atom null.
So this is a block:
% block(X): X is a block
block(X) :-
is_below(X, _Pile, _BlockOrNull).
Prolog can now enumerate blocks:
?- block(X).
X = a ;
X = b ;
X = c ;
X = d ;
X = e ;
X = f.
Note that null is not included, which is good since it is not a block.
Now, is_below complicates things because it talks about non-blocks (namely, null) and also about the numbers of piles, which we don't always need. Let's define a simpler notion of a block being directly on top of another block:
% block_on(X, Y): X is a block directly on top of block Y
block_on(X, Y) :-
is_below(Y, _Pile, X),
block(X).
Note that we use block(X) to make sure we only talk about blocks. Let's test:
?- block_on(X, Y).
X = b,
Y = a ;
X = d,
Y = c ;
X = e,
Y = d ;
X = f,
Y = e ;
false.
Good. Now, let's define notions for being the topmost and the bottommost block on a pile:
% top(X): X is a block that is topmost on its pile
top(X) :-
block(X),
\+ block_on(_OtherBlock, X). % no other block is on X
% bottom(X): X is a block that is bottommost on its pile
bottom(X) :-
block(X),
\+ block_on(X, _OtherBlock). % X is not on any other block
This behaves like this:
?- top(X).
X = b ;
X = f.
?- bottom(X).
X = a ;
X = c ;
false.
And now we can return to your comment:
I thought something along the lines of digging deeper on both blocks till block one is paired with null, but I cant quite get my head around it.
You were talking about digging (upwards?) until you arrive at a topmost block, but in fact what you should be doing is to dig downwards until you arrive at a bottommost block! Hopefully you can see that it's easier to talk about these concepts now that we have given them clearer names, rather than descriptions like being "paired with null".
Let's start with a non-recursive rule for expressing "higher than". Any non-bottom block is definitely "higher than" any bottom block:
% higher_than(X, Y): X is a block higher on any pile than Y
higher_than(X, Y) :-
bottom(Y),
block(X),
\+ bottom(X).
This already captures a lot of relationships:
?- higher_than(X, Y).
X = b,
Y = a ;
X = d,
Y = a ;
X = e,
Y = a ;
X = f,
Y = a ;
X = b,
Y = c ;
X = d,
Y = c ;
X = e,
Y = c ;
X = f,
Y = c ;
false.
Any non-bottom block (b, d, e, f) is higher than any bottom block (a, c).
Now let's do the "digging" part to express that, for example, f is higher than b. Your idea is correct: If we're at some blocks X and Y, and X is directly on top of some block V and Y is directly on top of some block W, and we can somehow establish that V is higher than W, then X is higher than Y! Here's the same idea expressed in Prolog code:
higher_than(X, Y) :-
block_on(X, V),
block_on(Y, W),
higher_than(V, W).
So is f higher than b?
?- higher_than(f, b).
true ;
false.
Nice. And enumerating all "higher than" pairs:
?- higher_than(X, Y).
X = b,
Y = a ;
X = d,
Y = a ;
X = e,
Y = a ;
X = f,
Y = a ;
X = b,
Y = c ;
X = d,
Y = c ;
X = e,
Y = c ;
X = f,
Y = c ;
X = e,
Y = b ;
X = e,
Y = d ;
X = f,
Y = b ;
X = f,
Y = d ;
X = f,
Y = e ;
false.
Most of these are as before, but we got some new pairs as well: e is higher than b and d, f is higher than b, d, and e. And that is all!
Final remark: I'm not an expert on blocks worlds, but my impression was that it is more usual to model the table top as a special "location" rather than having a special marker for "there is nothing above this".
So I would have represented the same world more like this:
pile_on(1, a, table).
pile_on(1, b, a).
pile_on(2, c, table).
pile_on(2, d, c).
pile_on(2, e, d).
pile_on(2, f, e).
You could switch your code to this representation, maybe it would make your life easier. You could also keep the same higher_than definition -- if you adjust the definitions of block and block_on, all the rest can remain the same.

Assuming is_below( A, P, B) means block A is immediately below block B in some pile P, or is topmost in that pile, with B = null, we can code the is_higher( A, B) predicate exactly as you wanted:
we either have one more step to go down the piles and recurse, or we've reached the bottom of the B pile and judge the situation accordingly:
is_higher( A, B) :- % A is higher than B, if
is_below( A2, _, A), % A is atop one
is_below( B2, _, B), % which is _higher_ than that
A \== B, % which B is atop of
is_higher( A2, B2). % (determined _recursively_)
is_higher( A, B) :- % or,
is_below( _, _, A), % A is not bottommost
is_below( B, _, _), % while B is, because
\+ is_below( _, _, B). % there is nothing below B
%% the world: c
%% b e
%% a d
is_below(a,1,b).
is_below(b,1,c).
is_below(c,1,null).
is_below(d,2,e).
is_below(e,2,null).
Testing:
36 ?- findall( A-B, (is_higher(A,B), A\==null), X).
X = [c-b, c-e, b-a, b-d, c-a, c-d, e-a, e-d].

Related

Count number of vowels in a string using Prolog

I am new in prolog, so i have to explain these code to my class teacher.
can someone please explain this code. Thanks
vowel(X):- member(X,[a,e,i,o,u]).
nr_vowel([],0).
nr_vowel([X|T],N):- vowel(X),nr_vowel(T,N1), N is N1+1,!.
nr_vowel([X|T],N):- nr_vowel(T,N).
output:
1 ?- nr_vowel([a,t,i,k],X).
X = 2.
https://i.stack.imgur.com/dGfU5.jpg
An explanation is indeed highly appropriate.
For example, let us ask the simplest question:
Which solutions are there at all?
Try out out, by posting the most general query where all arguments are fresh variables:
?- nr_vowel(Ls, N).
Ls = [],
N = 0 ;
Ls = [a],
N = 1.
Hm! That's probably not what you wanted to describe!
So I change your code to:
nr_vowel([], 0).
nr_vowel([X|T], N):-
vowel(X),
nr_vowel(T,N1),
N #= N1+1.
nr_vowel([X|T], N):-
nr_vowel(T,N).
Then we get:
?- nr_vowel(Ls, N).
Ls = [],
N = 0 ;
Ls = [a],
N = 1 ;
Ls = [a, a],
N = 2 ;
Ls = [a, a, a],
N = 3 ;
etc.
Looks better!
How about fair enumeration? Let's see:
?- length(Ls, _), nr_vowel(Ls, N).
Ls = [],
N = 0 ;
Ls = [a],
N = 1 ;
Ls = [e],
N = 1 ;
Ls = [i],
N = 1 ;
Ls = [o],
N = 1 ;
Ls = [u],
N = 1 ;
Ls = [_2006],
N = 0 ;
Ls = [a, a],
N = 2 ;
Ls = [a, e],
N = 2 .
The first few answers all look promising, but what about Ls = [_2006], N = 0?
This is clearly too general!
You must make your program more specific to avoid this overly general answer.
Here is the problem in a nutshell:
?- nr_vowel([X], N), X = a.
X = a,
N = 1 ;
X = a,
N = 0.
Whaaat? a is a vowel, so why is N = 0??
Here is it in a smaller nutshell:
?- nr_vowel([a], 0).
true.
Whaaaaat??
I leave adding suitable constraints to the predicate as an exercise for you.
The code is simplistic in itself, all it does is count the number of vowels in a list (Guess that's quite evident to you).
Let's take your input as an example, the list is [a,t,i,k]
When you call nr_vowel([a,t,i,k],Z), prolog searches for and unifies the query with the second nr_vowel clause, this is because it is the first clause with a non-empty list input.
Now, vowel(a) returns true, so prolog moves on to the next predicate, which calls nr_vowel([t,i,k],Z). However this time, when prolog tries to unify it with the second nr_vowel, vowel(t) returns false, so it unifies it with the third clause and behaves similarly until the list is empty.
As soon as the list is empty, prolog unifies Z with 0 and starts coming up the recursion levels and does N=N+1 depending on if the caller predicate had a vowel or not, and as soon as it reaches the top of the recursive chain, Z is unified with the final value of N.
In short -
N=N+1 happens if the head of the list is a vowel
N=N i.e. no change occurs if head of list is NOT a vowel.

Prolog recursing through list of lists

I'm attempting a prolog question that states the following:
A magic square is a 3× 3 matrix of distinct numbers (between 1 and 9) such that all rows and columns add up to the same total (but not necessarily the diagonals). For example:
2 7 6
9 5 1
4 3 8
is a magic square.
We will represent squares in Prolog as 3 × 3 matrices, i.e. lists of lists [R1, R2, R3] where each R_i is a list of three numbers. For example, the
representation of the above magic square is
[[2,7,6],[9,5,1],[4,3,8]]
Define a predicate magic/1 that tests whether a ground 3 × 3 matrix (i.e.
where all the entries are numbers) is a magic square.
I've done this the following way, and I'm pretty sure it's allowed if I also do it like this in an exam, however to me it seems like sort of a hack:
magic([[A,B,C], [D,E,F], [G,H,I]]) :-
Y is A + B + C,
Y is D + E + F,
Y is G + H + I,
Y is A + D + G,
Y is B + E + H,
Y is C + F + I.
My desired way would be to recurse through each list in the outer list, and sum it up. For each of the lists in outer list, they should sum up to the same value (I think 15 is actually the only possible solution for this "magic" matrix). Likewise, I do the same for the columns (take the first, second and 3rd of each list and add up respectively). However, I'm not entirely sure how to do the latter as I haven't been working with list of lists much. I would appreciate if anybody would give a neat solution on how these sort of computations can be done generally.
Thanks
Note that your solution does not check that A, ..,I values are distinct and in the range 1..9. Here is a solution for NxN squares for N > 2:
magic(L) :-
magic_range(L),
magic_sum(S, L),
magic_line(S, L),
transpose(L, T),
magic_line(S, T).
% S value from https://oeis.org/A006003
magic_sum(S, L) :-
length(L, N),
S is N * (N*N + 1) / 2.
magic_range(L) :-
flatten(L, F),
sort(F, S),
length(L, N),
N2 is N * N,
numlist(1, N2, S).
magic_line(_, []).
magic_line(S, [A | As]) :-
sumlist(A, S),
magic_line(S, As).
% https://github.com/SWI-Prolog/swipl-devel/blob/9452af09962000ebb5157fe06169bbf51af5d5c9/library/clp/clpfd.pl#L6411
transpose(Ls, Ts) :-
must_be(list(list), Ls),
lists_transpose(Ls, Ts).
lists_transpose([], []).
lists_transpose([L|Ls], Ts) :-
foldl(transpose_, L, Ts, [L|Ls], _).
transpose_(_, Fs, Lists0, Lists) :-
maplist(list_first_rest, Lists0, Fs, Lists).
list_first_rest([L|Ls], L, Ls).
Some queries
?- magic([[1,1,1],[1,1,1],[1,1,1]]).
false.
?- magic([[2,7,6],[9,5,1],[4,3,8]]).
true ;
false.
?- magic([[16,3,2,13], [5,10,11,8], [9,6,7,12], [4,15,14,1]]).
true ;
false.
The transpose predicate is the most complicated part. See here for some alternatives.

Decompression of a list in prolog

I need to decompress a list in prolog , like in the example below :
decode([[a,1],[b,2],[c,1],[d,3]],L).
L = [a, b, b, c, d, d, d] ;
I made this code :
divide(L,X,Y):-length(X,1),append(X,Y,L).
divide2(L,X,Y):-divide(L,[X|_],[Y|_]).
makelist(_,N,[]):- N =< 0 .
makelist(X,Y,[X|Result]):-Y1 is Y-1,makelist(X,Y1,Result).
makelist2(L,L2):-divide2(L,X,Y),makelist(X,Y,L2).
decode([],[]).
decode([H|T],L):-makelist2(H,H2),append(H2,L,L2),decode(T,L2).
and when i call
makelist2([a,3],L2).
L2 = [a,a,a].
but when i call
decode([[a,3],[b,1],[c,4]],L)
runs continuously. What am i doing wrong ?
Another variation of the theme, using a slightly modified version of Boris' repeat/3 predicate:
% True when L is a list with N repeats of X
repeat([X, N], L) :-
length(L, N),
maplist(=(X), L).
decode(Encoded, Decoded) :-
maplist(repeat, Encoded, Expanded),
flatten(Expanded, Decoded).
If Encode = [[a,1],[b,2],[c,1],[d,3]], then in the above decode/2, the maplist/3 call will yield Expanded = [[a],[b,b],[c],[d,d,d]], and then the flatten/2 call results in Decoded = [a,b,b,c,d,d,d].
In SWI Prolog, instead of flatten/2, you can use append/2 since you only need a "flattening" at one level.
EDIT: Adding a "bidirectional" version, using a little CLPFD:
rle([], []).
rle([X], [[1,X]]).
rle([X,Y|T], [[1,X]|R]) :-
X \== Y, % use dif(X, Y) here, if available
rle([Y|T], R).
rle([X,X|T], [[N,X]|R]) :-
N #= N1 + 1,
rle([X|T], [[N1,X]|R]).
This will yield:
| ?- rle([a,a,a,b,b], L).
L = [[3,a],[2,b]] ? ;
(1 ms) no
| ?- rle(L, [[3,a],[2,b]]).
L = [a,a,a,b,b] ? ;
no
| ?- rle([a,a,a,Y,Y,Z], [X, [N,b],[M,c]]).
M = 1
N = 2
X = [3,a]
Y = b
Z = c ? a
no
| ?- rle([A,B,C], D).
D = [[1,A],[1,B],[1,C]] ? ;
C = B
D = [[1,A],[2,B]] ? ;
B = A
D = [[2,A],[1,C]] ? ;
B = A
C = A
D = [[3,A]] ? ;
(2 ms) no
| ?- rle(A, [B,C]).
A = [D,E]
B = [1,D]
C = [1,E] ? ;
A = [D,E,E]
B = [1,D]
C = [2,E] ? ;
A = [D,E,E,E]
B = [1,D]
C = [3,E] ? ;
...
| ?- rle(A, B).
A = []
B = [] ? ;
A = [C]
B = [[1,C]] ? ;
A = [C,D]
B = [[1,C],[1,D]] ? ;
...
As #mat suggests in his comment, in Prolog implementations that have dif/2, then dif(X,Y) is preferable to X \== Y above.
The problem is in the order of your append and decode in the last clause of decode. Try tracing it, or even better, trace it "by hand" to see what happens.
Another approach: see this answer. So, with repeat/3 defined as:
% True when L is a list with N repeats of X
repeat(X, N, L) :-
length(L, N),
maplist(=(X), L).
You can write your decode/2 as:
decode([], []).
decode([[X,N]|XNs], Decoded) :-
decode(XNs, Decoded_rest),
repeat(X, N, L),
append(L, Decoded_rest, Decoded).
But this is a slightly roundabout way to do it. You could define a difference-list version of repeat/3, called say repeat/4:
repeat(X, N, Reps, Reps_back) :-
( succ(N0, N)
-> Reps = [X|Reps0],
repeat(X, N0, Reps0, Reps_back)
; Reps = Reps_back
).
And then you can use a difference-list version of decode/2, decode_1/3
decode(Encoded, Decoded) :-
decode_1(Encoded, Decoded, []).
decode_1([], Decoded, Decoded).
decode_1([[X,N]|XNs], Decoded, Decoded_back) :-
repeat(X, N, Decoded, Decoded_rest),
decode_1(XNs, Decoded_rest, Decoded_back).
?- decode([[a,1],[b,2],[c,1],[d,3]],L).
L = [a, b, b, c, d, d, d].
?- decode([[a,3],[b,1],[c,0],[d,3]],L).
L = [a, a, a, b, d, d, d].
?- decode([[a,3]],L).
L = [a, a, a].
?- decode([],L).
L = [].
You can deal with both direction with this code :
:- use_module(library(lambda)).
% code from Pascal Bourguignon
packRuns([],[]).
packRuns([X],[[X]]).
packRuns([X|Rest],[XRun|Packed]):-
run(X,Rest,XRun,RRest),
packRuns(RRest,Packed).
run(Var,[],[Var],[]).
run(Var,[Var|LRest],[Var|VRest],RRest):-
run(Var,LRest,VRest,RRest).
run(Var,[Other|RRest],[Var],[Other|RRest]):-
dif(Var,Other).
%end code
pack_1(In, Out) :-
maplist(\X^Y^(X = [V|_],
Y = [V, N],
length(X, N),
maplist(=(V), X)),
In, Out).
decode(In, Out) :-
when((ground(In); ground(Out1)),pack_1(Out1, In)),
packRuns(Out, Out1).
Output :
?- decode([[a,1],[b,2],[c,1],[d,3]],L).
L = [a, b, b, c, d, d, d] .
?- decode(L, [a,b,b,c,d,d,d]).
L = [[a, 1], [b, 2], [c, 1], [d, 3]] .
a compact way:
decode(L,D) :- foldl(expand,L,[],D).
expand([S,N],L,E) :- findall(S,between(1,N,_),T), append(L,T,E).
findall/3 it's the 'old fashioned' Prolog list comprehension facility
decode is a poor name for your predicate: properly done, you predicate should be bi-directional — if you say
decode( [[a,1],[b,2],[c,3]] , L )
You should get
L = [a,b,b,c,c,c].
And if you say
decode( L , [a,b,b,c,c,c] ) .
You should get
L = [[a,1],[b,2],[c,3]].
So I'd use a different name, something like run_length_encoding/2. I might also not use a list to represent individual run lengths as [a,1] is this prolog term: .(a,.(1,[]). Just use a simple term with arity 2 — myself, I like using :/2 since it's defined as an infix operator, so you can simply say a:1.
Try this on for size:
run_length_encoding( [] , [] ) . % the run-length encoding of the empty list is the empty list.
run_length_encoding( [X|Xs] , [R|Rs] ) :- % the run-length encoding of a non-empty list is computed by
rle( Xs , X:1 , T , R ) , % - run-length encoding the prefix of the list
run_length_encoding( T , Rs ) % - and recursively run-length encoding the remainder
. % Easy!
rle( [] , C:N , [] , C:N ) . % - the run is complete when the list is exhausted.
rle( [X|Xs] , C:N , [X|Xs] , C:N ) :- % - the run is complete,
X \= C % - when we encounter a break
. %
rle( [X|Xs] , X:N , T , R ) :- % - the run continues if we haven't seen a break, so....
N1 is N+1 , % - increment the run length,
rle( Xs, X:N1, T, R ) % - and recurse down.
. % Easy!
In direct answer to the original question of, What am I doing wrong?...
When I ran the original code, any expected use case "ran indefinitely" without yielding a result.
Reading through the main predicate:
decode([],[]).
This says that [] is the result of decoding []. Sounds right.
decode([H|T],L) :- makelist2(H,H2), append(H2,L,L2), decode(T,L2).
This says that L is the result of decoding [H|T] if H2 is an expansion of H (which is what makelist2 does... perhaps - we'll go over that below), and H2 appended to this result gives another list L2 which is the decoded form of the original tail T. That doesn't sound correct. If I decode [H|T], I should (1) expand H, (2) decode T giving L2, then (3) append H to L2 giving L.
So the corrected second clause is:
decode([H|T], L) :- makelist2(H, H2), decode(T, L2), append(H2, L2, L).
Note the argument order of append/3 and that the call occurs after the decode of the tail. As Boris pointed out previously, the incorrect order of append and the recursive decode can cause the continuous running without any output as append with more uninstantiated arguments generates a large number of unneeded possibilities before decode can succeed.
But now the result is:
| ?- decode([[a,3]], L).
L = [a,a,a] ? ;
L = [a,a,a,a] ? ;
...
If you try out our other predicates by hand in the Prolog interpreter, you'll find that makelist2/2 has an issue:
It produces the correct result, but also a bunch of incorrect results. Let's have a look at makelist2/2. We can try this predicate by itself and see what happens:
| ?- makelist2([a,3], L).
L = [a,a,a] ? ;
L = [a,a,a,a] ? ;
...
There's an issue: makelist2/2 should only give the first solution, but it keeps going, giving incorrect solutions. Let's look closer at makelist/2:
makelist2(L,L2) :- divide2(L,X,Y), makelist(X,Y,L2).
It takes a list L of the form [A,N], divides it (via divide2/3) into X = A and Y = N, then calls an auxiliary, makelist(X, Y, L2).
makelist(_,N,[]):- N =< 0 .
makelist(X,Y,[X|Result]):-Y1 is Y-1,makelist(X,Y1,Result).
makelist/3 is supposed to generate a list (the third argument) by replicating the first argument the number of times given in the second argument. The second, recursive clause appears to be OK, but has one important flaw: it will succeed even if the value of Y is less than or equal to 0. Therefore, even though a correct solution is found, it keeps succeeding on incorrect solutions because the base case allows the count to be =< 0:
| ?- makelist(a,2,L).
L = [a,a] ? ;
L = [a,a,a] ? ;
We can fix makelist/2 as follows:
makelist(_,N,[]):- N =< 0 .
makelist(X,Y,[X|Result]):- Y > 0, Y1 is Y-1, makelist(X,Y1,Result).
Now the code will generate a correct result. We just needed to fix the second clause of decode/2, and the second clause of makelist/3.
| ?- decode([[a,3],[b,4]], L).
L = [a,a,a,b,b,b,b]
yes
The complete, original code with just these couple of corrections looks like this:
divide(L, X, Y) :- length(X, 1), append(X, Y, L).
divide2(L, X, Y) :- divide(L, [X|_], [Y|_]).
makelist(_, N, []) :- N =< 0 .
makelist(X, Y, [X|Result]) :- Y > 0, Y1 is Y-1, makelist(X,Y1,Result).
makelist2(L, L2) :- divide2(L, X, Y), makelist(X, Y, L2).
decode([], []).
decode([H|T], L) :- makelist2(H,H2), decode(T,L2), append(H2,L2,L).
Note some simple, direct improvements. The predicate, divide2(L, X, Y) takes a list L of two elements and yields each, individual element, X and Y. This predicate is unnecessary because, in Prolog, you can obtain these elements by simple unification: L = [X, Y]. You can try this right in the Prolog interpreter:
| ?- L = [a,3], L = [X,Y].
L = [a,3]
X = a
Y = 3
yes
We can then completely remove the divide/3 and divide2/3 predicates, and replace a call to divide2(L, X, Y) with L = [X,Y] and reduce makelist2/2 to:
makelist2(L, L2) :- L = [X, Y], makelist(X, Y, L2).
Or more simply (because we can do the unification right in the head of the clause):
makelist2([X,Y], L2) :- makelist(X, Y, L2).
You could just remove makelist2/2 and call makelist/2 directly from decode/2 by unifying H directly with its two elements, [X, N]. So the original code simplifies to:
makelist(_, N, []) :- N =< 0 .
makelist(X, Y, [X|Result]) :- Y > 0, Y1 is Y-1, makelist(X,Y1,Result).
decode([], []).
decode([[X,N]|T], L) :- makelist(X, N, H2), decode(T, L2), append(H2, L2, L).
And makelist/3 can be performed a bit more clearly using one of the methods provided in the other answers (e.g., see Boris' repeat/3 predicate).

Prolog - making a recursive divisor

Okay, so I'm a beginner in Prolog so I'm sorry if I can't quite get my question across very clearly but this is where I'm struggling:
divide_by(X, D, I, R) :- (D > X), I is 0, R is X.
divide_by(X, D, I, R) :-
X >= D,
X_1 is X - D,
I_1 is I + 1,
divide_by(X_1, D, I_1, R),
R is X_1.
I'm trying to write a program that will accept two arguments (X and D) and return the Iterations (I) and Remainder (R) so that it can display the result of X / D when the user enters:
divide_by(8,3,I,R). for example.
When tracing the code I know that I is incorrect because the first increment makes it equal to 0 and so the count for that is wrong. But I don't know how to declare I is 0 without it resetting every time it recurses through the loop. (I don't want to declare I as 0 in the query)
I also realised that when it has finished recursing (when X < D) then I is going to be set to 0 because of the base case.
Would anyone be kind enough to show me how I can fix this?
You need to introduce an accumulator and use a helper predicate, something like this:
divide(_,0,_,_) :- !, fail . % X/0 is undefined and so can't be solved.
divide(0,_,0,0) :- !. % 0/X is always 0.
divide(X,Y,Q,R) :- % the ordinary case, simply invoke the
divrem(X,Y,0,Q,R) % helper with the accumulator seeded with 0
.
divrem(X,Y,Q,Q,X) :- % if X < Y, we're done.
X < Y . %
divrem(X,Y,T,Q,R) :- % otherwise...
X >= Y , % as long as X >= Y,
X1 is X - Y , % compute the next X
T1 is T + 1 , % increment the accumulator
divrem(X1,Y,T1,Q,R) % recurse down
. % Easy!

Rectangular Peg Solitaire in Prolog?

possible quick question here since I'm new to Prolog. I'm trying to convert this code for solving a triangular peg solitaire puzzle into solving a rectangular peg solitaire puzzle. The problem I think I'm facing is trying to figure out how to let the program know it completed the puzzle. Here's what I've got currently:
% Legal jumps along a line.
linjmp([x, x, o | T], [o, o, x | T]).
linjmp([o, x, x | T], [x, o, o | T]).
linjmp([H|T1], [H|T2]) :- linjmp(T1,T2).
% Rotate the board
rotate([[A, B, C, D, E, F],
[G, H, I, J, K, L],
[M, N, O, P, Q, R],
[S, T, U, V, W, X]],
[[S, M, G, A],
[T, N, H, B],
[U, O, I, C],
[V, P, J, D],
[W, Q, K, E],
[X, R, L, F]]).
rotateBack([[A, B, C, D],
[E, F, G, H],
[I, J, K, L],
[M, N, O, P],
[Q, R, S, T],
[U, V, W, X]],
[[D, H, L, P, T, X],
[C, G, K, O, S, W],
[B, F, J, N, R, V],
[A, E, I, M, Q, U]]).
% A jump on some line.
horizjmp([A|T],[B|T]) :- linjmp(A,B).
horizjmp([H|T1],[H|T2]) :- horizjmp(T1,T2).
% One legal jump.
jump(B,A) :- horizjmp(B,A).
jump(B,A) :- rotate(B,BR), horizjmp(BR,BRJ), rotateBack(A,BRJ).
%jump(B,A) :- rotate(BR,B), horizjmp(BR,BRJ), rotate(BRJ,A).
% Series of legal boards.
series(From, To, [From, To]) :- jump(From, To).
series(From, To, [From, By | Rest])
:- jump(From, By),
series(By, To, [By | Rest]).
% A solution.
solution(L) :- series([[o, x, x, x, x, x],
[x, x, x, x, x, x],
[x, x, x, x, x, x],
[x, x, x, x, x, x]], L).
The triangular puzzle code required that the user input what the ending table would look like, but I didn't want that. I want this to show any possible solution. The table will always be exactly 6x4. I liked the idea of rotating the grid to continue to simply figure out horizontal jumps, so I changed the rotate function to rotate it's side, and added a RotateBack function to put it back into place. I figured I would have to do this because the grid isn't symmetrical. Since it will always be this size, I figure the simplest way to find the end is to set up a counter that will count how many moves are taken place. Once we hit 22 moves (the max moves possible to clear the whole grid except for 1 peg), then the solution will be a success.
In other words, I think I need to remove this code:
% Series of legal boards.
series(From, To, [From, To]) :- jump(From, To).
series(From, To, [From, By | Rest])
:- jump(From, By),
series(By, To, [By | Rest]).
And change it so that it sets up a counter that stops at 22. Any suggestions?
I think you could count the pegs, or better, fail when there are at least 2.
To do it efficiently, should be (untested code)
finished(L) :-
\+ call_nth(find_peg(L), 2).
find_peg(L) :-
member(R, L),
memberchk(R, x).
call_nth/2, as defined in this answer, requires the builtin nb_setval. This is available in SWI-Prolog or Yap.

Resources