How can I repeatedly extract minimum number until the list is empty?
I want to find a minimum number, then exclude it from the original list, then find a minimum again and again, until the list becomes empty.
Input:
?- Find_Minimum([2, 1, 4, 3, 5], C)
Output:
C = 1
C = 2
C = 3
C = 4
C = 5
False
Here a simple solution using sort/2 (in SWI):
minimum(L,E):-
sort(L,LSorted),
pick(LSorted,E).
pick([H|_],H).
pick([_|T],E):-
pick(T,E).
?- minimum([2,1,4,3,5],E).
E = 1
E = 2
E = 3
E = 4
E = 5
false
Keep in mind that sort/2 removes duplicates. If you want to keep them use for instance msort/2 (in SWI). For an even simpler solution you can use member/2:
minimum(L,E):-
sort(L,LSorted),
member(E,LSorted).
?- minimum([2,1,4,3,5],E).
E = 1
E = 2
E = 3
E = 4
E = 5
I would had written - more or less - the same answer as #damianodamiano (+1), but tried nevertheless to code something more 'direct' than sorting. It turns out the outcome is rather technical...
:- module(minext, [minext/2,minext/3]).
minext(L,M) :-
minext(L,T,R),
( M=T
; minext(R,M)
).
minext(L,X,R) :-
select(X,L,R),
\+((
member(Y,R),
Y<X
)), !.
I'm trying to get more into learning prolog as I'll be taking an AI class at school next semester. I've been able to get down the basics down and can do relation based stuff, however, I've been trying to learn permutations and combinatronics and they seem pretty straightforward, but it led me to a question that I can't figure out how to solve. Say I wanted to know the permutations of 1's and 0's with a certain condition that there must be atleast 4 1's in a row.
I have no idea where I would start to try and find a solution for this, but in the end I want the code to do something like this:
?- placeOnesAndZeros(9,X).
% where 9 is the length of the list/array and X is the permutations
[0,0,0,0,0,0,0,0,0]
[1,1,1,1,0,0,0,0,0]
[0,1,1,1,1,0,0,0,0]
[0,0,1,1,1,1,0,0,0]
[0,0,0,1,1,1,1,0,0]
[0,0,0,0,1,1,1,1,0]
[0,0,0,0,0,1,1,1,1]
[1,1,1,1,0,1,1,1,1]
[1,1,1,1,1,0,0,0,0]
[0,1,1,1,1,1,0,0,0]
[0,0,1,1,1,1,1,0,0]
[0,0,0,1,1,1,1,1,0]
[0,0,0,0,1,1,1,1,1]
[1,1,1,1,1,1,0,0,0]
[0,1,1,1,1,1,1,0,0]
[0,0,1,1,1,1,1,1,0]
[0,0,0,1,1,1,1,1,1]
[1,1,1,1,1,1,1,0,0]
[0,1,1,1,1,1,1,1,0]
[0,0,1,1,1,1,1,1,1]
[1,1,1,1,1,1,1,1,0]
[0,1,1,1,1,1,1,1,1]
[1,1,1,1,1,1,1,1,1]
Thank you in advance!
EDIT CODE:
printList([ ]).
printList([H|T]) :- print(H), nl, printList(T).
eval([],_).
eval([H|T],[1,0]):-member(H,[1,0]),eval(T,[1,0]).
placeOnesAndZeros(N, L):-length(L,N), eval(L,[1,0]).
Generate and test it's the name of the basic technique used to search a solution space. In Prolog, it's practically built in. Just provide a filter discarding what is not required:
?- placeOnesAndZeros(9,L),once(append(_,[1,1,1,1|_],L)).
once/1 is required, otherwise append/3 could succeed multiple times.
To check the correctness of the approach, here is how to count how many solutions we get:
?- aggregate(count,L^H^T^(placeOnesAndZeros(9,L),once(append(H,[1,1,1,1|T],L))),C).
C = 111.
The quantification on variables L,H,T (these last 2 being introduced only to aggregate) can be avoided using aggregate_all:
?- aggregate_all(count,(placeOnesAndZeros(9,L),once(append(_,[1,1,1,1|_],L))),C).
C = 111.
edit
As #lurker noted, my filter isn't correct. Try instead
atLeastFourOnes(L) :- memberchk(1,L), atLeastFourOnes_(L).
atLeastFourOnes_([]).
atLeastFourOnes_([0|L]) :- atLeastFourOnes_(L).
atLeastFourOnes_([1,1,1,1|L]) :- stripOnes(L,R), atLeastFourOnes_(R).
that yields
?- placeOnesAndZeros(9,L),atLeastFourOnes(L).
L = [1, 1, 1, 1, 1, 1, 1, 1, 1] ;
L = [1, 1, 1, 1, 1, 1, 1, 1, 0] ;
L = [1, 1, 1, 1, 1, 1, 1, 0, 0] ;
...
?- aggregate(count,L^(placeOnesAndZeros(9,L),atLeastFourOnes(L)),C).
C = 22.
PYP
CQB
CBCW
-----
WXYPB
where each letter represents a unique digit from 0-9 and the value below the line represents the sum of those about it.
Check out the very related question Faster implementation of verbal arithmetic in Prolog.
Based on my previous answer, let's solve your specific equation using clpfd!
?- Eq = ([P,Y,P] + [C,Q,B] + [C,B,C,W] #= [W,X,Y,P,B]),
crypt_arith_(Eq,Zs),
labeling([],Zs).
Eq = ([9,3,9]+[8,7,5]+[8,5,8,1]#=[1,0,3,9,5]),
Zs = [9,3,8,7,5,1,0],
P = 9,
Y = 3,
C = 8,
Q = 7,
B = 5,
W = 1,
X = 0 ;
false.
I have a list of variables in my program, say A, B, C, D, ..., J, and I need to restrict the domain of each of the variables to the same set of integers, say 1, 2, ... 10. I know of a few different ways to do this, but all of them use at least one method from CLPFD, such as X #> 0, X ins [domain], or fd_domain(args). I haven't been able to find a way of doing this without any built-in libraries (all of which are banned for this project).
I would think that writing in the rules like this would be sufficient:
A > 0, A < 11, B > 0, B < 11, ..., J > 0, J < 11
But apparently the variables are not sufficiently instantiated. I know it's a trivially simple question, but I've been searching on my own for a while and really have no other resources for help. Thanks very much.
There's the between function in SWI-Prolog:
?- between(1, 9, A).
A = 1 ;
A = 2 ;
A = 3 ;
A = 4 ;
A = 5 ;
A = 6 ;
A = 7 ;
A = 8 ;
A = 9.
If that's banned as well (it's non-standard), then you use member/2:
?- member(A, [1, 2, 3, 4, 5, 6, 7, 8, 9]).
A = 1 ;
A = 2 ;
A = 3 ;
A = 4 ;
A = 5 ;
A = 6 ;
A = 7 ;
A = 8 ;
A = 9.
Without CLP(fd), you'll be trapped in the generate-and-test paradigm, though, and perhaps it's better to find some workaround where you check variable values in an ad hoc way to get decent performance.
so i am trying to solve kenken using prolog but i ran into several problems from the start, first of all lets say i run it like kenken([X1,X2,X3,.....X16]). and i want to solve for this x's with rules i defined before. so lets say the first cell has 3 values X1,X2,and X3 and i want to get 2 by using multiplication meaning that X1*X2*X3=2, now how do i set up a rule to see all posible solutions if i had something like that.
also how would i tell my x's to only use a range of values 1-4.
i tried to do something like
:- use_module(library(clpr)).
solve([X1,X2,X3]):-
{X1*X2*X3=2}.
but its gives me a really weird output.
Since you reason over integers, not floats, consider using library(clpfd) instead of CLP(R). In SICStus, SWI and YAP, you can constrain a finite domain variable X to the integer range 1-4 with:
X in 1..4
You can use the built-in predicate label/1 to search for concrete solutions. Example with SWI-Prolog:
?- Vars = [A,B,C], A*B*C #= 2, Vars ins 1..4, label(Vars).
yielding:
Vars = [1, 1, 2], A = B, B = 1, C = 2 ;
Vars = [1, 2, 1], A = C, C = 1, B = 2 ;
Vars = [2, 1, 1], A = 2, B = C, C = 1.
You need the is operator to do arithmetic:
2 is X1*X2*X3
Note that this will not work unless the X's are all bound to numbers.