hello i have a list like this:
[[3,[a,b,c,d]],[2,[a,b,d]],[5,[d,e,f]]]
list of lists...
i want to find the minimum number on inner list
in this case i want to return D=2 and L=[a,b,d]
i tried this code:
minway([[N|L]],N,L).
minway([[M|L1]|L2],D,_):- M<D, minway(L2,M,L1).
minway([[M|_]|L2],D,L):- M>=D, minway(L2,D,L).
but i got error:
</2: Arguments are not sufficiently instantiated
Exception: (8) minway([[3,[a,b,c,d]],[2,[a,b,d]],[5,[d,e,f]]], _G7777, _G7778) ?
creep
for this run sentence:
minway([[3,[a,b,c,d]],[2,[a,b,d]],[5,[d,e,f]]],D,L).
the result need to be:
D=2.
L=[a,b,d].
where my problem?
and how to fix it?
tnx a lot
First, switch to a better data representation: Instead of [Key,Value], use Key-Value!
Then, define minway_/3 based on
iwhen/2,
ground/1,
keysort/2, and
member/2, like so:
minway_(Lss, N, Ls) :-
iwhen(ground(Lss), (keysort(Lss,Ess), Ess = [N-_|_], member(N-Ls, Ess))).
Sample query using SICStus Prolog 4.5.0:
| ?- minway_([3-[a,b,c,d],2-[a,b,d],5-[d,e,f],2-[x,t,y]], N, Ls).
N = 2, Ls = [a,b,d] ? ;
N = 2, Ls = [x,t,y] ? ;
no
There are a couple of fundamental issues.
One is in your problem lies in your representation of a list. Your predicates seem to assume that, for example, [3, [a,b,c]] is represented as [3 | [a,b,c]] but it is not. The list [3 | [a,b,c]] is the list with 3 as the head, and [a,b,c] as the rest of the list or the tail. In other words, [3 | [a,b,c]] is [3, a, b, c].
And, so, your base case would be:
minway([[N,L]], N, L).
The second issue is in your other predicate clauses. There's no starting point for D. In other words, it's never given a value to start with, so you get an instantiation error. You cannot compare N > D if one of the variables doesn't have a value.
When doing a minimum or maximum from scratch, a common approach is to start by assuming the first element is the candidate result, and then replace it if you find a better one on each step of the recursion. It also means you need to carry with you the last candidate at each recursive call, so that adds extra arguments:
minway([[N,L]|T], D, R) :-
minway(T, N, L, D, R).
minway([], D, R, D, R). % At the end, so D, R is the answer
minway([[N,L]|T], Dm, Rm, D, R) :-
( N < Dm
-> minway(T, N, L, D, R) % N, L are new candidates if N < Dm
; minway(T, N, Dm, Rm, D, R) % Dm, Rm are still best candidate
).
In Prolog, you can simplify this a little since Prolog has a more general term comparison operator, #<, #>, etc, which is smart about comparing more complex terms. For example, [2, [d,e,f]] #< [3, [a,b,c]] is true since 2 < 3 is true. We can then write:
minway([H|T], D, R) :-
minway(T, H, D, R).
minway([], [D, R], D, R).
minway([H|T], M, D, R) :-
( H #< M
-> minway(T, H, D, R)
; minway(T, M, D, R)
).
You can do this by using the minimum predicate. Findall can be very helpful.
min([X],X).
min([H|T],Min):-
min(T,TMin),
H>TMin,
Min is TMin.
min([H|T],Min):-
min(T,TMin),
H=<TMin,
Min is H.
minway(List,D,L):-
findall(Value,member([Value,_],List),VList),
min(VList,Min),
D=Min,
findall(EList,member([Min,EList],List),L).
?-minway([[3,[a,b,c,d]],[2,[a,b,d]],[5,[d,e,f]]],D,L).
D = 2,
L = [[a, b, d]]
Try library(aggregate):
?- aggregate_all(min(X,Y),
member([X,Y], [[3,[a,b,c,d]],
[2,[a,b,d]],
[5,[d,e,f]]]),
min(D,L)).
D = 2,
L = [a, b, d].
See also here:
Aggregation operators on backtrackable predicates
https://www.swi-prolog.org/pldoc/man?section=aggregate
Related
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'm new to Prolog and trying to do this question. We have a list
List = [a,a,a,a,b,c,c,a,a,d,e,e,e,e]
I want to pack it into sub-lists of similar elements.
Pack( [a,a,a,a,b,c,c,a,a,d,e,e,e,e], Sublists)
should give
Sublists = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]]
This is what I have tried so far:
pack([],[],[]).
pack([H],[H],[H]).
pack([H,H1|T],Z,X):- H==H1 , append([H],Z,Z1) , pack([H1|T],Z1,X).
pack([H,H1|T],Z,X):- H=\=H1 , append([H],Z,Z1) ,
append(Z1,X,Xs) , pack([H1|T],Z1,Xs).
Below is the error:
Arithmetic: `a/0' is not a function
In:
[4] a=\=b
[3] pack([a,b|...],[a,a],_1608) at line 13
[2] pack([a,a|...],[a],_1688) at line 13
[1] pack([a,a|...],[],_1762) at line 13
Thanks in advance. I'm trying to solve these problems:
P-99: Ninety-Nine Prolog Problems.
You can approach this kind of problem with simple list processing and using SWI Prolog's dif/2 to provide a general solution:
pack([], []). % packing empty is empty
pack([X], [[X]]). % packing a single element
pack([X,X|T], [[X|PH]|PT]):- % rule for packing when next two terms are the same
pack([X|T], [PH|PT]).
pack([X,Y|T], [[X]|PT]):- % rule for different term
dif(X, Y),
pack([Y|T], PT).
2 ?- pack([a,a,a,a,b,c,c,a,a,d,e,e], L).
L = [[a, a, a, a], [b], [c, c], [a, a], [d], [e, e]] ;
false.
3 ?- pack(L, [[a,a,a], [b,b], [c]]).
L = [a, a, a, b, b, c] ;
false.
4 ?-
Note that lurker's solution still has some performance issues. See the ; false for each solution? This is an indication that Prolog still retains some memory (called a choice point - actually there may be even several such choice points). For many cases however, no such choice point is needed. Here is a solution that overcomes that problem (The name group in place of pack is quite common in the context of Haskell)
group([], []).
group([E|Es], [[E|Gs]|Gss]) :-
igroup(Es, E, Gs, Gss).
igroup([], _, [], []).
igroup([E|Es], F, Gs1, Gss1) :-
( E\=F
-> Gs1=[], Gss1=[[E|Gs2]|Gss2]
; E==F
-> Gs1=[E|Gs2], Gss1=Gss2
; E=F,
Gs1=[E|Gs2], Gss1=Gss2
; dif(E, F),
Gs1=[], Gss1=[[E|Gs2]|Gss2]
),
igroup(Es, E, Gs2, Gss2).
Note how the testing for the equality of E and F is split into four cases:
First E \= F which means that both are definitely different.
Then E == F which means that both are definitely identical.
Then E = F which is the general case of equality, and
dif(E, F) which is the case of general inequality
For the last two cases there is no -> because both may be true.
Since it is quite cumbersome to maintain so many cases, there is library(reif)
for
SICStus and
SWI which permits to write the same more compactly:
igroup([], _, [], []).
igroup([E|Es], F, Gs1, Gss1) :-
if_(E = F
, ( Gs1 = [E|Gs2], Gss1 = Gss2 )
, ( Gs1 = [], Gss1 = [[E|Gs2]| Gss2] )),
igroup(Es, E, Gs2, Gss2).
The error you got is because =\=/2 is true if expr1 is evaluates to a number not equal to expr2 . Instead you can use \=\2 which evaluates \+term1=term2. ==/2 evaluates to term1 equivalent to term2, =:=/ is true if expr1 is a number which is equal to expr2. One more mistake I found in your code is you're not clearing the Intermediate List. You have to flush the values in it after you have added the similar elements list to your Sublists list. I have used cut ! to reduce backtracking. Instead, if you write mutually exclusive predicates, it's better.
I have edited your code:
pack1([],[],[]).
pack1([H],L,[Z]):- append([H],L,Z),!.
pack1([H,H1|T],Z,X):- H == H1 , append([H],Z,Z1) , pack1([H1|T],Z1,X),!.
pack1([H,H1|T],Z,[Z1|Zs]):- H\=H1 ,append([H],Z,Z1) ,pack1([H1|T],[],Zs),!.
Output:
?-pack1([a,a,a,a,b,c,c,a,a,d,e,e,e,e],[],Z).
Z=[[a, a, a, a], [b], [c, c], [a, a], [d], [e, e, e, e]]
?-pack1([a,a,a,a,b,c,1,c,a,a,d,e,e,e,e],[],Z).
Z= [[a, a, a, a], [b], [c], [1], [c], [a, a], [d], [e, e, e, e]]
?-pack1([],[],Z).
Z= []
Hope this helps.
without using dif/2
my_pack([],[[]]).
my_pack([X], [[X]]).
my_pack([X,X|L], [F|R]) :- my_pack([X|L], [F1|R]), append([X], F1, F).
my_pack([X|L], [F|R]) :- my_pack(L, R), append([X], [], F).
I have a List and I am trying to add to it elements from another list that are not already present in the first List.
So if I had 2 Lists :
[a, b, 3, c]
[2, a, b, 4]
The output would be:
[a, b, 3, c, 2, 4]
I am able to get it in reversed order but not in the correct one, here is what I am trying to do:
add_to_list(L, [], L).
add_to_list(List, [H|T], [H|Res]) :-
\+ member(H, List),
add_to_list(List, T, Res).
add_to_list(List, [H|T], Res):-
add_to_list(List, T, Res).
And when I do the method with the 2 Lists mentioned above the output I get is:
[2, 4, a, b, 3, c]
I am aware that my ending clause is adding the L to the end of the result I get, which is why the order is a mess but how can I do it the correct way?
Well the problem here is that you should first move to the end of the first list before concatenating data.
We can still use the code you have written, but alter it slightly like:
atl(_, [], []).
atl(List, [H|T], R) :-
( member(H, List)
-> R = Res
; R = [H|Res]
),
atl(List, T, Res).
We here basically made three changes: (a) we renamed addToList/3 to atl/3; we changed L to [] in the first line; and (c) we used an if-then-else to prevent that the third clause gets triggered even if H is not a member of List (this was a semantical error in your code).
Now we will obtain for the given input as output:
?- atl([a, b, 3, c] , [2, a, b, 4], R).
R = [2, 4] ;
false.
So now we can write an addToList/3 in terms of atl/3: we first generate the list of items to append, and next we use append/3 to append these at the end of the list:
addToList(A, B, L) :-
atl(A, B, R),
append(A, R, L).
I've been searching through the many existing Prolog questions on SO relevant to splitting but couldn't find one as generic as the one that I want. I'd like to point out that I've been able to split lists into lists of 2/3/4 elements by using 2/3/4 variables piped before a list variable. This question is different from that only because of its genericness.
So, my list will always contain N*N items, N being unknown beforehand(usually will vary from 4 to 36, yes N is also a perfect square). I want to split it into a list of N lists containing N items each because that'll allow me to treat it as a matrix, hence allowing to transpose and certain operations of that sort. I haven't really been able to get too far with the logic because I'm relatively new to declarative programming; please see below my incomplete(faulty) attempt:
listmodel(1,L):- L = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16].
size(L,N) :- length(L,N1), N is round(sqrt(N1)).
% add_tail(+Liste, +Element, -ResultantList)
add_tail([],L,[L]).
add_tail([X|L1],L2,[X|LI]):-add_tail(L1,L2,LI).
% partition the list containing N*N items into a list of N lists containing N elements each.
% part(+Liste, +Size, -ResultantList)
part([],_,DL).
part(L,N,DL) :-
length(P,N), % P(refix) initialized
append(P,S,L), % S(uffix) contains rest of L, using append in (-,-,+) mode
add_tail(DL,P,DL1), %add P(first N elements) as first element of DL.
part(S,N,DL1).
Now running ?- listmodel(1,L),size(L,N),part(L,N,DL). will produce DL=[] because that is what it gets initialized to in the first add_tail call in the part predicate. I can't seem to figure out how to store all elements in a list that's preserved through the recursion.
Any help/direction of any kind will be appreciated. I'm stuck here since over 23 hours 10 minutes now.
Thanks.
This should do it:
part([], _, []).
part(L, N, [DL|DLTail]) :-
length(DL, N),
append(DL, LTail, L),
part(LTail, N, DLTail).
Base case is first/last arguments are empty lists.
Recursive step takes a fresh list of N elements, takes the first N elements from L (which will be one of the items of the third argument) and calls recursively.
Want to combine versatility and favorable termination properties?
Use clpfd!
:- use_module(library(clpfd)).
First, we define
list_prefix_n_suffix/4.
list_prefix_n_suffix(Zs,Xs,N,Ys) is logically equivalent to both append(Xs,Ys,Zs), length(Xs,N) and length(Xs,N), append(Xs,Ys,Zs), but has better universal termination behavior than either1 one!
list_prefix_n_suffix(Zs, Xs, N, Ys) :-
list_prefix_n0_n_suffix(Zs, Xs, 0,N, Ys).
list_prefix_n0_n_suffix(Zs, Xs, N0,N, Ys) :-
zcompare(Order, N0, N),
rel_list_prefix_n0_n_suffix(Order, Zs, Xs, N0,N, Ys).
rel_list_prefix_n0_n_suffix(=, Ys, [], _,_, Ys).
rel_list_prefix_n0_n_suffix(<, [Z|Zs], [Z|Xs], N0,N, Ys) :-
N1 #= N0 + 1,
list_prefix_n0_n_suffix(Zs, Xs, N1,N, Ys).
Some sample queries for list_prefix_n_suffix/4:
?- list_prefix_n_suffix([a,b,c], Xs,-1, Ys).
false. % OK: too small
?- list_prefix_n_suffix([a,b,c], Xs, 0, Ys).
Xs = [], Ys = [a,b,c]. % succeeds deterministically
?- list_prefix_n_suffix([a,b,c], Xs, 4, Ys).
false. % OK: too big
?- list_prefix_n_suffix([a,b,c], Xs, N, Ys).
Xs = [] , N = 0, Ys = [a,b,c]
; Xs = [a] , N = 1, Ys = [b,c]
; Xs = [a,b] , N = 2, Ys = [c]
; Xs = [a,b,c], N = 3, Ys = []
; false. % terminates universally
Based upon above list_prefix_n_suffix/4 we define list_rows_width/3:
list_rows_width([], [], _N).
list_rows_width([E|Es0], [[R|Rs]|Rss], N) :-
list_prefix_n_suffix([E|Es0], [R|Rs], N, Es),
list_rows_width(Es, Rss, N).
Sample queries using list_rows_width/3:
?- list_rows_width([a,b,c,d,e,f], Rows, 4).
false. % OK: 6 is not divisible by 4
?- list_rows_width([a,b,c,d,e,f], Rows, 3).
Rows = [[a,b,c],[d,e,f]]. % succeeds deterministically
?- list_rows_width([a,b,c,d,e,f,g,h,i,j,k,l], Rows, N).
N = 1, Rows = [[a],[b],[c],[d],[e],[f],[g],[h],[i],[j],[k],[l]]
; N = 2, Rows = [[a, b],[c, d],[e, f],[g, h],[i, j],[k, l]]
; N = 3, Rows = [[a, b, c],[d, e, f],[g, h, i],[j, k, l]]
; N = 4, Rows = [[a, b, c, d],[e, f, g, h],[i, j, k, l]]
; N = 6, Rows = [[a, b, c, d, e, f],[g, h, i, j, k, l]]
; N = 12, Rows = [[a, b, c, d, e, f, g, h, i, j, k, l]]
; false. % terminates universally
Works just like it should!
Footnote 1: Without resorting to using alternative control-flow mechanisms like prolog-coroutining.
So i have this code which copies everything from a list to another one.
How should I modify it in order to copy, lets say the first two character.
$copy(L,R) :-
copy2(L,R).
copy2([X],[X]).
copy2([H|T1],[H|T2]) :-
copy2(T1,T2).
example of what i want it to be: ?- copy([a,b,c,d,e,f],X,2). --> X = [a,b]
You can copy lists just with unification:
?- [a,b,c,d,e] = List.
List = [a, b, c, d, e].
?- [a,b,c,d,e] = [V,W,X,Y,Z].
V = a,
W = b,
X = c,
Y = d,
Z = e.
?- [a,b,c,d,e] = [V,W|Rest].
V = a,
W = b,
Rest = [c, d, e].
A predicate like the one you describe, copying the first N elements of a list, can be defined thus:
first_n(List, N, Xs) :-
length(Xs, N),
append(Xs _, List).
Which works like so:
?- first_n([a,b,c,d,e], 2, X).
X = [a, b].
There are a bunch of different ways to write a similar predicate. The way I have defined first_n/3, it will fail if N is larger than the length of List (this was pointed to out by #false in the comments). One could instead write an analog of the common function take, which will return List in its entirety in the event that N is greater than List's length:
take_n(N, List, Taken) :-
( length(List, M),
N > M
->
Taken = List
;
length(Taken, N),
append(Taken, _, List)
).
This answer was corrected (several times) under the guidance of #false's helpful criticism.