Prolog: Putting elements in a list for a decimal to binary conversion - list

Hello I was trying to modify a decimal to binary conversion function, so that it would display the results in a list. I'm new to prolog and I can't seem to get it to function properly.
dec2bin(0,0).
dec2bin(1,1).
dec2bin(N,L):- N>1,X is N mod 2,Y is N//2, dec2bin(Y,L1), L = [L1|[X]].
Then this is the result:
86 ?- dec2bin(26,L).
L = [[[[1, 1], 0], 1], 0]
Can someone help me understand what it is that I'm doing wrong.
Thanks

if you amend your code
dec2bin(0,[0]).
dec2bin(1,[1]).
dec2bin(N,L):-
N > 1,
X is N mod 2,
Y is N // 2,
dec2bin(Y,L1),
L = [X|L1].
you will get your solution with bits in reverse order:
?- dec2bin(26,L).
L = [0, 1, 0, 1, 1]
Instead of appending each bit, consider a final reverse/2, or invert the order by means of an accumulator
dec2bin(N,L) :- dec2bin(N,[],L).
dec2bin(0,L,[0|L]).
dec2bin(1,L,[1|L]).
dec2bin(N,L,R):-
N > 1,
X is N mod 2,
Y is N // 2,
dec2bin(Y,[X|L],R).

You have to apply some list concatenation, but you are just creating two terms lists and nesting them with L = [L1|[X]] when you consider L1 to be just a number.
If you consider it as a list, you can simply appending to it the newly created X, but to do so you have to rewrite the base cases of your recursion:
dec2bin(0,[0]).
dec2bin(1,[1]).
dec2bin(N,L):-
N > 1,
X is N mod 2,
Y is N // 2,
dec2bin(Y,L1),
append(L1, [X], L).
yielding to:
?- dec2bin(26,L).
L = [1, 1, 0, 1, 0]
where append/3 can be a library predicate or your own implementation.

Related

Arithmetic in Prolog - Multiples of a number

I want to create a function multiples(X, N, R) where R is a list containing all multiples of X from X to X * N.
An example would be: multiples(3, 4, [12, 9, 6, 3]), which should give out true.
My code so far:
multiples(X, N, R) :- X >= 1, N >= 1, Z is X*N, contains(Z, R).
contains(Z, [Z|_]).
contains(Z, [W|V]) :- contains(Z,V), L is Z-X, L >= X, contains(L, V).
The output of the console for multiples(3,4,X). is X = [12|_xxxx] and when I type ; an error occurs.
How do I manage to receive the list that I want?
(Maybe my idea is completely wrong).
I found 4 issues with your code. Here is the fixed code, explanation below:
multiples(X, N, R) :-
X >= 1,
N >= 1,
Z is X*N,
contains(X, Z, R).
contains(X, Z, [Z|V]) :-
L is Z-X,
L >= X,
contains(X, L, V).
contains(_, Z, [Z]).
?- multiples(3,4,X).
X = [12, 9, 6, 3] ;
X = [12, 9, 6] ;
X = [12, 9] ;
X = [12] ;
false.
At first in your contains predicate you access X and W and never state their values. Solve X by adding another attribute to the predicate. Solve W by replacing it with Z.
Another problem is the order of your rules. The larger contains rule should be the "main" rule, only if this one fails the other one should "fire". By placing the default rule on top you get the right result.
Also the rule contains(_, Z, [Z]). marks the end, therefore it the return list has only the element Z in it and does not contain any other (unknown) elements.
The last point is that you don't need two contains calls in the main contains rule.
The example works for the first answer. However you can improve this with a cut (!), which prevents going to the second rule after successfully visiting the first rule:
contains(X, Z, [Z|V]) :-
L is Z-X,
L >= X,
!,
contains(X, L, V).
contains(_, Z, [Z]).
?- multiples(3,4,X).
X = [12, 9, 6, 3].
A slight modification to your code. contains predicate will collect the numbers in a list, and N will keep getting decreased till it satisfies the base predicate.
multiples(X, N, R) :- X >= 1, N >= 1, contains(X,N, R),!.
contains(_,0,[]).
contains(X,N,[Z|List]):-
Z is X*N,
N1 is N-1,
contains(X,N1,List).
Example:
?- multiples(3,4,R).
R = [12, 9, 6, 3]
?- multiples(2,5,R).
R = [10, 8, 6, 4, 2]
?- multiples(25,5,R).
R = [125, 100, 75, 50, 25]

Unique combinations of 0 and 1 in list in prolog

I have problem, because I want to generate permutations of a list (in prolog), which contains n zeros and 24 - n ones without repetitions. I've tried:findall(L, permutation(L,P), Bag) and then sort it to remove repetitions, but it causes stack overflow. Anyone has an efficient way to do this?
Instead of thinking about lists, think about binary numbers. The list will have a length of 24 elements. If all those elements are 1's we have:
?- X is 0b111111111111111111111111.
X = 16777215.
The de fact standard predicate between/3 can be used to generate numbers in the interval [0, 16777215]:
?- between(0, 16777215, N).
N = 0 ;
N = 1 ;
N = 2 ;
...
Only some of these numbers satisfy your condition. Thus, you will need to filter/test them and then convert the numbers that pass into a list representation of its binary equivalent.
Select n random numbers between 0 and 23 in ascending order. These integers give you the indexes of the zeroes and all the configurations are different. The key is generating these list of indexes.
%
% We need N monotonically increasing integer numbers (to be used
% as indexes) from [From,To].
%
need_indexes(N,From,To,Sol) :-
N>0,
!,
Delta is To-From+1,
N=<Delta, % Still have a chance to generate them all
N_less is N-1,
From_plus is From+1,
(
% Case 1: "From" is selected into the collection of index values
(need_indexes(N_less,From_plus,To,SubSol),Sol=[From|SubSol])
;
% Case 2: "From" is not selected, which is only possible if N<Delta
(N<Delta -> need_indexes(N,From_plus,To,Sol))
).
need_indexes(0,_,_,[]).
Now we can get list of indexes picked from the available possible indexes.
For example:
Give me 5 indexes from 0 to 23 (inclusive):
?- need_indexes(5,0,23,Collected).
Collected = [0, 1, 2, 3, 4] ;
Collected = [0, 1, 2, 3, 5] ;
Collected = [0, 1, 2, 3, 6] ;
Collected = [0, 1, 2, 3, 7] ;
...
Give them all:
?- findall(Collected,need_indexes(5,0,23,Collected),L),length(L,LL).
L = [[0, 1, 2, 3, 4], [0, 1, 2, 3, 5], [0, 1, 2, 3, 6], [0, 1, 2, 3, 7], [0, 1, 2, 3|...], [0, 1, 2|...], [0, 1|...], [0|...], [...|...]|...],
LL = 42504.
We are expecting: (24! / ((24-5)! * 5!)) solutions.
Indeed:
?- L is 20*21*22*23*24 / (1*2*3*4*5).
L = 42504.
Now the only problem is transforming every solution like [0, 1, 2, 3, 4] into a string of 0 and 1. This is left as an exercise!
Here is an even simpler answer to generate strings directly. Very direct.
need_list(ZeroCount,OneCount,Sol) :-
length(Zs,ZeroCount),maplist([X]>>(X='0'),Zs),
length(Os,OneCount),maplist([X]>>(X='1'),Os),
compose(Zs,Os,Sol).
compose([Z|Zs],[O|Os],[Z|More]) :- compose(Zs,[O|Os],More).
compose([Z|Zs],[O|Os],[O|More]) :- compose([Z|Zs],Os,More).
compose([],[O|Os],[O|More]) :- !,compose([],Os,More).
compose([Z|Zs],[],[Z|More]) :- !,compose(Zs,[],More).
compose([],[],[]).
rt(ZeroCount,Sol) :-
ZeroCount >= 0,
ZeroCount =< 24,
OneCount is 24-ZeroCount,
need_list(ZeroCount,OneCount,SolList),
atom_chars(Sol,SolList).
?- rt(20,Sol).
Sol = '000000000000000000001111' ;
Sol = '000000000000000000010111' ;
Sol = '000000000000000000011011' ;
Sol = '000000000000000000011101' ;
Sol = '000000000000000000011110' ;
Sol = '000000000000000000100111' ;
Sol = '000000000000000000101011' ;
Sol = '000000000000000000101101' ;
Sol = '000000000000000000101110' ;
Sol = '000000000000000000110011' ;
Sol = '000000000000000000110101' ;
....
?- findall(Collected,rt(5,Collected),L),length(L,LL).
L = ['000001111111111111111111', '000010111111111111111111', '000011011111111111111111', '000011101111111111111111', '000011110111111111111111', '000011111011111111111111', '000011111101111111111111', '000011111110111111111111', '000011111111011111111111'|...],
LL = 42504.

How to reify Prolog's backtracking state to perform the same task as "lazy seq" from Clojure?

Here is a quicksort algorithm for numbers written in Clojure. It is basically the quicksort algorithm found in "The Joy of Clojure", 2nd edition, page 133. I modified it slightly for (hopefully) better readability, because the original felt a bit too compact:
(defn qsort-inner [work]
(lazy-seq
(loop [loopwork work]
(let [[ part & partz ] loopwork ]
(if-let [[pivot & valuez] (seq part)]
(let [ smaller? #(< % pivot)
smz (filter smaller? valuez)
lgz (remove smaller? valuez)
nxxt (list* smz pivot lgz partz) ]
(recur nxxt))
(if-let [[oldpivot & rightpartz] partz]
(cons oldpivot (qsort-inner rightpartz))
[]))))))
(defn qsort [ xs ]
(qsort-inner (list xs)))
The algorithm is started by a call to qsort, which envelops a passed list of numbers into another list (thus creating a list containing a single list), then calls qsort-inner.
(qsort [10 4 5 88 7 1]) ;; (qsort-inner [[10 4 5 88 7 1]])
;; (1 4 5 7 10 88)
qsort-inner has three noteworthy points:
It delays actual processing. Instead of returning the result of a complete sorting of the input list, it returns a "lazy-seq", which is an (object? thing? thunk?) that emits the next number of the sorted sequence when queried, i.e. sorts on an as-needed basis. The state of the computation is given by the suspended tail of (cons oldpivot (qsort-inner rightpartz))
There is a loop + recur tail-recursive part which is used whenever the algorithm wanders down the sorting tree "towards the left" (see below for algorithm details.)
There is a fully recursive call (qsort-inner rightpartz) which is used when the next least number has been obtained and the sorting tree can be "re-arranged" (see below for algorithm details.)
With the help of the lazy-seq thing, we can make the algorithm emit data one-by-one:
;; the full result is generated on printout
(qsort [10 4 5 88 7 1])
(1 4 5 7 10 88)
;; store the lazy-seq and query it
(def l (qsort [10 4 5 88 7 1]))
(first l)
;; 1
(second l)
;; 4
I was thinking about how to perform this lazy quicksort in Prolog. In fact, laziness, at least in this instance, is given for free in Prolog by backtracking! We can ask for a first result, computation halts and the next result is then obtained by backtracking.
qsort_inner(X, [[],X|_]).
qsort_inner(X, [[],_|WorkRest]) :- qsort_inner(X, WorkRest).
qsort_inner(X, [[Piv|Ns]|WorkRest]) :-
pick_smaller(Piv,Ns,SMs),
pick_notsmaller(Piv,Ns,NSMs),
qsort_inner(X,[SMs,Piv,NSMs|WorkRest]).
pick_smaller(Pivot,Ins,Outs) :- include(#>(Pivot),Ins,Outs).
pick_notsmaller(Pivot,Ins,Outs) :- exclude(#>(Pivot),Ins,Outs).
qsort(X,Lin) :- qsort_inner(X,[Lin]).
Sort a list "lazily":
qsort(X,[3,2,1]).
X = 1;
X = 2;
X = 3;
false
Gotta get them all:
qsort_fully(Lin,Lout) :- bagof(X, qsort(X, Lin), Lout).
Unfortunately, the data structure that keeps track of the computational state is not apparent: it is on the stack, it cannot be unified to a variable. Thus is can only use this kind of "laziness" when I am on Prolog's top level.
How do I capture the state of the computation and invoke it later?
Note on how the quick sort works
Given a list of numbers, the algorithm selects the first element of the list as pivot value (light green in the image).
It then builds a tree with those numbers strictly smaller than the pivot value in a list "on the left", the pivot itself (dark green) and those numbers larger or equal to the pivot value as a list "on the right".
It then recursively moves down this tree "towards the left".
This continues until the list of numbers smaller than the pivot value is empty.
At that point, the pivot value (here, 28) is the least number overall and can be output.
This makes the list to sort one element smaller. The tree can now be reduced by one level with a trivial rearrangement operation: the right branch of the now left-branch-less and pivot-less "deepest tree-node but one" becomes the left branch of the tree node "deepest tree-node but two".
Searching for the least element can now proceed again "towards the left".
The tree structure does not need to be explicitly kept as it holds no information. Instead, the sequence of alternating "leaf lists" and "pivot numbers" is kept in a list. Which is why we the intial "list of a lits of numbers".
Prolog is a very reifiable language. Just turn your code into data:
qsort_gen(Lin, G) :-
% G is the initial generator state for Lin's quicksorting
G = qsort_inner([Lin]).
% This_State Next_Elt Next_State
next( qsort_inner([[], X | WorkRest]), X, qsort_inner(WorkRest) ).
next( qsort_inner([[Piv|Ns] | WorkRest]), X, G ) :-
pick_smaller( Piv, Ns, SMs),
pick_notsmaller(Piv, Ns, NSMs),
next( qsort_inner([SMs, Piv, NSMs | WorkRest]), X, G).
pick_smaller( Pivot, Ins, Outs) :- include( #>(Pivot), Ins, Outs).
pick_notsmaller(Pivot, Ins, Outs) :- exclude( #>(Pivot), Ins, Outs).
That's all.
15 ?- qsort_gen([3,2,5,1,9,4,8], G), next(G,X,G2), next(G2,X2,G3), next(G3,X3,G4).
G = qsort_inner([[3, 2, 5, 1, 9, 4, 8]]),
X = 1,
G2 = qsort_inner([[], 2, [], 3, [5, 9, 4|...]]),
X2 = 2,
G3 = qsort_inner([[], 3, [5, 9, 4, 8]]),
X3 = 3,
G4 = qsort_inner([[5, 9, 4, 8]]).
16 ?- qsort_gen([1,9,4,8], G), next(G,X,G2), next(G2,X2,G3), next(G3,X3,G4).
G = qsort_inner([[1, 9, 4, 8]]),
X = 1,
G2 = qsort_inner([[9, 4, 8]]),
X2 = 4,
G3 = qsort_inner([[8], 9, []]),
X3 = 8,
G4 = qsort_inner([[], 9, []]).
17 ?- qsort_gen([1,9,4], G), next(G,X,G2), next(G2,X2,G3), next(G3,X3,G4).
G = qsort_inner([[1, 9, 4]]),
X = 1,
G2 = qsort_inner([[9, 4]]),
X2 = 4,
G3 = qsort_inner([[], 9, []]),
X3 = 9,
G4 = qsort_inner([[]]).
For easier interfacing, we can use take/4:
take( 0, Next, Z-Z, Next):- !.
take( N, Next, [A|B]-Z, NextZ):- N>0, !, next( Next, A, Next1),
N1 is N-1,
take( N1, Next1, B-Z, NextZ).
Then,
19 ?- qsort_gen([3,2,5,1,9,4,8], G), take(6, G, L-[], _).
G = qsort_inner([[3, 2, 5, 1, 9, 4, 8]]),
L = [1, 2, 3, 4, 5, 8].
20 ?- qsort_gen([3,2,5,1,9,4,8], G), take(7, G, L-[], _).
G = qsort_inner([[3, 2, 5, 1, 9, 4, 8]]),
L = [1, 2, 3, 4, 5, 8, 9].
21 ?- qsort_gen([3,2,5,1,9,4,8], G), take(10, G, L-[], _).
false.
take/4 obviously needs tweaking to close the output list gracefully when next/3 fails. It was written with the infinite lists in mind, originally. This is left as an exercise for a keen explorer.
This isn't standardized, but a number of Prologs nowadays provide facilities to maintain and manipulate multiple independent backtrackable states, often known as engines.
For example, using the corresponding primitives in ECLiPSe, you might write
init(Vars, Goal, Engine) :-
engine_create(Engine, []),
engine_resume(Engine, (true;Goal,yield(Vars,Cont),Cont), true).
more(Engine, Vars) :-
engine_resume(Engine, fail, yielded(Vars)).
and use that as follows (with qsort/2 as defined by you)
?- init(X, qsort(X,[3,2,1]), Eng),
more(Eng, X1),
more(Eng, X2),
more(Eng, X3).
X = X
Eng = $&(engine,"9wwqv3")
X1 = 1
X2 = 2
X3 = 3
Yes (0.00s cpu)
Here, the variable Eng is bound to an opaque engine-handle. This engine executes a nondeterministic goal that yields a new solution to the caller every time it is resumed and instructed to backtrack.

Prolog: Head of a variable list is not instantated

I'm writing a simple code generating a simple list with 5 numbers whose first variable should be positive and I'm trying to understand why this code fails
test([H|T]) :- H > 0, length(T,4).
when I call with
length(X,5), test(X).
it shows me the following error:
ERROR: Arguments are not sufficiently instantiated
When I debug the code, the H variable in test isn't instantiated.
Anyone know why?
The issue here is that your rule for test([H|T]) doesn't describe in Prolog that H is a positive integer. It only tests if H > 0, which fails since H has not instantiation. Just attempting to compare an uninstantiated variable with a number (H > 0 in this case) doesn't cause Prolog to assume you intended H to be a number, and further, doesn't instantiate H.
Further, your rule for test/1 doesn't describe the rest of the list (T) other than to force that it be length 4. Since you're query establishes the rule that the length of the original list be 5, this stipulation is redundant.
You appear to be wanting to define test(L) such that it means L is an arbitrary list of positive integers. This is generally done using CLP(FD):
:- use_module(library(clpfd)).
test(X) :- X ins 1..10000.
This rule says that X is a list whose values are in the range 1 to 10000. The appropriate query to generate the lists of length 5 would then be:
?- length(X, 5), test(X), label(X).
X = [1, 1, 1, 1, 1] ;
X = [1, 1, 1, 1, 2] ;
X = [1, 1, 1, 1, 3] ;
X = [1, 1, 1, 1, 4] ;
X = [1, 1, 1, 1, 5] ;
...
If you want to restrict it further and say that elements need to be unique, you can use all_different/1:
test(X) :- X ins 1..10000, all_different(X).
?- length(X, 5), test(X), label(X).
X = [1, 2, 3, 4, 5] ;
X = [1, 2, 3, 4, 6] ;
X = [1, 2, 3, 4, 7] ;
X = [1, 2, 3, 4, 8] ;
X = [1, 2, 3, 4, 9] ;
X = [1, 2, 3, 4, 10] ;
...

Sum of even and odd numbers of a list in Prolog

What I need to do is to write a predicate that takes a list of numbers and returns a list consisting of two elements, the first one is the sum of the even numbers and the second one the sum of the odd numbers.
For example:
?- sum([5,4,9,8,1,7], L).
L = [12, 22].
So far I have written:
iseven(N) :-
0 is mod(N,2).
Since you've defined iseven/2 you could use it like:
sum([],[0,0]).
sum([H|T],[N1,N2]):-
sum(T,[N3,N4]),
( iseven(H)
-> N1 is N3+H, N2 is N4
; N2 is N4+H, N1 is N3
).
Example:
?-sum([5,4,9,8,1,7], L).
L = [12, 22].
A non if-then-else version using different clauses:
sum([],[0,0]).
sum([H|T],[N1,N2]):- sum(T,[N3,N2]), iseven(H), N1 is N3+H.
sum([H|T],[N1,N2]):- sum(T,[N1,N3]), \+ iseven(H), N2 is N3+H.
You could also write this predicate using accumulators and if_/3. Furthermore you can incorporate the single goal of iseven/1 into the predicate:
list_sums(L,S) :-
list_sums_(L,S,0-0).
list_sums_([],[E,O],E-O).
list_sums_([X|Xs],S,E0-O0) :-
M is X mod 2,
if_(M=0,(E1 is E0+X, O1 is O0),(E1 is E0, O1 is O0+X)),
list_sums_(Xs,S,E1-O1).
Note how the accumulators are written as a pair (E-O). If you are free to choose a representation for the two sums, this pair notation would be an alternative to a list with two elements. Your example query yields the desired result:
?- list_sums([5,4,9,8,1,7],L).
L = [12, 22].
And the example from the comments terminates considerably faster:
?- length(L,100),maplist(=(1),L),time(list_sums(L,[A,B])).
% 703 inferences, 0.000 CPU in 0.000 seconds (100% CPU, 3426895 Lips)
L = [1, 1, 1, 1, 1, 1, 1, 1, 1|...],
A = 0,
B = 100.
However, due to the use of is/2 this is only working in one direction. If you'd like to use the predicate in the other direction as well, you could opt to use CLP(FD). In that case include the line
:- use_module(library(clpfd)).
in your source file and replace all occurrences of is/2 in list_sums_/3
by #=/2:
list_sums_([],[E,O],E-O).
list_sums_([X|Xs],S,E0-O0) :-
M #= X mod 2,
if_(M=0,(E1 #= E0+X, O1 #= O0),(E1 #= E0, O1 #= O0+X)),
list_sums_(Xs,S,E1-O1).
Your example query still yields the same result and the example from the comments terminates in an acceptable time:
?- length(L,100),maplist(=(1),L),time(list_sums(L,[A,B])).
% 18,928 inferences, 0.004 CPU in 0.004 seconds (99% CPU, 4888152 Lips)
L = [1, 1, 1, 1, 1, 1, 1, 1, 1|...],
A = 0,
B = 100.
But the predicate works in both directions now. In some cases Prolog can find concrete answers without further ado:
?- list_sums([A,B],[2,1]).
A = 2,
B = 1 ;
A = 1,
B = 2 ;
false.
In other cases you get residual goals as an answer:
?- L=[A,B,C,D,E,F], list_sums(L,[12,22]).
L = [A, B, C, D, E, F],
A+B#=_G3306,
A mod 2#=0,
B mod 2#=0,
_G3306+C#=_G3342,
C mod 2#=0,
_G3342+D#=12,
D mod 2#=0,
E+F#=22,
E mod 2#=_G3402,
F mod 2#=_G3414,
_G3414 in 0..1,
dif(_G3414, 0),
_G3402 in 0..1,
dif(_G3402, 0) ;
...
In these cases you can restrict the elements of the list to some interval and use label/1 to get concrete numbers as solution. For example, you can ask for solutions with six numbers from zero to seven and Prolog will give you all 300 solutions:
?- length(L,6), L ins 0..7, list_sums(L,[12,22]), label(L).
L = [6, 6, 1, 7, 7, 7] ;
L = [6, 6, 3, 5, 7, 7] ;
...
You can use a functionnal way :
one_sum(X, [SE,SO], [SE1, SO1]) :-
( X mod 2 =:= 0 ->
SE1 is SE+X, SO1 = SO
; SE1 = SE, SO1 is SO+X).
sum(L, S) :-
foldl(one_sum, L, [0,0], S).