List in certain range - prolog

I have a predicate that is supposed to form a list from list, taking into a new list only these numbers that are in a certain range. The predicate works, but suppose that I want to get a list not including bounds.
So I change the condition A >= L, A =< R to A > L, A < R, but then I only get "True", and Prolog outputs nothing.
What could be a problem here?
My code is:
range([], _, _, []).
range([A|L1], L, R, [A|L2]) :-
A>L,
A<R,
range(L1, L, R, L2).
range([A|L1], L, R, L2) :-
A=<L;
A>=R,
range(L1, L, R, L2).
This is what program outputs:
range([1,2,3,4,5], 1,4, X).
?- range([1,2,3,4,5,6,7,8,9,10], 1,3, X).
true .
This is what I want it to output:
?- range([1,2,3,4,5,6,7,8], 1, 5, X).
X = [2,3,4] .

I think you forgot needed parenthesis
range([A|L1], L, R, L2) :-
( A=<L ; A>=R ),
range(L1, L, R, L2).
otherwise, when A=<L, you loose the recursive call, and then variables remain not instantiated.

Priority of the conjunction and disjuntion, , and ;, makes it necessary to write the third clause as:
range([A|L1], L, R, L2) :-
( A=<L
; A>=R
),
range(L1, L, R, L2).

Related

How do I see a detailed order (execution) for a Prolog query?

Let's say I have this Prolog program:
loves(vincent, mia).
loves(marcellus, mia).
jealous(A, B) :- loves(A, C), loves(B, C).
With query jealous(A,B). I'm very new to Prolog and I'd like to know how is it possible to see the exact order the program will be running and taking its ways for this query? I have tried using trace, jealous(A,B). command but it has only given me that:
Isn't there any more detailed solution for that? :/
Have you seen the Prolog Visualizer?
When you get to the page be sure to click on the icons in the upper right to learn more.
Enjoy.
Screenshot after step 10 of 49.
Screenshot for example given after all steps.
The Prolog Visualizer uses a slightly nonstandard way to enter a query by ending the query with a question mark (?), e.g.
jealous(A,B)?
If you do not post a query in the input area on the left you will receive an error, e.g.
The input for the Prolog Visualizer for your example is
loves(vincent, mia).
loves(marcellus, mia).
jealous(A, B) :- loves(A, C), loves(B, C).
jealous(A,B)?
When the Prolog Visualizer completes your example, notice the four results in green on the right
If you are using SWI-Prolog and after you understand syntactic unification, backtracking and write more advanced code you will find this of use:
Overview of the SWI Prolog Graphical Debugger
For other useful Prolog references see: Useful Prolog references
If the Prolog system has callable_property/2 and sys_rule/3, then one can code
a smart "unify" port as follows, showing most general unifiers (mgu's`):
:- op(1200, fx, ?-).
% solve(+Goal, +Assoc, +Integer, -Assoc)
solve(true, L, _, L) :- !.
solve((A, B), L, P, R) :- !, solve(A, L, P, H), solve(B, H, P, R).
solve(H, L, P, R) :- functor(H, F, A), sys_rule(F/A, J, B),
callable_property(J, sys_variable_names(N)),
number_codes(P, U), atom_codes(V, [0'_|U]), shift(N, V, W),
append(L, W, M), H = J, reverse(M, Z), triage(M, Z, I, K),
offset(P), write_term(I, [variable_names(Z)]), nl,
O is P+1, solve(B, K, O, R).
% triage(+Assoc, +Assoc, -Assoc, -Assoc)
triage([V=T|L], M, R, [V=T|S]) :- var(T), once((member(W=U, M), U==T)), W==V, !,
triage(L, M, R, S).
triage([V=T|L], M, [V=T|R], S) :-
triage(L, M, R, S).
triage([], _, [], []).
% shift(+Assoc, +Atom, -Assoc)
shift([V=T|L], N, [W=T|R]) :-
atom_concat(V, N, W),
shift(L, N, R).
shift([], _, []).
% offset(+Integer)
offset(1) :- !.
offset(N) :- write('\t'), M is N-1, offset(M).
% ?- Goal
(?- G) :-
callable_property(G, sys_variable_names(N)),
shift(N, '_0', M),
solve(G, M, 1, _).
Its not necessary to modify mgu's retrospectively, since a solution to a
Prolog query is the sequential composition of mgu's. Here is an example run:
?- ?- jealous(A,B).
[A_0 = X_1, B_0 = Y_1]
[H_1 = mia, X_1 = vincent]
[Y_1 = vincent]
A = vincent,
B = vincent ;
[Y_1 = marcellus]
A = vincent,
B = marcellus ;
Etc..
This is a preview of Jekejeke Prolog 1.5.0 the new
predicate sys_rule/3, its inspired by the new
predicate rule/2 of SWI-Prolog, but keeps the
clause/2 argument of head and body and uses a predicate
indicator.

Lists size multiplication

I'm new to Prolog and I'm trying to get my head around lists. The problem I'm struggling with is:
Given numbers in the form of lists (1 : [x], 3: [x, x, x]), implement the 'times' predicate /3.
E.g.: times([x, x], [x, x, x], R).
R = [x, x, x, x, x, x].
The plus, and successor predicates where 2 previous points of the exercise. I know I'm not using the successor predicate, but it didn't seem that useful later on.
This is what i've tried so far
successor([], [x]).
successor([X|T], R) :-
append([X|T], [X], R).
plus(L1, L2, R) :- append(L1, L2, R).
times([], _, []).
times(_, [], []).
times([_], L, L).
times(L, [_], L).
times([_|T], L2, R) :- plus(L2, R, RN),
times(T, L2, RN).
The output is:
R is [].
I think you make things too complicated here. You can define successor as:
successor(T, [x|T]).
We can define plus/3 as:
plus([], T, T).
plus([x|R], S, [x|T]) :-
plus(R, S, T).
This is more or less the implementation of append/3, except that here we check if the first list only contains x.
For times/3 we know that if the first item is empty, the result is empty:
times([], _, []).
and for a times/3 where the first item has shape [x|R], we need to add the second item to the result of a call to times/3 with R:
times([x|R], S, T) :-
times(R, S, T1),
plus(S, T1, T).
So putting it all together, we obtain:
successor(T, [x|T]).
plus([], T, T).
plus([x|R], S, [x|T]) :-
plus(R, S, T).
times([], _, []).
times([x|R], S, T) :-
times(R, S, T1),
plus(S, T1, T).

PROLOG - LCM of couples in list

I want to find the Least Common Multiple (LCM) of couples from a list. But in the following way:
For example if I have this list:
L1 = [1,2,3,4,5].
I want to produce this list:
L2 = [1,2,6,12,60].
I use the first element of L1 as first element of L2 and the rest follow this form:
L2[0] = L1[0]
L2[i+1] = lcm( L1[i+1] , L2[i] )
Here is what I've done so far, but it doesn't work. Always printing false.
%CALL_MAKE----------------------------------------
%Using call_make to append Hd to L2 list
call_make([Hd|Tail], Result) :-
make_table(Tail, [Hd], Result).
%MAKE_TABLE---------------------------------------
%Using make_table to create the rest L2
make_table([],Res,Res).
make_table([Head|Tail], List, Result) :-
my_last(X, List),
lcm(Head, X, R),
append(List, R, Res),
make_table(Tail, Res, Result).
%last element of a list---------------------------
my_last(X,[X]).
my_last(X,[_|L]):- my_last(X, L).
%GCD----------------------------------------------
gcd(X, 0, X) :- !.
gcd(X, Y, Z) :-
H is X rem Y,
gcd(Y, H, Z).
%LCM----------------------------------------------
lcm(X,Y,LCM):-
gcd(X,Y,GCD),
LCM is X*Y//GCD.
I want to run the program and get this:
?- call_make([1,2,3,4,5], Result).
Result = [1,2,6,12,60].
append/3 is taking two lists to concatenate, while here:
append(List, R, Res),
R is a scalar. Change it to
append(List, [R], Res),

Splitting a list into 2 lists at a pivot in prolog

I want to split a list into 2 lists at a pivot P, if the number is less than P it goes into L1 and if it is greater than P then it will go into L2.
This is what I have so far, I am able to split a list L into L1 = [[],[]] in this form. But I want to split the list into 2 lists L1, and L2, how would I do that?
split(L,P,L1):-
split(L,P,[],L1).
split([],_,[],[]).
split([],_,X,[X]) :- X \= [].
split([P|T],P,[],L1) :- split(T,P,[],L1).
split([P|T],P,L,[L|L1]) :- L \= [], split(T,P,[],L1).
split([H|T],P,S,L1) :- H \= P, append(S, [H], S2), split(T,P,S2,L1).
You only need three rules to implement this predicate:
:- use_module(library(clpfd)).
split([], _, [], []).
split([H|T], P, L1, [H|T2]) :-
H #>= P,
split(T, P, L1, T2).
split([H|T], P, [H|T1], L2) :-
H #< P,
split(T, P, T1, L2).
The code is fairly straightforward
Note that, because of library(clpfd), this predicate also works e.g. when the initial list and the pivot are not known:
?- split(L,P,[5,47],[101]).
L = [101, 5, 47],
P in 48..101 ;
L = [5, 101, 47],
P in 48..101 ;
L = [5, 47, 101],
P in 48..101 ;
false.
Using partition/4
As mentionned in a comment, you can use partition/4 to do this:
split(L, P, L1, L2) :-
partition(zcompare(>,P), L, L1, L2).
However, this will not exhibit as many different behaviours as the first implementation.

print out letter squences in prolog

I have to write out a program in Prolog that prints out letter sequences, Implement in Prolog a predicate twist/2 for ‘twisting’ pairs of entries of a list and discarding the entries in between. More precisely,
• Interchange the 1st and 2nd entries,
• Discard the 3rd entry,
• Interchange the 4th and 5th entries,
• Discard the 6th entry and so on as follows:
twist([’B’,r,a,d,f,o,r,d], T)--->
twist([’B’,r,a,d,f,o,r,d], [], y, T)--->
twist([a,d,f,o,r,d], [’B’,r], n, T)--->
twist([d,f,o,r,d], [’B’,r], y, T)--->
twist([o,r,d], [d,f,’B’,r], n, T)--->
twist([r,d], [d,f,’B’,r], y, T)--->
twist([], [r,d,d,f,’B’,r], n, T)--->
reverse([r,d,d,f,’B’,r], T)--->
T = [r,’B’,f,d,d,r] ---> success
So far I have:
twist(L,T) :-
twist(L, [], y, T). % clause 0: invoke auxiliary predicate
twist([], Acc, L) :- reverse(Acc, L),
twist(A,G,_|T), Acc, L) :- twist(T,[A,G|Acc], L),
twist([A,G], Acc, L) :- twist([],[A,G|Acc], L),
twist([], Acc, L) :- reverse(Acc, L).
I'm sure that's right but i keep getting the same error.
here's the full error message:
4 ?- twist([b, r ,a ,d ,f ,o ,r ,d], T).
ERROR: twist/2: Undefined procedure: twist/4
ERROR: However, there are definitions for:
ERROR: twist/2
Exception: (7) twist([b, r, a, d, f, o, r, d], [], y, _G2583) ?
Any help would be great.
try this:
twist([],[]).
twist([X],[X]).
twist([X,Y],[Y,X]).
twist([X,Y,_|Tail],[Y,X|NewTail]):- twist(Tail, NewTail).
And then ask:
?- twist([b, r ,a ,d ,f ,o ,r ,d], T).
T = [r, b, f, d, d, r] ;
false.
credits go to #lurker.

Resources