I've been trying to teach myself Prolog for a few weeks. Right now I'm trying to find all ways to make a large integer from several smaller integers, using a predicate partition/3 that I want to work like:
| ?- partition(4, [1, 2, 3], X).
X = [1, 1, 1, 1] ? ;
X = [1, 1, 2] ? ;
X = [1, 3] ? ;
X = [2, 2] ? ;
no
thus finding all ways to make 4 from 1, 2 and 3. Duplicate solutions like [1, 2, 1] and [2, 1, 1] are fine but probably not hard to avoid. Here's what I have right now:
partition(N, _, []) :- N = 0.
partition(N, [], _) :- fail.
partition(N, [IH|IT], [OH|OT]) :-
N =< 0, fail;
N > IH, M is N-IH, OH = IH,
partition(M, [IH|IT], OT).
% if the first input IH can be subtracted from N,
% do so into M and push IH into the output list [OH|OT]
partition(N, [_|IT], Output) :-
N =< 0, fail;
partition(N, IT, Output).
% after trying the first input term, try the others
The idea is that N will eventually become zero, and the subtractions that got it there will be placed in the third argument as a list. The third and fourth rules only operate on positive integers, the second rule says not to run out of inputs, and the first rule signals that the partition is valid when N reaches zero. Problem is, I only get:
| ?- partition(4, [1, 2, 3], X).
no
The first and second rules make sense to me, the third and fourth seem iffy but I can't find anything specifically wrong with them. I thought that the output tail OT might not get instantiated when M becomes zero, but the first rule takes care of that. Or is there some fundamental misunderstanding of how Prolog works (which seems likely to happen often for me)?
Also, are the N =< 0, fail; parts redundant? They seem redundant but I can't be sure until I get something that works.
Edit: I'm using GNU Prolog.
You have one issue here, with the comparison of N to IH:
partition(N, [IH|IT], [OH|OT]) :-
N =< 0, fail;
N > IH, [...]
It should be N >= IH.
Consider your example partition(4, [1, 2, 3], X):
It matches predicate 3, which in turn checks partition(3,[1,2,3],OT)
partition(3,[1,2,3],OT) matches the third predicate, that checks partition(2,[1,2,3],OT).
partition(2,[1,2,3],OT) matches the third predicate, that checks partition(1,[1,2,3],OT).
partition(1,[1,2,3],OT) matches the fourth predicate, since 1 > 1 fails. Checks partition(1,[2,3],OT).
partition(1,[2,3],OT) will match the fourth predicate to the end, and fail when the list is empty.
Related
My goal is to put 1 in the list if the corresponding number is odd, put 0 otherwise.
even(X):- 0 is mod(X,2).
odd(X):- 1 is mod(X,2).
%This is used to determine even or odd.
determine([X|Xs],L):-
even(X),append(L,0,K),
determine(Xs,K).
determine([X|Xs],L):-
odd(X),append(L,1,K).
determine(Xs,K).
The ideal output is:
determine([1,2,3,4,5],K).
K=[1,0,1,0,1].
I know my current approach is very wrong, but I can't come up with an idea.
If you want to make use of your predicates odd and even, this
is a possible solution:
determine([], []).
determine([H|T], [1|T2]) :-
odd(H),
determine(T,T2).
determine([H|T], [0|T2]) :-
even(H),
determine(T,T2).
I would prefer this, though:
determine2([], []).
determine2([H|T], [R|T2]) :-
R is mod(H,2),
determine2(T,T2).
There are several approaches, here I show you two. The first is the simplest (no need to use append/2):
even_odd(A,R):- ( 0 is mod(A,2) -> R = 0; R = 1).
test([],[]).
test([H|T],[R|T1]):-
even_odd(H,R),
test(T,T1).
?- test([1,2,3,4,5],L).
L = [1, 0, 1, 0, 1]
Or you can use maplist/3, in a more compact way
?- maplist(even_odd,[1,2,3,4,5],L).
L = [1, 0, 1, 0, 1]
I'm working on a prolog algorithm that will perform a "swap" on a list.
Example:
Input: [1,2,3,4] -> Output: [3,4,1,2]
Input: [1,2,3,4,5] -> Output: [4,5,3,1,2]
The first half and second half of the list swap places, if there is an odd number then the center element retains it's position. I have come up with an algorithm, but I am getting an error:
?- swap([1,2,3,4],L).
ERROR: length/2: Type error: `integer' expected, found `round(4/2)'
My code is as follows:
swap(L, S) :-
length(L, Length),
reverse(L, L2),
mixing(L, Length, A),
trim(L2, Length/2 , B),
append(A,B,S).
trim(L,N,S) :-
length(P,N),
append(P,S,L).
mixing(L, Length, A) :-
( mod(Length, 2) == 0
-> trim(L, round(Length/2), A)
; trim(L, round(Length/2), A)
).
The problem is that in 'mixing' when I call trim (L, round(Length/2), A) the type is not integer? I understand that Length/2 is not an integer (most likely a float) and I thought round was equivalent to integer(expr) which rounds and transforms the data type to an integer. I also tried replacing round with the truncate(expr) and integer(expr), but I was receiving the same errors. Can someone explain what I'm doing wrong?
Prolog doesn't do inline expression evaluation. Thus, calls such as trim(L2, Length/2 , B) and trim(L, round(Length/2), A) will not work as you expect. Expressions are only evaluated in specific when using certain operators such as is/2, arithmetic comparisons, or their CLP(FD) counterparts. These expressions would need to be done as: L is Length // 2, trim(L2, L, B) and R is round(Length/2), trim(L, R, A) if done literally.
Your solution could be condensed, however, as follows.
swap(L, S) :-
same_length(L, S), % L and S are necessarily the same length
length(L, N),
M is N // 2, % integer divide ; half the original list length
length(Left, M), % Left is a list of half the length of L
% or half minus one if the length is odd
( (N mod 2) =:= 1 % If the original length is odd...
-> append(Left, [H|Right], L), % then L is Left + [H|Right]
append(Right, [H|Left], S) % So, S is Right + [H|Left]
; append(Left, Right, L), % otherwise, L is Left + Right
append(Right, Left, S) % So, S is Right + Left
).
round is not a function, it's a predicate. I haven't looked at the rest of the code, but that line should be
round(Length/2, R), trim(L, R, A)
EDIT: BTW, you're overthinking it.
swap([], []).
swap([X], [X]).
swap([X, Y | A], [Y, X | B]) :- swap(A, B).
Here's another solution that is based upon a modification to a predicate posted by #joel76 for splitting a list into two equal length lists. The modification I made enables the predicate to succeed with an odd-length list by including the "middle" list of 0 or 1 elements as an argument. It also uses same_length to constrain the arguments to avoid a termination issue for certain arguments. I included a simple implementation of same_length/2 which not all Prologs have (it is included with SWI Prolog).
swap(L, S) :-
same_length(L, S),
div(L, Front, Middle, Back), % L is divided into two halfs & middle
append(Back, Middle, NewFront), % S is Back + Middle + Front
append(NewFront, Front, S).
% List L consists of Left + Middle + Right where Left and Right are equal length
% and Middle has maximum length of 1
%
div(L, Left, Middle, Right) :-
split(L, L, Left, Middle, Right).
split(L, [], [], [], L).
split([H|T], [_], [], [H], T).
split([H|T], [_, _|T1], [H|T2], M, Right) :-
split(T, T1, T2, M, Right).
% same_length/2 is pre-defined in SWI Prolog and succeeds if the arguments
% are lists of equal length
%
same_length([], []).
same_length([_|Xs], [_|Ys]) :- same_length(Xs, Ys).
an idiomatic solution:
swap(L,S) :-
%maplist(when_, [
append([X,C,Y],L), (C=[];C=[_]), same_length(X,Y),
reverse(X,U), reverse(Y,V), append([U,C,V],S)
%])
.
?- swap([1,2,3,4,5],S).
S = [2, 1, 3, 5, 4] ;
false.
it's not a true relation, since it hangs if called in mode swap(-,+), but it behaves better after uncommenting the bracketing, and providing this snippet:
:- meta_predicate when_(0).
when_(P) :-
strip_module(P,_,Q), Q =.. [_|As],
or_list(As, Exp), display(Exp),
when(Exp, P).
or_list([A], ground(A)) :- !.
or_list([A|As], (ground(A);Exp)) :- or_list(As, Exp).
edit
after #false' comments, I'm trying to explain the motivation of this answer. The requested swap/2 'function' seems to be an ideal candidate to showcase the peculiarity of Prolog data model, albeit the requested explanation (about proper syntactic usage of integer arithmetic applied to lists) is not even hinted here.
From the very start of Prolog we have available an unique mixing of relational and functional (recursive) tools, that could make little sense to a newbie. At least, it still surprises me... and I like this fact.
Now, functional logic programming, for instance Curry, attempts a solution through 'narrowing'. From the linked page:
Narrowing is useful because it allows a function to be treated as a relation: its value can be computed "in both directions"
Now, when_/1 it's a simple minded approach to the same problem. Down to earth, the swap/2 has been described as a function, but could be implemented as a relation ?
#false suggestion, adding same_length(L,S) as first goal, fixes the swap(-,+) mode, but loops on swap(-,-). The approach based on when_/1 instead reports the inability to ground the conjunction.
edit
Termination issues apart, my choice of goals order is really ineffective. Hinting this answer to another question, occurred to me that a big efficiency gain (at least, for the mode swap(+,-)) can be obtained putting constraints first:
3 ?- numlist(1,100,L), time((append([X,C,Y],L), (C=[];C=[_]), same_length(X,Y), append([Y,C,X], S))).
% 328,899 inferences, 0.125 CPU in 0.125 seconds (100% CPU, 2634422 Lips)
L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
X = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
C = [],
Y = [51, 52, 53, 54, 55, 56, 57, 58, 59|...],
S = [51, 52, 53, 54, 55, 56, 57, 58, 59|...]
.
4 ?- numlist(1,100,L), time(((C=[];C=[_]), same_length(X,Y), append([X,C,Y],L), append([Y,C,X], S))).
% 3,273 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 3210999 Lips)
I am trying to write the predicate rowN/3 which returns the n-th element (in this case row) of a matrix.
Example:
?- rowN([[1,2],[3,4],[5,6]], 2, R).
R = [3,4];
No
I am struggling with the counter. I have tried unsuccessfully to find some pretty similar examples. So far I've managed to write this:
Code:
rowN(L,[],[]).
rowN([],X,[]).
rowN([],[],[].
rowN([H|T],X,R) :-
A==X,
A is A + 1,
rowI(T,A,H).
This line does not make much sense:
rowN(L,[],[]).
because the second argument is an integer (if I understand correctly), and you use a list. This is the case with nearly all your arguments. Furthermore you use RowI in your recursive call?
Solution
A solution is to first specify that the first row (I = 1), is equal to the head of the matrix:
rowN([H|_],1,H).
next you need to find an iterative way to enumerate through your matrix. So the header is definitely something of the form:
rowN([H|T],I,X) :-
# ...
Now we will assume that I is not equal to 1 (we will discuss this topic later). In that case we need to traverse the matrix further, so we will take the tail and set the counter I one back. This can be done using:
rowN([_|T],I,X) :-
I1 is I-1,
rowN(T,I1,X).
So our predicate reads:
rowN([H|_],1,H).
rowN([_|T],I,X) :-
I1 is I-1,
rowN(T,I1,X).
Now if you use this predicate, it will give the correct result:
?- rowN([[1,2],[3,4],[5,6]], 2, R).
R = [3, 4] ;
false.
The question is why does the predicate does not generate other results: after showing the first result, for rowN([[1,2],[3,4],[5,6]], 2, R) :- rowN([[3,4],[5,6]],1,[3,4])., it could try to find alternatives. It does so by using the second clause, but then it will eventually run out of rows and call for the rowN([],_,_) predicate, since not of the clauses match, it will fail.
This solution is not perfect: it does not work in all directions correctly, which is in general hard in Prolog. That's why good Prolog programmers have written libraries.
Using swi-prolog's builtin nth1/3
Instead of reinventing the wheel, you can make use of the nth1/3 predicate in swi-prolog. Although the arguments are swapped - you need to call it like nth1(2,[[1,2],[3,4],[5,6]],R). - it has the advantage that it works in more directions that what most people can come up in an fast solution, it is with near certainty bugfree (because it has been tested billions of times by all Prolog programs that use the predicate) and some of these builtins are implemented in C++ making them sometimes faster. For instance:
?- nth1(2, [[1,2],[3,4],[5,6]], R).
R = [3, 4].
?- nth1(I, [[1,2],[3,4],[5,6]], [5,6]).
I = 3.
?- nth1(I, [[1,2],[3,4],[5,6]], R).
I = 1,
R = [1, 2] ;
I = 2,
R = [3, 4] ;
I = 3,
R = [5, 6].
?- nth1(I,M,[2,3]).
I = 1,
M = [[2, 3]|_G23] ;
I = 2,
M = [_G22, [2, 3]|_G26] ;
I = 3,
M = [_G22, _G25, [2, 3]|_G29] ;
I = 4,
M = [_G22, _G25, _G28, [2, 3]|_G32] .
You can thus ask what the second row is, ask where the row [5,6] is located, make the query more generic by answering with tuples of the index I and the row R and generate a matrix with a row [2,3] somewhere.
I'm trying to write a Prolog predicate that can decomposes a given non-negative integer into every possible sum, using a DCG.
For example:
?- s(3, L, []).
L = [3] ? ;
L = [2,1] ? ;
L = [1,2] ? ;
L = [1,1,1] ? ;
false.
I started by writing a predicate which takes a number N and returns L = [1,2,3,...,N]:
mkList(N, L) :-
m(0, N, L).
m(X, X, []).
m(Y, L, [H|T]) :-
H is Y+1,
m(H, L, T).
However, I'm not sure how I can proceed.
s(Input) -->
{ mkList(Input, InputList) },
{ member(X, InputList) },
[X].
This is what I was going to use, it starts out my running through the list one by one. However, I'm not sure where I should include a rule to find the difference between X and Input.
the base case is easy:
all_sum(N) --> [N].
now, we can call recursively if we provide a M between 1 and N, and take the rest R (beware it must be > 0)
all_sum(N) --> {...},[M],all_sum(R).
please fill the dots using the hints above.
You will get
?- phrase(all_sum(3),L).
L = [3] ;
L = [1, 2] ;
L = [1, 1, 1] ;
L = [2, 1] ;
false.
The best way to proceed is to think like Prolog, that is, recursively. Yes, you've got recursion. It may even be right, but I'm not following it.
Thinking like this should work:
mkList(Number,List) :-
pick a number between 1 and number. It'll be your first addend.
subtract it from number to get the remainder.
make a recursive call to handle the remainder.
patch together List based on the first addend and the list from the recursive call.
Obviously we need to stop when Number is less than 1.
This doesn't use a DCG, but for the life of me I can't see how a DCG is relevant here.
I have to create list of n elements for example,
do_list(5,L1).
should return,
L1=[1,2,3,4,5].
This is what I have, but it's not working.
do_list(X,L1):- X1 is X-1, do_list(X1,[X1|L1]).
do_list(0,[]).
If you want to create a list of consecutive numbers from 1 to N you can use builtin predicates findall/3 and between/3 this way:
do_list(N, L):-
findall(Num, between(1, N, Num), L).
?- do_list(5,L).
L = [1, 2, 3, 4, 5].
SWI also has another builtin which does just that, numlist/3:
?- numlist(1,5,L).
L = [1, 2, 3, 4, 5].
There are three problems with your code. The first problem is that you add X1 to the list in the clause body, but you never pass the new list back towards the head of the clause. I.e., L1 is an accumulator variable, but you need a third argument that will be bound to the final list.
The second is that the second clause only matches if the input list is empty. This will never be the case, since you add X1 to the list before calling do_list/2 recursively. I.e., you don't have a recursion anchor, and the goal ?- do_list(5,L) will never return.
The third problem is that you add X1 to the list instead of X. You'd skip the largest number.
This is how it should work:
do_list(N, L) :- do_list1(N, [], L).
do_list1(0, L, L) :- !.
do_list1(N, R, L) :- N > 0, N1 is N-1, do_list1(N1, [N|R], L).
Or if you don't want to use any built-in function (like me, when I tried this as a practice and then run into this question), you can use this (working but not effective) solution:
connect([],X,X).
connect([H|T],C,[H|T2]) :- connect(T,C,T2).
revert([],[]).
revert([H|T],R) :- revert(T,Trev), connect(Trev,[H],R)
do_revlist(0,[]).
do_revlist(X,[X|L]) :- X1 is X-1, do_revlist(X1,L).
do_list(X,L2) :- do_revlist(X,L), revert(L,L2).
P.S. Works only for positive integers.
Another solution similar to that of twinterer but without cut or predefined predicates, employing an accumulator.
do_List(Max,L) :- do_ListAcc(1,Max,L). % call Accumulator
do_ListAcc(N,N,[N]). % N=:=N ends recursion
do_ListAcc(Min,Max,[Min|Succs]) :-
Next is Min + 1,
do_ListAcc(Next,Max,Succs).
This also works only for positive integers.