Related
For an input like extract_column([[1,2], [3, 4], [5,6]], 0, X)., I'd like to see the result as [1,3,5]. I'm not sure if my base case is correct or how to proceed with the recursive logic.
The point is to get the Ith element of the header (list), append it to the result list R and recursively apply that logic to all of the lists inside the big list.
extract_column([], [R1]).
extract_column([H|T], I, [R]) :-
extract_column([T], I, [R1]),
nth0(I, [H], num1),
append([R], num1, R1).
Indeed, the base case is not correct and furthermore there is no need to use append/3.
The base case should define a predicate of arity 3 (i.e., with arguments Matrix, Index, Column).
To add an element Y to the beginning of a list Ys, just write [Y|Ys].
For more efficiency, it's better to use tail recursion (moving the recursive call to the end of the clause).
Thus, a possible solution is:
extract_column([], _, []).
extract_column([X|Xs], I, [Y|Ys]) :-
nth0(I, X, Y),
extract_column(Xs, I, Ys).
Examples:
?- extract_column( [[1,2], [3, 4], [5,6]], 0, Col).
Col = [1, 3, 5].
?- extract_column( [[1,2], [3, 4], [5,6]], I, Col).
I = 0,
Col = [1, 3, 5] ;
I = 1,
Col= [2, 4, 6].
I have just started programing in Prolog, using tkeclipse. What I want to do, is to replace an element of the list with another element on the first place that it occurs. However, when I press the more button (;) I want the query to return also the other solutions. Example:
?- replace(1,a,[1,2,3],R).
R = [a, 2, 3]
Yes
?- replace(1,a,[1,2,1,1,3],R).
R = [a, 2, 1, 1, 3] ;
R = [1, 2, a, 1, 3] ;
R = [1, 2, 1, a, 3] ;
No
What I wrote so far, works fine, but in the end, after [1,2,1,a,3], I also get [1,2,1,1,3] instead of no. My code is as follows:
%%% replace/4
replace(_,_,[],[]).
replace(X,Y,[X|T],[Y|T]).
replace(X,Y,[H|T],[H|T2]) :-
replace(X,Y,T,T2).
Just delete the first clause
replace(_,_,[],[]).
and you should be fine.
You [1,2,1,1,3] because:
replace(1,a,[1,2,1,1,3],[1,2,1,1,3]) is successful by
always taking the third clause, reducing the pre-replacement-list and the result-of-the-replacement list element by element
succeeding on the empty list by taking the first clause
You want:
Success on the empty list (0 replacements); and also
A stream of of exactly-one-replacements
And so:
replace(_,_,[],[]) :- !. % make this deterministic with a a cut
replace(X,Y,PreList,PostList) :-
replace_2(X,Y,PreList,PostList).
% replace_2/4 is the same as replace/4 but does NOT succeed for the empty list
replace_2(X,Y,[X|T],[Y|T]).
replace_2(X,Y,[H|T],[H|T2]) :-
replace_2(X,Y,T,T2).
And so:
?- replace(1,a,[1,2,3],R).
R = [a, 2, 3] ;
false.
?- replace(1,a,[1,2,1,1,3],R).
R = [a, 2, 1, 1, 3] ;
R = [1, 2, a, 1, 3] ;
R = [1, 2, 1, a, 3] ;
false.
?- replace(foo,a,[1,2,1,1,3],R).
false.
?- replace(foo,a,[],R).
R = [] ;
false.
I have a list with an unknown number of zeros at the beginning of it, for example [0, 0, 0, 1, 2, 0, 3]. I need this list to be stripped of leading zeros, so that it would look like [1, 2, 0 , 3].
Here's what I have:
lead([Head | _], _) :- Head =\= 0.
lead([0 | Tail], _) :-
lead(Tail, Tail).
The output of which is simply True. Reading the trace shows that it is running until it has a list with no leading zeros, but then the answer doesn't propagate back up the stack. I'm pretty new to Prolog, so I can't figure out how to make it do that.
Here is a solution that works in all directions:
lead([],[]).
lead([H|T],[H|T]) :-
dif(H,0).
lead([0|T],T2) :-
lead(T,T2).
Some queries:
?- lead([0,0,0,1,2,0,3], L).
L = [1, 2, 0, 3] ;
false.
?- lead(L, []).
L = [] ;
L = [0] ;
L = [0, 0] ;
L = [0, 0, 0] ;
...
?- lead(L0, L).
L0 = L, L = [] ;
L0 = L, L = [_G489|_G490],
dif(_G489, 0) ;
L0 = [0],
L = [] ;
L0 = [0, _G495|_G496],
L = [_G495|_G496],
dif(_G495, 0) ;
L0 = [0, 0],
L = [] ;
L0 = [0, 0, _G501|_G502],
L = [_G501|_G502],
dif(_G501, 0) ;
L0 = [0, 0, 0],
L = [] ;
...
EDIT This predicate actually doesn't work for e.g. lead(L0, [0,1,2]).
With library(reif):
:- use_module(reif).
remove_leading_zeros([], []).
remove_leading_zeros([H|T], Rest) :-
if_( H = 0,
remove_leading_zeros(T, Rest),
Rest = [H|T]).
Then:
?- remove_leading_zeros([0,0,0,1,2,0,3], R).
R = [1, 2, 0, 3].
?- remove_leading_zeros([2,0,3], R).
R = [2, 0, 3].
?- remove_leading_zeros(L, R).
L = R, R = [] ;
L = [0],
R = [] ;
L = [0, 0],
R = [] ;
L = [0, 0, 0],
R = [] . % and so on
Here is a solution that actually works for all possible inputs and doesn't leave unnecessary choice points:
lead(L0, L) :-
( nonvar(L),
L = [H|_] ->
dif(H,0)
;
true
),
lead_(L0, L).
lead_([], []).
lead_([H|T], L) :-
if_(H \= 0,
L = [H|T],
lead_(T,L)).
The initial check for nonvar(L) is the only solution I have been able to come up with that would prevent problems with e.g. lead(L0, [0,1,2,3]), while retaining the behavior of the predicate in all other situations.
This uses if_/3, part of library(reif)
if_(If_1, Then_0, Else_0) :-
call(If_1, T),
( T == true -> Then_0
; T == false -> Else_0
; nonvar(T) -> throw(error(type_error(boolean,T),
type_error(call(If_1,T),2,boolean,T)))
; throw(error(instantiation_error,instantiation_error(call(If_1,T),2)))
).
This also uses (\=)/3, that I came up with by simple modification of (=)/3 in library(reif).
\=(X, Y, T) :-
( X \= Y -> T = true
; X == Y -> T = false
; T = true, dif(X, Y)
; T = false,
X = Y
).
Some queries
?- lead([0,0,0,1,2,0,3],L). % No choice point
L = [1, 2, 0, 3].
?- lead([1,2,0,3],L).
L = [1, 2, 0, 3].
?- lead([0,0,0,0],L).
L = [].
?- lead([],L).
L = [].
?- lead(L0,[0,1,2,0,3]). % Correctly fails
false.
?- lead(L0,[1,2,0,3]).
L0 = [1, 2, 0, 3] ;
L0 = [0, 1, 2, 0, 3] ;
L0 = [0, 0, 1, 2, 0, 3] ;
…
?- lead(L0,L). % Exhaustively enumerates all cases:
L0 = L, L = [] ; % - LO empty
L0 = L, L = [_G2611|_G2612], % - L0 contains no leading 0
dif(_G2611, 0) ;
L0 = [0], % - L0 = [0]
L = [] ;
L0 = [0, _G2629|_G2630], % - L0 contains one leading 0
L = [_G2629|_G2630],
dif(_G2629, 0) ;
L0 = [0, 0], % - L0 = [0, 0]
L = [] ;
L0 = [0, 0, _G2647|_G2648], % - L0 contains two leading 0s
L = [_G2647|_G2648],
dif(_G2647, 0) ;
… % etc.
Here is a solution that doesn't generate any choice points. Its
using freeze/2, in a way that is not anticipated by dif/2. But using
freeze/2 here is quite appropriate, since one rule of thumb for freeze/2
is as follows:
Rule of Thumb for freeze/2: Use freeze/2 where the predicate would
generate uninstantiated solutions and a lot of choice points. The hope
is that a subsequent goal will specify the solution more, and the
freeze/2 will be woken up. Unfortunately doesn't work with CLP(FD) or
dif/2, since freeze/2 does not react to refinements implied by CLP(FD)
or dif/2, only unification will wake it up.
The code is thus:
lead(X, Y) :- var(X), !, freeze(X, lead(X,Y)).
lead([X|Y], Z) :- var(X), !, freeze(X, lead([X|Y],Z)).
lead([0|X], Y) :- !, lead(X, Y).
lead(X, X).
Here are some sample runs (SWI-Prolog without some import, Jekejeke Prolog use Minlog Extension and ?- use_module(library(term/suspend))):
?- lead([0,0,0,1,2,3], X).
X = [1, 2, 3].
?- lead([0,0|X], Y).
freeze(X, lead(X, Y)).
?- lead([0,0|X], Y), X = [0,1,2,3].
X = [0, 1, 2, 3],
Y = [1, 2, 3].
?- lead([Z,0|X], Y), X = [0,1,2,3].
X = [0, 1, 2, 3],
freeze(Z, lead([Z, 0, 0, 1, 2, 3], Y)).
?- lead([Z,0|X], Y), X = [0,1,2,3], Z = 0.
Z = 0,
X = [0, 1, 2, 3],
Y = [1, 2, 3].
In the above lead/2 implemetation only the first argument is handled. To handle multiple arguments simultaneously the predicate when/2 can be used. But for simplicity this is not shown here.
Also when using suspended goals, one might need a labeling like predicate at the end, since suspended goals cannot detect inconsistency among them.
The problem in your code is that the second parameter, your output, is specified as _, so your predicate is true for any output. What you want is a predicate that is true if and only if it is the input minus leading zeroes.
lead([], []).
lead([0 | Tail], Tail2) :- !, lead(Tail, Tail2).
lead([Head | Tail], [Head | Tail]) :- Head =\= 0.
The ! in the first line is optional. It prunes the search tree so Prolog does not consider the second line (which would fail) if the first line matches.
Here's how I'd phrase it. First, establish constraints: either X or Y must be bound to a list. Anything else fails.
If X is bound, we don't care about Y: it can be bound or unbound. We just strip any leading zeros from X and unify the results with Y. This path has a single possible solution.
If X is unbound and Y is bound, we shift into generative mode. This path has an infinite number of possible solutions.
The code:
strip_leading_zeros(X,Y) :- listish(X), !, rmv0( X , Y ) .
strip_leading_zeros(X,Y) :- listish(Y), !, add0( Y , X ) .
rmv0( [] , [] ) .
rmv0( [D|Ds] , R ) :- D \= 0 -> R = [D|Ds] ; rmv0(Ds,R) .
add0( X , X ) .
add0( X , Y ) :- add0([0|X],Y ) .
listish/1 is a simple shallow test for listish-ness. Use is_list/1 if you want to be pedantic about things.
listish( L ) :- var(L), !, fail.
listish( [] ) .
listish( [_|_] ) .
Edited to note: is_list/1 traverses the entire list to ensure that it is testing is a properly constructed list, that is, a ./2 term, whose right-hand child is itself either another ./2 term or the atom [] (which denotes the empty list). If the list is long, this can be an expensive operation.
So, something like [a,b,c] is a proper list and is actually this term: .(a,.(b,.(c,[]))). Something like [a,b|32] is not a proper list: it is the term .(a,.(b,32)).
Hi I want to write a function called perfect_part that takes a list of integers as input and if possible, return two sub-lists whose sum is exactly half of the total values of all integers in original list.
For example,
?- perfect_part([6, 3, 2, 1], L, R).
L = [6],
R = [3, 2, 1] ;
false.
?- perfect_part([1, 2, 3, 4, 0], L, R).
L = [1, 4],
R = [2, 3, 0] ;
L = [2, 3],
R = [1, 4, 0] ;
Here is my try:
listsum([], 0).
listsum([H|T], Total):-
listsum(T, Sum1),
Total is H + Sum1.
subset([],L).
subset([X|T],L):- member(X,L),subset(T,L).
perfect_part([], 0, 0).
perfect_part(Nums, Left, Right):-
listsum(Nums, S),
H is S / 2,
subset(Left, Nums),
subset(Right, Nums),
listsum(Left, H),
listsum(Right, H).
But if I run it, I got error message:
ERROR: is/2: Arguments are not sufficiently instantiated
How can I fix it? Am I on the right track to sovle this problem?
The predicate subset/2 is missing, and it's an essential part to answer your question. Specifically, if sublists are contiguous, you can solve as easily as
perfect_part(X,L,R) :- append(L,R,X), listsum(L,S), listsum(R,S).
Then I would look for a more adequate replacement for append/3, like
partition([],[],[]).
partition([H|T],[H|L],R) :- partition(T,L,R).
partition([H|T],L,[H|R]) :- partition(T,L,R).
that leads to
perfect_part(X,L,R) :- partition(X,L,R), listsum(L,S), listsum(R,S).
edit Now, from subset/2 it's apparent the error cause: in base case, L is unbound.
Should be subset([],[])., but it doesn't terminate. I wonder how you get the error...
more edit To avoid duplicate solutions, I suggest to break the symmetry with
perfect_part(X,L,R) :- partition(X,L,R), L #=< R, listsum(L,S), listsum(R,S).
I want to access list permutation and pass it as argument to other functions.
This is the permutation code:
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :-
takeout(X,R,S),
write(S).
perm([X|Y],Z) :-
perm(Y,W),
takeout(X,Z,W).
perm([],[]).
To start with, let's redefine your predicates so they don't do any unnecessary I/O:
takeout(X,[X|R],R).
takeout(X,[F |R],[F|S]) :- takeout(X,R,S).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
Now you have what could be considered a "pure" permutation function:
?- perm([1,2,3], X).
X = [1, 2, 3] ;
X = [2, 1, 3] ;
X = [2, 3, 1] ;
X = [1, 3, 2] ;
X = [3, 1, 2] ;
X = [3, 2, 1] ;
false.
So, suppose you have a max_heap function that takes a list of values and produces a tree. I'll let you worry about that, so let's just posit that it exists and is called max_heap/2 and let's further posit that you have a way to display this attractively called display_heap/1. To "take" the permutation and "send" it as a parameter to these functions, you're really saying in math-ese: suppose P is a permutation of X, let's make a max_heap with it and display it. Or, suppose P is a permutation of X, H is a max heap made from X, let's display H:
show_heaps(List) :- perm(List, P), max_heap(P, H), display_heap(H).
This says the same thing as my English sentence: suppose P is a permutation of the list, then H is a heap representation of it, then display it. Technically, display_heap/1 is still a predicate which could be true or false for a given heap. In practice, it will always be true, and if you run this you'll still have to hit ; repeatedly to say, give me another solution, unless you use a failure-driven loop or an extralogical predicate like findall/3 to cause all the solutions to be found.
Edit: Let's discuss failure-driven loops and findall/3. First let me add some new predicates, because I don't know exactly what you're doing, but it doesn't matter for our purposes.
double([X|Xs], [Y|Ys]) :- Y is X*2, double(Xs, Ys).
double([],[]).
showlist(Xs) :- print(Xs).
So now I have a predicate double/2 which doubles the values in the list and a predicate showlist/1 that prints the list on standard output. We can try it out like so:
?- perm([1,2,3], X), double(X, Y), showlist(Y).
[2,4,6]
X = [1, 2, 3],
Y = [2, 4, 6] ;
[4,2,6]
X = [2, 1, 3],
Y = [4, 2, 6] ;
[4,6,2]
X = [2, 3, 1],
Y = [4, 6, 2] ;
[2,6,4]
X = [1, 3, 2],
Y = [2, 6, 4] ;
[6,2,4]
X = [3, 1, 2],
Y = [6, 2, 4] ;
[6,4,2]
X = [3, 2, 1],
Y = [6, 4, 2] ;
false.
When you type ; you're saying, "or?" to Prolog. In other words, you're saying "what else?" You're telling Prolog, in effect, this isn't the answer I want, try and find me another answer I like better. You can formalize this process with a failure-driven loop:
?- perm([1,2,3], X), double(X, Y), showlist(Y), fail.
[2,4,6][4,2,6][4,6,2][2,6,4][6,2,4][6,4,2]
false.
So now you see the output from each permutation having gone through double/2 there, and then Prolog reported false. That's what one means by something like this:
show_all_heaps(List) :- perm(List, X), double(X, Y), showlist(Y), nl, fail.
show_all_heaps(_).
Look at how that works:
?- show_all_heaps([1,2,3]).
[2,4,6]
[4,2,6]
[4,6,2]
[2,6,4]
[6,2,4]
[6,4,2]
true.
The other option is using findall/3, which looks more like this:
?- findall(Y, (perm([1,2,3], X), double(X, Y)), Ys).
Ys = [[2, 4, 6], [4, 2, 6], [4, 6, 2], [2, 6, 4], [6, 2, 4], [6, 4, 2]].
Using this to solve your problem is probably beyond the scope of whatever homework it is you're working on though.
We can define list_permutation/2 based on same_length/2 and select/3 like this:
:- use_module(library(lists),[same_length/2,select/3]).
list_permutation(As,Bs) :-
same_length(As,Bs), % redundant goal helps termination
list_permutation_(As,Bs).
list_permutation_([],[]).
list_permutation_([A|As],Bs0) :-
select(A,Bs0,Bs),
list_permutation_(As,Bs).
Thanks to same_length/2, both of the following queries1,2 terminate universally:
?- list_permutation([1,2,3],Ys).
Ys = [1,2,3]
; Ys = [1,3,2]
; Ys = [2,1,3]
; Ys = [3,1,2]
; Ys = [2,3,1]
; Ys = [3,2,1]
; false.
?- list_permutation(Xs,[1,2,3]).
Xs = [1,2,3]
; Xs = [1,3,2]
; Xs = [2,1,3]
; Xs = [2,3,1]
; Xs = [3,1,2]
; Xs = [3,2,1]
; false.
So far, so good. But what does the answer sequence look like if there are duplicate list items?
?- list_permutation([1,1,1],Ys).
Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; false.
5/6 answers are redundant! What can we do? We simply use selectd/3 instead of select/3!
list_permuted(As,Bs) :-
same_length(As,Bs),
list_permuted_(As,Bs).
list_permuted_([],[]).
list_permuted_([A|As],Bs0) :-
selectd(A,Bs0,Bs), % use selectd/3, not select/3
list_permuted_(As,Bs).
Let's re-run above query that gave us 5 redundant solutions before!
?- list_permuted([1,1,1],Ys).
Ys = [1,1,1]
; false.
?- list_permuted(Xs,[1,1,1]).
Xs = [1,1,1]
; false.
Better! All redundant answers are gone.
Let's compare the solution set for some sample case:
?- _Xs = [1,2,1,1,2,1,1,2,1],
setof(Ys,list_permutation(_Xs,Ys),Yss),
setof(Ys,list_permuted(_Xs,Ys),Yss),
length(Yss,N).
N = 84, Yss = [[1,1,1,1,1,1,2,2,2],[1,1,1,1,1,2,1,2,2],[...|...]|...].
OK! How about empirical runtime measurements with a problem of a slightly bigger size?
We use call_time/2 for measuring the runtime in milli-seconds T_ms.
?- call_time(\+ (list_permutation([1,2,1,1,1,2,1,1,1,2,1],_),false),T_ms).
T_ms = 8110.
?- call_time(\+ (list_permuted( [1,2,1,1,1,2,1,1,1,2,1],_),false),T_ms).
T_ms = 140.
OK! And with proper compilation of if_/3 and (=)/3, list_permuted/2 is even faster!
Footnote 1: Using SICStus Prolog version 4.3.2 (x86_64-linux-glibc2.12).
Footnote 2: The answers given by the Prolog toplevel have been post-processed for the sake of readability.
If you just want to explore the permutations without the "False" in the end, this code might be helpful
takeout(X,[F |R],[F|S]) :- F\=X, takeout(X,R,S).
takeout(X,[X|R],R).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
So, the output of perm([a,b],B) would be
B=[a,b]
B=[b,a]