Related
I'm new to Prolog and I have this code. I would like it to split a list into two lists or sublists where the first sublist/ list is of a predefined length and the other one contains the rest of the elements. Here's the code.
`
list_length([],0).
list_length([_|T],N):- list_length(T, N1), N is N1 + 1.
div(L, A, B, N) :-
append(A, B, L),
length(A, N),
length(B, N).
div(L, A, B, N) :-
append(A, B, L),
length(A, N),
N1 is N + 1,
length(B, N1).
div(L, A, B, N) :-
append(A, B, L),
length(A, N),
N1 is N - 1,
length(B, N1).
``
When I run my above code, it returns an error saying:
ERROR: Unknown procedure: (div)/4
ERROR: However, there are definitions for:
ERROR: (div)/3
false.
I would like the input to be this:
`?- div([44,55,23,86,49,94,30,77], L1, L2, 6).
L1 = [44,55,23,86,49,94]
L2 = [30,77]
Help me understand what I am doing wrong.
Help me understand what I am doing wrong.
You should be using length/2 and append/3, one after the other, like this:
div(L, A, B, N) :-
append(A, B, L),
length(A, N).
This is all.
Do not define your own length/2.
But you have not shown how you compile and evaluate your code. For example, I get:
?- [user].
|: div(L, A, B, N) :- append(A, B, L), length(A, N).
|: ^D% user://1 compiled 0.01 sec, 1 clauses
true.
?- div([a,b,c,d], A, B, 2).
A = [a, b],
B = [c, d] ;
false.
?- div([a,b,c,d], [X,Y], B, N).
X = a,
Y = b,
B = [c, d],
N = 2.
?- div([a,b,c,d], A, [X,Y,Z], N).
A = [a],
X = b,
Y = c,
Z = d,
N = 1 ;
false.
?- div([a,b], A, B, N).
A = [],
B = [a, b],
N = 0 ;
A = [a],
B = [b],
N = 1 ;
A = [a, b],
B = [],
N = 2 ;
false.
?- div(L, A, B, N).
L = B,
A = [],
N = 0 ;
L = [_A|B],
A = [_A],
N = 1 ;
L = [_A, _B|B],
A = [_A, _B],
N = 2 .
Since I made that mistake already, it is worth asking: Can you switch the order of append and length in the definition? What happens if you do?
I am trying to implement a partition predicate in Prolog that splits a list into its two halves, a Prefix and a Suffix, of approximately same lengths.
partition(L,P,S)
Where prefixes and suffixes are defined as such:
prefix(P,L) :- append(P,_,L).
suffix(S,L) :- append(_,S,L).
If L is [], then Prefix and S are [].
If L is [H], then P is [H] and S is [].
If L has two or more elements, this is how the list is partitioned into its prefix and suffix:
Length of L is N and the length of P is div(N,2). The length of S is N - div(N,2).
So for instance:
?- partition([a,b,c,d],X,Y).
X = [a,b]
Y = [c,d]
?- partition([a],X,Y).
X = [a]
Y = [ ]
Here is my code and the error I get:
partition([],[],[]).
partition([H],[H],[]).
partition(L, P, S) :-
length(L, N),
Plen is div(N,2),
Slen is N - div(N,2),
length(Pre, Plen),
length(Suff, Slen),
prefix(Pre, L),
suffix(Suff, L),
P is Pre,
S is Suff.
partition([a,b,c,d],X,Y).
>>> Type error: `[]' expected, found `[a,b]' (a list)
("x" must hold one character)
I don't understand this error message but this is wrong:
P is Pre,
S is Suff.
This is for arithmetic evaluation whereby the Right-Hand-Side is evaluated as an arithmetic expression and unified with the Left-Hand-Side.
You just want to unify the variables:
P = Pre,
S = Suff.
Alternatively, you can use the same same for P and Pre / S and Suff throughout.
If you change is to to = as suggested by David Tonhofer's answer, the whole thing works.
But I would like to add that you are complicating things a bit. You have identified correctly that append/3 can be used to compute list prefixes and suffixes. But for any list to be partitioned and any prefix, the suffix is unique, and is already computed by append/3! And the other way round: If you ask it to compute a suffix, it will also compute the prefix you seek. But then you throw these answers away and try to recompute a matching prefix or suffix. There is no need to do that.
If we make your prefix and suffix predicates a bit more explicit:
list_prefix_theonlypossiblematchingsuffix(List, Prefix, TheOnlyPossibleMatchingSuffix) :-
append(Prefix, TheOnlyPossibleMatchingSuffix, List).
list_suffix_theonlypossiblematchingprefix(List, Suffix, TheOnlyPossibleMatchingPrefix) :-
append(TheOnlyPossibleMatchingPrefix, Suffix, List).
We can see that once we have a given prefix for a list, there really is no more choice for the suffix (and vice versa):
?- list_prefix_theonlypossiblematchingsuffix([a, b, c, d], Prefix, MatchingSuffix).
Prefix = [],
MatchingSuffix = [a, b, c, d] ;
Prefix = [a],
MatchingSuffix = [b, c, d] ;
Prefix = [a, b],
MatchingSuffix = [c, d] ;
Prefix = [a, b, c],
MatchingSuffix = [d] ;
Prefix = [a, b, c, d],
MatchingSuffix = [] ;
false.
So there is no need to try to compute the prefix and suffix separately and to match up their lengths. It's enough to restrict the prefix, as the suffix will follow:
partition(List, Prefix, TheOnlyPossibleMatchingSuffix) :-
length(List, N),
PrefixLength is N div 2,
length(Prefix, PrefixLength),
list_prefix_theonlypossiblematchingsuffix(List, Prefix, TheOnlyPossibleMatchingSuffix).
This works as you want:
?- partition([a, b, c, d], Prefix, Suffix).
Prefix = [a, b],
Suffix = [c, d].
?- partition([a, b, c, d, e], Prefix, Suffix).
Prefix = [a, b],
Suffix = [c, d, e].
Once you have this, it's much clearer to replace the goal involving list_prefix_verylongpredicatename with what is really meant:
partition(List, Prefix, Suffix) :-
length(List, N),
PrefixLength is N div 2,
length(Prefix, PrefixLength),
append(Prefix, Suffix, List).
Coming from other programming languages it may be a bit unusual that a predicate like append/3 computes several things at once that have a deep relationship with each other, i.e., a prefix and the unique matching suffix. But this is one of the things that makes Prolog so expressive and powerful. Get used to it and profit from it!
It seems to me that you're doing a lot of unnecessary work here.
This is all I think you need:
partition(L,P,S) :-
partition(L,L,P,S).
partition(L,[],[],L).
partition(([H|L],[_],[H],L).
partition([H|L],[_,_|L2],[H|P],S) :-
partition(L,L2,P,S).
If I query ?- partition([a],X,Y), write([X,Y]). then I get:
[[a], []]
true.
If I query ?- partition([a,b,c,d,e],X,Y), write([X,Y]). then I get:
[[a, b, c], [d, e]]
true.
Since you've already defined your prefixes and suffixes as
prefix(P,L) :- append(P, _, L). % prefix
suffix(S,L) :- append(_, S, L). % suffix
just smash the two together into one call,
partition(L,P,S) :-
append(P, S, L),
and this would be it, except you have additional conditions about the comparative lengths of the two near-halves, so just add them into the mix:
length( P, N), length( A, N), % same length, fresh list A
(A = [_|S] ; A = S). % S one shorter than P, or same length
And that's that. Testing:
2 ?- partition( [1,2,3], A, B ).
A = [1, 2],
B = [3].
3 ?- partition( L, [1,2], [3] ).
L = [1, 2, 3].
15 ?- partition( L, A, B ).
L = A, A = B, B = [] ;
L = A, A = [_G2477],
B = [] ;
L = [_G2477, _G2483],
A = [_G2477],
B = [_G2483] ;
L = [_G2477, _G2483, _G2492],
A = [_G2477, _G2483],
B = [_G2492] ;
L = [_G2477, _G2483, _G2489, _G2492],
A = [_G2477, _G2483],
B = [_G2489, _G2492]
....
I am having trouble starting this Prolog program that takes two lists and returns true if all members in the first list are members of the second list, and false otherwise.
Examples:
?- members([a, c], [a, b, c, d])
true
?- members([d, a, c, a], [a, b, c, d, e])
true
?- members([b, e], [a, b, c, d])
false
?- members([], [a, b, c, d])
true
How do I go about doing this? Any help is appreciated.
You can use maplist on this kind of problem since it follows a standard recursive list traversal:
mem(L, X) :- memberchk(X, L).
subset(S, L) :- maplist(mem(L), S).
Results:
| ?- subset([a,c], [a,b,c,d]).
yes
| ?- subset([c,a], [a,b,c,d]).
yes
| ?- subset([e], [a,b,c,d]).
no
| ?- subset([], [a,b,c,d]).
yes
| ?- subset(S, [a,b,c,d]), S=[_|_].
S = [a] ? ;
S = [a,a] ? ;
S = [a,a,a] ? ;
...
Note that the original problem definition does not rule out the case where the subset can have duplicate elements from the superset. If you want to restrict the subsets to having counts of elements less than or equal to the superset, you can use select/3:
subset([], _).
subset([X|Xs], L) :-
select(X, L, L1),
subset(Xs, L1).
Results:
| ?- subset([a,c], [a,b,c,d,e]).
true ? ;
no
| ?- subset([a,f], [a,b,c,d,e]).
no
| ?- subset([a,a], [a,b,c,d,e]).
no
| ?- subset(S, [a,b,c]), S=[_|_].
S = [a] ? ;
S = [a,b] ? ;
S = [a,b,c] ? ;
S = [a,c] ? ;
S = [a,c,b] ? ;
S = [b] ? ;
S = [b,a] ? ;
...
S = [c,b] ? ;
S = [c,b,a] ? ;
no
You'll note that the list [c,b,a] is considered a different list in Prolog versus [a,b,c] so it is a separate solution. If you want to make the lists behave truly as sets, then that's a different solution.
"We tried nothing and we're all out of ideas"
I would suggest you find a predicate that does that, then look at its implementation.
$ swipl
?- subset([a, c], [a, b, c, d]).
true.
?- subset([d, a, c, a], [a, b, c, d, e]).
true.
?- subset([b, e], [a, b, c, d]).
false.
?- subset([], [a, b, c, d]).
true.
It is documented here: http://www.swi-prolog.org/pldoc/doc_for?object=subset/2
You can click on the little yellow circle with the colon and the dash to see how it is implemented: http://www.swi-prolog.org/pldoc/doc/SWI/library/lists.pl?show=src#subset/2
713 subset([], _) :- !.
714 subset([E|R], Set) :-
715 memberchk(E, Set),
716 subset(R, Set).
This definition is about the same as:
maplist([M]>>memberchk(M, Set), Subset)
This definition always succeeds or fails only once. This is by design.
It could also have been implemented like this:
maplist([M]>>member(M, Set), Subset)
And it behaves like the suggestion in the comments:
?- maplist([M]>>member(M, [a,b]), Subset).
Subset = [] ;
Subset = [a] ;
Subset = [a, a] ;
Subset = [a, a, a] ;
Subset = [a, a, a, a] .
?- length(Subset, _), maplist([M]>>member(M, [a,b]), Subset).
Subset = [] ;
Subset = [a] ;
Subset = [b] ;
Subset = [a, a] ;
Subset = [a, b] ;
Subset = [b, a] ;
Subset = [b, b] ;
Subset = [a, a, a] ;
Subset = [a, a, b] .
I have written the following code to check whether it is a palindrome or not. I have also created the logic to insert elements when the list is not a palindrome
reverse_list(Inputlist, Outputlist) :-
reverse(Inputlist, [], Outputlist).
reverse([], Outputlist, Outputlist).
reverse([Head|Tail], List1, List2) :-
reverse(Tail, [Head|List1], List2).
printList([]).
printList([X|List]) :-
write(X),
write(' '),
printList(List).
palindrome(List1) :-
reverse_list(List1, List2),
compareLists(List1, List1, List2, List2).
compareLists(L1, [], [], L2) :-
write("\nList is Palindrome").
compareLists(L1, [X|List1], [X|List2], L2) :-
compareLists(L1, List1, List2, L2),
!.
compareLists(L1, [X|List1], [Y|List2], [Z|L2]) :-
write("\nList is not Palindrome. "),
append(L1, L2, L),
printList(L).
The code gives the correct output for
palindrome([a,b,c,a]).
List is not Palindrome. a b c a c b a
palindrome([a,b,c]).
List is not Palindrome. a b c b a
However, for an input such as
palindrome([a,b,c,b]).
List is not Palindrome. a b c b c b a
The optimal solution however should be
a b c b a
What changes should I incorporate to be able to achieve this?
The first 3 equations of a DCG capture the palindrome pattern.
Add a fourth, covering the mismatch, to complete the specification:
p([]) --> [].
p([T]) --> [T].
p([T|R]) --> [T], p(P), [T], {append(P,[T],R)}.
p([T|R]) --> [T], p(P), {append(P,[T],R)}.
?- phrase(p(L), [a,b,c,b]).
L = [a, b, c, b, a] ;
L = [a, b, c, c, b, a] ;
L = [a, b, c, b, c, b, a] ;
L = [a, b, c, b, b, c, b, a] ;
false.
I think you need a predicate with two Args, In and Out :
pal([], []).
pal([X], [X]).
pal(In, Out) :-
% first we check if the first and last letter are the same
( append([H|T], [H], In)
% we must check that the middle is a palindrome
-> pal(T, T1),
append([H|T1], [H], Out)
; % if not, we remove the first letter
% and we work with the rest
In = [H|T],
% we compute the palindrome from T
pal(T,T1),
% and we complete the palindrome to
% fit the first letter of the input
append([H|T1], [H], Out)).
EDIT1
This code looks good but there is a bug for
? pal([a,b,c,a], P).
P = [a, b, c, b, a] .
Should be [a,b,c,a,c,b,a]
I'll try to fix it.
EDIT2
Looks correct :
build_pal([H|T], Out):-
pal(T,T1),
append([H|T1], [H], Out).
pal([], []).
pal([X], [X]).
pal(In, Out) :-
( append([H|T], [H], In)
-> pal(T, T1),
( T = T1
-> append([H|T1], [H], Out)
; build_pal(In, Out))
; build_pal(In, Out)).
with output :
?- pal([a,b,c], P).
P = [a, b, c, b, a] .
?- pal([a,b,a], P).
P = [a, b, a] .
?- pal([a,b,c,b], P).
P = [a, b, c, b, a] .
?- pal([a,b,c,a], P).
P = [a, b, c, a, c, b, a] .
?- pal([a,b,a,c,a], P).
P = [a, b, a, c, a, b, a] .
I am new to Prolog and trying to implement a sort of a deep square predicate, which squares all the numbers in the list and also in the sublists. I wrote some sort of a working code but its not giving me the output i expect.
Code:
dsquare([],S).
dsquare([H|T],[R|S]):- number(H), dsquare(T,S), R is H*H, !.
dsquare([H|T],S):- isList(H), dsquare(H,S).
dsquare([H|T],[R|S]) :- dsquare(T,S), R = H, !.
Current Output:
2?- dsquare([[2],4,a],X).
X = [4| _VDHV] ;
X = [[2], 16, a| _VDNM] ;
fail.
Expected Output:
X = [[4], 16, a]
Also i wanted to know why am i getting those '_VDHV' and '_VDNM' in my output.
Any help would be much appreciated.
Edit:
ok so I updated my code as:
dsquare([],[]).
dsquare([H|T],[R|S]):- number(H), R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]):- isList(H), dsquare(H,R), dsquare(T,S).
dsquare([H|T],[R|S]) :- R=H, dsquare(T,S).
but the output that I get is:
13?- dsquare([a,3,[[2]],b,4],X).
X = [a, 9, [[4]], b, 16] ;
X = [a, 9, [[4]], b, 4] ;
X = [a, 9, [[2]], b, 16] ;
X = [a, 9, [[2]], b, 4] ;
X = [a, 9, [[2]], b, 16] ;
X = [a, 9, [[2]], b, 4] ;
X = [a, 9, [[2]], b, 16] ;
X = [a, 9, [[2]], b, 4] ;
X = [a, 3, [[4]], b, 16] ;
X = [a, 3, [[4]], b, 4] ;
X = [a, 3, [[2]], b, 16] ;
X = [a, 3, [[2]], b, 4] ;
X = [a, 3, [[2]], b, 16] ;
X = [a, 3, [[2]], b, 4] ;
X = [a, 3, [[2]], b, 16] ;
X = [a, 3, [[2]], b, 4] ;
fail.
I have no clue how it gets so many results.
Edit
finally the working solution is
dsquare([],[]).
dsquare([H|T],[R|S]) :- number(H), !, R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]) :- isList(H), !, dsquare(H,R), dsquare(T,S).
dsquare([H|T],[H|S]) :- dsquare(T,S).
your Prolog should warn you about a 'singleton' in your first and third rules.
Try
dsquare([],[]).
...
dsquare([H|T],[S|R]):- isList(H), dsquare(H,S), dsquare(T,R).
OT don't place cuts without a motivated reason.
edit you get more results beacuse the last rule get fired on backtracking. Now could be the time to place the cuts where needed (i.e. after the code entered a branch guarded by a condition):
dsquare([],[]).
dsquare([H|T],[R|S]) :- number(H), !, R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]) :- isList(H), !, dsquare(H,R), dsquare(T,S).
dsquare([H|T],[R|S]) :- R=H, dsquare(T,S).
or consider a refactoring that accounts for repeated code:
dsquare([],[]).
dsquare([H|T],[R|S]) :-
( number(H)
-> R is H*H
; isList(H)
-> dsquare(H,R)
; R=H
),
dsquare(T,S).
edit the above definition (I tested that with 'if/then/else') seems fine:
1 ?- dsquare([[2],4,a],X).
X = [[4], 16, a].
2 ?- dsquare([a,[3],[[[5]]],[2],a],X).
X = [a, [9], [[[25]]], [4], a].
The _Vxxx bits are prolog's representation of an unbound variable in the result. Basically, it's key or address in the symbol table.
In your first rule,
dsquare([],S).
you're never binding anything to the second argument. That means if you invoke it as dsquare([],X), X will remain unbound. And if invoked as dsquare([1,2,3],X) (assuming everything else was working properly, the resulting list structure would be broken and X would be something like [1,2,3|_VD3DC], since the very last item would be neither the atome [] (the empty list) or ./2, the structue that is a non-empty list.
In your second rule,
dsquare([H|T],[R|S]):- number(H), dsquare(T,S), R is H*H, !.
The cut (!) is unnecessary
your order of operators in incorrect. Square H first, then recurse down. That accomplishes two things: it (A) fails early (if the result is bound), and (B) allows tail-recursion optimization to be applied.
In your 3rd rule,
dsquare([H|T],S):- isList(H), dsquare(H,S).
You are recursing down on the sublist that is the head of the source list, but not evaluating the tail of the source list at all and instead simply discard it.
In your 4th rule,
dsquare([H|T],[R|S]) :- dsquare(T,S), R = H, !.
again, as in your second rule, the cut is unneeded and the order of operations reversed.
I'd write it something like this:
deep_square( [] , [] ) % squaring an empty list produces an empty list
.
deep_square( [X|Xs] , [Y|Ys] ) :- % otherwise...
number(X) , % if the head is a number,
Y is X*X , % square it
deep_square(Xs,Ys) % and recurse down
. %
deep_square( [X|Xs] , [Y|Ys] ) :- % otherwise...
nonvar(X) , % if the head is bound,
X = [_|_] , % and is a non-empty list.
deep_square( X , Y ) , % deep square the head
deep_square( Xs , Ys ) % and then recurse down
.
deep_square( [X|Xs] , [X|Ys] ) :- % otherwise the head is unbound or something other than a number or a non-empty list...
deep_square( Xs , Ys ) % recurse down.
. % Easy!
You'll notice that there is a lot of unification magick and suchlike that happens in the heads of the clauses of a prolog predicate.