Prolog: How do I return multiple values? - prolog

I want to take a value, such as 3 and return all from the given value to one. For example, if I passed in count(3), I would get 3,2, 1 separately. I don't want to return the values as a list. For what I wrote I tried to first return a value and then recursively call the next value to return. This however only returns once. What am I doing wrong?
count(0,1).
count(N,F) :-
N1 is N-1,
F is N-1,
count(N1,F1).

count(S0, S) :-
closure0(\X0^X^succ(X,X0), S0, S).
using this definition and lambdas
or
count(N,N).
count(N0,N) :-
succ(N1,N0),
count(N1,N).
or in plain ISO Prolog:
count(N,N).
count(N0,N) :-
N0 > 0, % or 1
N1 is N0-1,
count(N1,N).

May be something like that :
count(N,F) :-
N > 0,
( F = N
; N1 is N-1,
count(N1,F)).
You get
?- count(3,V).
V = 3 ;
V = 2 ;
V = 1 ;
false.

Related

prolog program for sum of all even fibonacci numbers below 4000000

I need a solution in prolog. I am trying but did not get the correct answer.
Kindly solve my problem by providing correct code.
A(1).
B(1).
Value(0).
fib(N, Value) :-
A is N <= 4000000, fib(A, A1),
B is N % 2 == 0, fib(B, B1):-
Value is +=A &&
A,B = B, A1+B1.
print Value.
test2:-
writeln("problem2(4000000,2,4613732) should be true."),
time(problem2(4000000,2,4613732)).
problem2(B,M,S5):-
[B,M] ins 1..sup,
genfib(0,1,B,LF),
include({M}/[X2]>> #=(mod(X2,M),0),LF,LN),
sum_list(LN,S5).
genfib(N1,N2,B,[N|LF]):-
N #= N1+N2,
`N #=< B,`
genfib(N2,N,B,LF),
!.
genfib(_,_,_,[]).

creating a list in prolog based on an other list

i am a begginer in prolog and i want to write a code that creates a list based on another list.I wrote this :
create([_],N,J,K,J):- N>K.
create([X|Xs],N,L,K,J):- X==N , N1 is N + 1 , create(Xs,N1,[-1|L],K,J).
create([X|Xs],N,L,K,J):-N1 is N + 1 , create([X|Xs],N1,[0|L],K,J).
K is the size of the output list.
N is a counter .
L is the output.
X is the input list.
?- create([1,2],1,[],5,N).
N = [0, 0, 0, 0, -1]
i would like to get a list with size equal to 5(K) filled with zeros except the positions that are specified in the input list on which the value will be -1(I didnt reverse it).
I think your code should be - note the list is built in the head, to avoid reversing)
create(_ ,N,K, []) :- N > K, !.
create([N|Xs],N,K,[-1|L]) :- !, N1 is N + 1, create(Xs,N1,K,L).
create( Xs ,N,K,[ 0|L]) :- N1 is N + 1, create(Xs,N1,K,L).
It requires the zeros positions sorted.
Otherwise, the more idiomatic - and cryptic -
create(Ps, N,K, L) :- findall(D, (
between(N,K,P),
( memberchk(P,Ps) -> D = -1 ; D = 0)), L).
will work regardless the ordering.

Prolog count list elements higher than n

I'm kinda new to Prolog so I have a few problems with a certain task. The task is to write a tail recursive predicate count_elems(List,N,Count) condition List_Element > N, Count1 is Count+1.
My approach:
count_elems( L, N, Count ) :-
count_elems(L,N,0).
count_elems( [H|T], N, Count ) :-
H > N ,
Count1 is Count+1 ,
count_elems(T,N,Count1).
count_elems( [H|T], N, Count ) :-
count_elems(T,N,Count).
Error-Msg:
ERROR: toplevel: Undefined procedure: count_elems/3 (DWIM could not correct goal)
I'm not quite sure where the problem is. thx for any help :)
If you want to make a tail-recursive version of your code, you need (as CapelliC points out) an extra parameter to act as an accumulator. You can see the issue in your first clause:
count_elems(L, N, Count) :- count_elems(L,N,0).
Here, Count is a singleton variable, not instantiated anywhere. Your recursive call to count_elems starts count at 0, but there's no longer a variable to be instantiated with the total. So, you need:
count_elems(L, N, Count) :-
count_elems(L, N, 0, Count).
Then declare the count_elem/4 clauses:
count_elems([H|T], N, Acc, Count) :-
H > N, % count this element if it's > N
Acc1 is Acc + 1, % increment the accumulator
count_elems(T, N, Acc1, Count). % check the rest of the list
count_elems([H|T], N, Acc, Count) :-
H =< N, % don't count this element if it's <= N
count_elems(T, N, Acc, Count). % check rest of list (w/out incrementing acc)
count_elems([], _, Count, Count). % At the end, instantiate total with accumulator
You can also use an "if-else" structure for count_elems/4:
count_elems([H|T], N, Acc, Count) :-
(H > N
-> Acc1 is Acc + 1
; Acc1 = Acc
),
count_elems(T, N, Acc1, Count).
count_elems([], _, Count, Count).
Also as CapelliC pointed out, your stated error message is probably due to not reading in your prolog source file.
Preserve logical-purity with clpfd!
Here's how:
:- use_module(library(clpfd)).
count_elems([],_,0).
count_elems([X|Xs],Z,Count) :-
X #=< Z,
count_elems(Xs,Z,Count).
count_elems([X|Xs],Z,Count) :-
X #> Z,
Count #= Count0 + 1,
count_elems(Xs,Z,Count0).
Let's have a look at how versatile count_elems/3 is:
?- count_elems([1,2,3,4,5,4,3,2],2,Count).
Count = 5 ; % leaves useless choicepoint behind
false.
?- count_elems([1,2,3,4,5,4,3,2],X,3).
X = 3 ;
false.
?- count_elems([1,2,3,4,5,4,3,2],X,Count).
Count = 0, X in 5..sup ;
Count = 1, X = 4 ;
Count = 3, X = Count ;
Count = 5, X = 2 ;
Count = 7, X = 1 ;
Count = 8, X in inf..0 .
Edit 2015-05-05
We could also use meta-predicate
tcount/3, in combination with a reified version of (#<)/2:
#<(X,Y,Truth) :- integer(X), integer(Y), !, ( X<Y -> Truth=true ; Truth=false ).
#<(X,Y,true) :- X #< Y.
#<(X,Y,false) :- X #>= Y.
Let's run above queries again!
?- tcount(#<(2),[1,2,3,4,5,4,3,2],Count).
Count = 5. % succeeds deterministically
?- tcount(#<(X),[1,2,3,4,5,4,3,2],3).
X = 3 ;
false.
?- tcount(#<(X),[1,2,3,4,5,4,3,2],Count).
Count = 8, X in inf..0 ;
Count = 7, X = 1 ;
Count = 5, X = 2 ;
Count = 3, X = Count ;
Count = 1, X = 4 ;
Count = 0, X in 5..sup .
A note regarding efficiency:
count_elems([1,2,3,4,5,4,3,2],2,Count) left a useless choicepoint behind.
tcount(#<(2),[1,2,3,4,5,4,3,2],Count) succeeded deterministically.
Seems you didn't consult your source file.
When you will fix this (you could save these rules in a file count_elems.pl, then issue a ?- consult(count_elems).), you'll face the actual problem that Count it's a singleton in first rule, indicating that you must pass the counter down to actual tail recursive clauses, and unify it with the accumulator (the Count that gets updated to Count1) when the list' visit is done.
You'll end with 3 count_elems/4 clauses. Don't forget the base case:
count_elems([],_,C,C).

Finding the k'th occurence of a given element

I just started in Prolog and have the problem:
(a) Given a list L, an object X, and a positive integer K, it returns
the position of the K-th occurrence of X in L if X appears at least K
times in L otherwise 0.
The goal pos([a,b,c,b],b,2,Z) should succeed with the answer Z = 4.
So far I have:
pos1([],H,K,F).
pos1([H],H,1,F).
pos1([H|T],H,K,F):- NewK is K - 1, pos1(T,H,NewK,F), F is F + 1.
pos1([H|T],X,K,F):- pos1(T,X,K,F).
But I can't figure out why I'm getting:
ERROR: is/2: Arguments are not sufficiently instantiated
Any help would be much appreciated!
Use clpfd!
:- use_module(library(clpfd)).
We define pos/4 based on (#>)/2, (#=)/2, if_/3, dif/3, and (#<)/3:
pos(Xs,E,K,P) :-
K #> 0,
pos_aux(Xs,E,K,1,P).
pos_aux([X|Xs],E,K,P0,P) :-
P0+1 #= P1,
if_(dif(X,E),
pos_aux(Xs,E,K,P1,P),
if_(K #< 2,
P0 = P,
(K0+1 #= K,
pos_aux(Xs,E,K0,P1,P)))).
Sample query as given by the OP:
?- X = b, N = 2, pos([a,b,c,b],X,N,P).
X = b, N = 2, P = 4. % succeeds deterministically
How about the following more general query?
?- pos([a,b,c,b],X,N,P).
X = a, N = 1, P = 1
; X = b, N = 1, P = 2
; X = b, N = 2, P = 4 % (exactly like in above query)
; X = c, N = 1, P = 3
; false.
Let's take a high-level approach to it, trading the efficiency of the resulting code for the ease of development:
pos(L,X,K,P):-
numerate(L,X,LN,1), %// [A1,A2,A3...] -> [A1-1,A2-2,A3-3...], where Ai = X.
( drop1(K,LN,[X-P|_]) -> true ; P=0 ).
Now we just implement the two new predicates. drop1(K,L,L2) drops K-1 elements from L, so we're left with L2:
drop1(K,L2,L2):- K<2, !.
drop1(K,[_|T],L2):- K1 is K-1, drop1(K1,T,L2).
numerate(L,X,LN,I) adds an I-based index to each element of L, but keeps only Xs:
numerate([],_,[],_).
numerate([A|B],X,R,I):- I1 is I+1, ( A=X -> R=[A-I|C] ; R=C ), numerate(B,X,C,I1).
Testing:
5 ?- numerate([1,b,2,b],b,R,1).
R = [b-2, b-4].
6 ?- pos([1,b,2,b],b,2,P).
P = 4.
7 ?- pos([1,b,2,b],b,3,P).
P = 0.
I've corrected your code, without changing the logic, that seems already simple enough.
Just added a 'top level' handler, passing to actual worker pos1/4 and testing if worked, else returning 0 - a debatable way in Prolog, imo is better to allow to fail, I hope you will appreciate how adopting this (see comments) simplified your code...
pos(L,X,K,F):- pos1(L,X,K,F) -> true ; F=0.
% pos1([],H,K,F). useless: let it fail
% pos1([H],H,1,F). useless: already handled immediatly bottom
pos1([H|T],H,K,P):- K==1 -> P=1 ; NewK is K - 1, pos1(T,H,NewK,F), P is F + 1.
pos1([_|T],X,K,P):- pos1(T,X,K,F),P is F+1.
I hope you're allowed to use the if/then/else construct. Anyway, yields
7 ?- pos([a,b,c,b],b,2,Z).
Z = 4.
8 ?- pos([a,b,c,b],b,3,Z).
Z = 0.
Something like this. An outer predicate (this one enforces the specified constraints) that invokes an inner worker predicate:
kth( L , X , K , P ) :-
is_list( L ) , % constraint: L must be a list
nonvar(X) , % constriant: X must be an object
integer(K) , K > 0 % constraint: K must be a positive integer
kth( Ls , X , K , 1 , P ) % invoke the worker predicate with its accumulator seeded to 1
. % easy!
is_list/2 ensures you've got a list:
is_list(X) :- var(X) , !, fail .
is_list([]).
is_list([_|_]).
The predicate that does all the work is this one:
kth( [] , _ , _ , _ , 0 ) . % if we hit the end of the list, P is 0.
kth( [X|Ls] , X , K , K , K ) :- ! . % if we find the Kth desired element, succeed (and cut: we won't find another Kth element)
kth( [_|Ls] , X , K , N , P ) :- % otherwise
N < K , % - if we haven't got to K yet ...
N1 is N+1 , % - increment our accumulator , and
kth(Ls,X,K,N1,P) % - recurse down.
. % easy!
Though the notion of returning 0 instead of failure is Not the Prolog Way, if you ask me.

Prolog: fill list with n elements

Need to make a predicate, fill(L,X,N), where L is a list formed containing N elements X. If N <= 0 or N != length of L, L should be an empty list.
Here's what I've done, I've never been able to get the if, else.. structure working correctly in Prolog:
fill(L,X,N) :-
((N =< 0) ->
L = [];
length(L,I),
((N =\+= I) ->
L = [];
fill2(L,X,N))).
fill2([H|T],X,N2) :-
NewN = N2 - 1,
H = X,
fill2(T,X,NewN).
I also have a simpler version, that works except when N != length of L
fill(L,_,N) :-
N =< 0,
L = [].
fill([H|T],X,N) :-
NewN = N - 1,
H = X,
fill(T,X,NewN).
So, for example, fill(L,20,4) returns L = [20,20,20,20], but fill([20,20,20],X,2) doesn't return L = [].
You are misunderstanding how Prolog is meant to be used. Predicates are not exactly functions, so they can't return. If you bind an argument to an instantiated variable:
?- fill([a,a,a], a, 4).
fail
the only sensible thing is that Prolog tells you, "this is not correct". Anyway, in this example:
?- fill([b,b], a, 3).
What should happen? Should the list be [a,a,a], or should the second and third argument be b and 2?
A very simple fill:
fill([], _, 0).
fill([X|Xs], X, N) :- succ(N0, N), fill(Xs, X, N0).
It will fail if not used properly, but you should make clear how it needs to be used.
A note: try to avoid explicit unification in the body of the predicate definition.

Resources