Related
I am having a problem while creating a list which I will the use to fill. I am trying to create it with independent variables, so that I can then unify with a maplist with some other lists.
For this, I did:
length(Subs, Len),
maplist(=([_, _, _]), Subs),
however, this results in this:
Subs = [[_22998, _23020, _23042], [_22998, _23020, _23042], [_22998, _23020, _23042]].
And so, when I try to unify the next way:
maplist(nth1(1), Subs, Com1),
maplist(nth1(2), Subs, Perm_sub),
maplist(nth1(3), Subs, Com3).
with:
Perm_sub = [5, 7, 6],
Com1 = [P23, P34, P36],
Com3 = [1, 3, 2].
It fails, because 5 unifies with _22998, and thus collides with 7. Is there a simple, elegant way of doing what I intend, or do I have to create a new function to handle this, and if so, how do I do the function?
You can create an auxiliary predicate as following:
triple([_, _, _]).
And ask:
?- length(L, 3), maplist(triple, L).
L = [[_2404, _2410, _2416], [_2422, _2428, _2434], [_2440, _2446, _2452]].
Alternatively, you can use a lambda expression as following:
?- length(L, 3), maplist([[_,_,_]]>>true, L).
L = [[_7198, _7204, _7210], [_7276, _7282, _7288], [_7354, _7360, _7366]].
EDIT 10/05/2021
Notice that variables used in a term are shared with their environment (they are "global", not lambda bound) and, consequently, they persist through all calls of maplist. For example, in the following query, variable X is instantiated with 1 and, after that, its value will persist through the next calls.
?- trace, maplist(=(X), [1,Y,1]).
^ Call: (11) apply:maplist(=(_1882), [1, _1892, 1]) ? creep
Call: (12) apply:maplist_([1, _1892, 1], user: =(_1882)) ? creep
Call: (13) _1882=1 ? creep
Exit: (13) 1=1 ? creep
Call: (13) apply:maplist_([_1892, 1], user: =(1)) ? creep
Call: (14) 1=_1892 ? creep
Exit: (14) 1=1 ? creep
Call: (14) apply:maplist_([1], user: =(1)) ? creep
Call: (15) 1=1 ? creep
Exit: (15) 1=1 ? creep
Call: (15) apply:maplist_([], user: =(1)) ? creep
Exit: (15) apply:maplist_([], user: =(1)) ? creep
Exit: (14) apply:maplist_([1], user: =(1)) ? creep
Exit: (13) apply:maplist_([1, 1], user: =(1)) ? creep
Exit: (12) apply:maplist_([1, 1, 1], user: =(1)) ? creep
^ Exit: (11) apply:maplist(user: =(1), [1, 1, 1]) ? creep
X = Y, Y = 1.
On the other hand, variables used as predicate arguments are "local" and their instantiations do not persist from one call to another. For example:
?- [user].
| equal(_X).
| ^Z
% user://1 compiled 0.02 sec, 1 clauses
true.
?- trace, maplist(equal, [1,Y,1]).
^ Call: (11) apply:maplist(equal, [1, _1752, 1]) ? creep
Call: (12) apply:maplist_([1, _1752, 1], user:equal) ? creep
Call: (13) equal(1) ? creep
Exit: (13) equal(1) ? creep
Call: (13) apply:maplist_([_1752, 1], user:equal) ? creep
Call: (14) equal(_1752) ? creep
Exit: (14) equal(_1752) ? creep
Call: (14) apply:maplist_([1], user:equal) ? creep
Call: (15) equal(1) ? creep
Exit: (15) equal(1) ? creep
Call: (15) apply:maplist_([], user:equal) ? creep
Exit: (15) apply:maplist_([], user:equal) ? creep
Exit: (14) apply:maplist_([1], user:equal) ? creep
Exit: (13) apply:maplist_([_1752, 1], user:equal) ? creep
Exit: (12) apply:maplist_([1, _1752, 1], user:equal) ? creep
^ Exit: (11) apply:maplist(user:equal, [1, _1752, 1]) ? creep
true.
I m trying to do a list member(member/2) with my own predicate.
starting this example
?-app([a,r,t],[t,s,m,n,a],L3).
L3=[a,t]
I tried to do similar exercises so I did this with prolog:
app([],_,[]).
app([H|T],[H1,T1],[H|L1]):- H is H1, L1 is H,! ,app(T,T1,L1).
app([_H|T],L,L2):- app(T,L,L2).
and all working regular, but the value in a list will be overwritten during the execution, in fact, the trace is :
trace, app([3,2],[3,5],X).
Call: (9) app([3, 2], [3, 5], _7426) ? creep
Call: (10) 3 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) _7736 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) app([2], 5, 3) ? creep
Call: (11) app([], 5, 3) ? creep
Fail: (11) app([], 5, 3) ? creep
Fail: (10) app([2], 5, 3) ? creep
Fail: (9) app([3, 2], [3, 5], _7426) ? creep
false.
I tried to make a modify on the base case in this way:
app([],_,_N).
but the output is every wrong:
trace, app([3,2],[3,5],X).
Call: (9) app([3, 2], [3, 5], _7426) ? creep
Call: (10) 3 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) _7736 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) app([2], 5, 3) ? creep
Call: (11) app([], 5, 3) ? creep
Exit: (11) app([], 5, 3) ? creep
Exit: (10) app([2], 5, 3) ? creep
Exit: (9) app([3, 2], [3, 5], [3|3]) ? creep
X = [3|3].
where I m wrong?
I think you're trying to do a sublist/2 predicate:
%! sublist(Sub, List)
% is true if Sub is a list that occurs in
% some position in List
sublist(Sub, List) :-
% first partition off some tail of the list
append(_Prefix, Tail, List),
% then get some prefix of the tail, this is a sublist
append(Sub, _TailTail, Tail).
There's more ways to do this, but I think append/3 is simple to
understand. This is a different problem from member/2, which is finding elements in a list, here our problem is to carve up a list into chunks, hence the very different implementation than you see in member/2. You'll often find in Prolog the first step to a solution is to define the problem well. Good luck in your Prolog learning.
I am trying to build a program that takes two integers (for example, 4 and 15) and returns the multiples of the first integer that divide into the second integer.
My program is as follows:
divisible(D,U,X):-
divisible_ext(D,U,D,X).
divisible_ext(D,U,D,X):-
U < D,
!.
divisible_ext(D,U,S,X):-
U > D,
D1 is D + S,
divisible_ext(D1,U,S,X1),
X is D.
As far as I am aware, my program should fail the base case with each call until the D value is greater than U (so with 4 and 15, 16 > 15). However in the trace, I can see that the base case is only called the first time, and then never again. Thus when D = 16, the U > D call fails and the entire program fails.
Why is the base case only being called once? Is there something I am not understanding about Prolog that I need to know, or is there a change to my code that I should make?
Edit: Here is my trace:
[trace] 20 ?- divisible(4,15,X).
Call: (7) divisible(4, 15, _G9543) ? creep
Call: (8) divisible_ext(4, 15, 4, _G9543) ? creep
Call: (9) 15<4 ? creep
Fail: (9) 15<4 ? creep
Redo: (8) divisible_ext(4, 15, 4, _G9543) ? creep
Call: (9) 15>4 ? creep
Exit: (9) 15>4 ? creep
Call: (9) _G9622 is 4+4 ? creep
Exit: (9) 8 is 4+4 ? creep
Call: (9) divisible_ext(8, 15, 4, _G9625) ? creep
Call: (10) 15>8 ? creep
Exit: (10) 15>8 ? creep
Call: (10) _G9625 is 8+4 ? creep
Exit: (10) 12 is 8+4 ? creep
Call: (10) divisible_ext(12, 15, 4, _G9628) ? creep
Call: (11) 15>12 ? creep
Exit: (11) 15>12 ? creep
Call: (11) _G9628 is 12+4 ? creep
Exit: (11) 16 is 12+4 ? creep
Call: (11) divisible_ext(16, 15, 4, _G9631) ? creep
Call: (12) 15>16 ? creep
Fail: (12) 15>16 ? creep
Fail: (11) divisible_ext(16, 15, 4, _G9631) ? creep
Fail: (10) divisible_ext(12, 15, 4, _G9628) ? creep
Fail: (9) divisible_ext(8, 15, 4, _G9625) ? creep
Fail: (8) divisible_ext(4, 15, 4, _G9543) ? creep
Fail: (7) divisible(4, 15, _G9543) ? creep
false.
Why is the base case only being called once?
The base case is
divisible_ext(D,U,D,X) :-
and the other case is
divisible_ext(D,U,S,X) :-
Notice that on the first call
Call: (8) divisible_ext(4, 15, 4, _G9543) ? creep
divisible_ext(D, U, D, X) :- <-- Base case
divisible_ext(D, U, S, X) :- <-- Other case
For the base case D = 4 for both D and
for the other case D = 4 and S = 4
so both predicates can be called.
Notice on the second call
Call: (9) divisible_ext(8, 15, 4, _G9625) ? creep
divisible_ext(D, U, D, X) :- <-- Base case
divisible_ext(D, U, S, X) :- <-- Other case
For the base case D = 8 and D = 4 and
for the other case D = 4 and S = 4
so the base can not be called because the first D is now 8 and second D is 4 which means the unification will not work and thus the predicate can not be called.
i am trying to implement Kadane's Algorithm in Prolog.
One of the requirements is a tail call (recursion).
I have tried many possibilities but without success.
Here is my code:
max_sum(L, S) :-
S is 0,
H is 0,
max_sum(L, H, S).
max_sum([], S, S).
max_sum([X | L], H, S) :-
( H + X < 0 -> NewH is 0; NewH is H + X),
( S < H + X -> NewS is NewH; NewS is S),
length(L, N),
( N < 1 -> max_sum(L, NewS, NewS); max_sum(L, NewH, NewS)).
NewH, NewS are temp values (we cant assign a value twice in Prolog right?).
Can i ask for a hint?
Edit:
[trace] ?- max_sum([1, 2, 3], S).
Call: (7) max_sum([1, 2, 3], _G8907) ? creep
Call: (8) _G8907 is 0 ? creep
Exit: (8) 0 is 0 ? creep
Call: (8) _G8991 is 0 ? creep
Exit: (8) 0 is 0 ? creep
Call: (8) max_sum([1, 2, 3], 0, 0) ? creep
Call: (9) 0+1<0 ? creep
Fail: (9) 0+1<0 ? creep
Redo: (8) max_sum([1, 2, 3], 0, 0) ? creep
Call: (9) _G8994 is 0+1 ? creep
Exit: (9) 1 is 0+1 ? creep
Call: (9) 0<0+1 ? creep
Exit: (9) 0<0+1 ? creep
Call: (9) _G8997 is 1 ? creep
Exit: (9) 1 is 1 ? creep
Call: (9) length([2, 3], _G8998) ? creep
Exit: (9) length([2, 3], 2) ? creep
Call: (9) 2<1 ? creep
Fail: (9) 2<1 ? creep
Redo: (8) max_sum([1, 2, 3], 0, 0) ? creep
Call: (9) max_sum([2, 3], 1, 1) ? creep
Call: (10) 1+2<0 ? creep
Fail: (10) 1+2<0 ? creep
Redo: (9) max_sum([2, 3], 1, 1) ? creep
Call: (10) _G9000 is 1+2 ? creep
Exit: (10) 3 is 1+2 ? creep
Call: (10) 1<1+2 ? creep
Exit: (10) 1<1+2 ? creep
Call: (10) _G9003 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) length([3], _G9004) ? creep
Exit: (10) length([3], 1) ? creep
Call: (10) 1<1 ? creep
Fail: (10) 1<1 ? creep
Redo: (9) max_sum([2, 3], 1, 1) ? creep
Call: (10) max_sum([3], 3, 3) ? creep
Call: (11) 3+3<0 ? creep
Fail: (11) 3+3<0 ? creep
Redo: (10) max_sum([3], 3, 3) ? creep
Call: (11) _G9006 is 3+3 ? creep
Exit: (11) 6 is 3+3 ? creep
Call: (11) 3<3+3 ? creep
Exit: (11) 3<3+3 ? creep
Call: (11) _G9009 is 6 ? creep
Exit: (11) 6 is 6 ? creep
Call: (11) length([], _G9010) ? creep
Exit: (11) length([], 0) ? creep
Call: (11) 0<1 ? creep
Exit: (11) 0<1 ? creep
Call: (11) max_sum([], 6, 6) ? creep
Exit: (11) max_sum([], 6, 6) ? creep
Exit: (10) max_sum([3], 3, 3) ? creep
Exit: (9) max_sum([2, 3], 1, 1) ? creep
Exit: (8) max_sum([1, 2, 3], 0, 0) ? creep
Exit: (7) max_sum([1, 2, 3], 0) ? creep
In Call(11) i have a good result (6) from this simple example. How can I end the function at this point without returning? It is my problem.
Result from this code is S = 0, not S = 6.
Final edit (working code):
max_sum(L, S) :-
max_sum(L, 0, 0, S).
max_sum([], _, S, S).
max_sum([X | L], H, F, S) :-
NewH is max(0, H + X),
(F < H + X -> NewF is NewH; NewF is F),
max_sum(L, NewH, NewF, S).
Where:
S - final result,
F - maximum_so_far,
H - maximum_ending_here,
X - head of list,
L - list,
NewH, NewF - temp values.
Thanks for the help :)
This question is, in fact, a duplicate of
"Finding the maximum sublist in Prolog".
There is a bounty is offered for it, so it cannot be flagged as a duplicate.
I propose using my previous solution—it is based on clpfd and runs with SWI-Prolog.
I propose a slightly altered version of the solution proposed by #repeat:
:- use_module(library(clpfd)).
zs_max([Z|Zs], MSF) :-
zs_max_(Zs, Z, Z, MSF).
zs_max_([], _, MSF, MSF).
zs_max_([Z|Zs], MEH0, MSF0, MSF) :-
max(Z, MEH0+Z) #= MEH1,
max(MSF0, MEH1) #= MSF1,
zs_max_(Zs, MEH1, MSF1, MSF).
First, the sample queries from the original solution that yield the same results:
?- zs_max([-2,1,-3,4,-1,2,1,-5,4], Max).
Max = 6
?- zs_max([-2,3,4,-5,8,-12,100,-101,7], Max).
Max = 100
However this version is more general, in that it works with arbitrary values (as suggested by #false in the comment to solution). This is accomplished by starting with the value of the first element of the list instead of 0. Thus the following query yields a different result:
?- zs_max([-2,-3,-4], X).
X = -2
?- zs_maxmum([-2,-3,-4], X).
X = 0
Another difference is that the empty list has no solution:
?- zs_max([], X).
no
?- zs_maxmum([], X).
X = 0
I think this behaviour is more reasonable, as the empty list has no sublist and hence no sums of sublists from which to choose a maximum. However, if desired, a special case for the empty list can be easily added:
zs_max([], replaceThisWithAReasonableValue).
the standard way is to add an output parameter, that gets unified when the recursion stops. Something like
max_sum(L, S) :-
max_sum(L, 0, 0, S).
max_sum([], _, S, S).
...
Then, your code is way more complex than needed: both versions listed on Wikipedia don't require any test, or length/2 computation.
Try to simplify it leaving just the computation (you can use for instance Max_ending_here is max(0, H + X), and the tail recursive call.
Q. Given [1,2,3] in Prolog get back [6,5,3] by reverse accumulation
I have the start code:
accumalate([H],[H]).
accumalate([H1 | H2], [Hnew, H2]),
Hnew is H1 + H2.
....
I am looking for basic Prolog solution.
We are not here to do you homework for you. So the best we can do is provide you with some tips. So ask yourself these questions:
What are the base cases here (for which inputs is the output immediate)?
You have accumulate([N], [N])., but what about empty lists?
In what order must the additions be performed?
More specifically, which elements must be added first?
Other than that, I can tell you that you can solve this using three clauses. No other predicates required. Good luck!
Bonus: you may want to define the head of the recursive clause as follows:
accumulate([N|T], [N1,N2|T2]).
Here is my take:
accumulate([],[]).
accumulate([H|T], [H1|T1]):-
sum([H|T],H1),
accumulate(T,T1).
sum([],0).
sum([H|T],Y):-
sum(T,Y1),
Y is H + Y1.
You can of course use a built-in sumlist/2 in place of the hand-crafted sum/2 if you prefer that.
Once you are done with the basic implementation , Try solving this problem in O(n) time. The idea is to start from the first element and keep on adding it to a secondary list till your original list is empty. The secondary list is the reverse list which you need.
If you append the two lists in your recursive step, you will end up having a O(N^2) complexity.
ac([], 0, []).
ac([H|T], ST, [ST|Res]) :-
ac(T, X, Res),
ST is H + X.
accum(List, Res) :-
ac(List, _, Res).
[trace] ?- accum([1,2,3], X).
Call: (6) accum([1, 2, 3], _G376) ? creep
Call: (7) ac([1, 2, 3], _G458, _G376) ? creep
Call: (8) ac([2, 3], _G461, _G454) ? creep
Call: (9) ac([3], _G464, _G457) ? creep
Call: (10) ac([], _G467, _G460) ? creep
Exit: (10) ac([], 0, []) ? creep
Call: (10) _G459 is 3+0 ? creep
Exit: (10) 3 is 3+0 ? creep
Exit: (9) ac([3], 3, [3]) ? creep
Call: (9) _G456 is 2+3 ? creep
Exit: (9) 5 is 2+3 ? creep
Exit: (8) ac([2, 3], 5, [5, 3]) ? creep
Call: (8) _G453 is 1+5 ? creep
Exit: (8) 6 is 1+5 ? creep
Exit: (7) ac([1, 2, 3], 6, [6, 5, 3]) ? creep
Exit: (6) accum([1, 2, 3], [6, 5, 3]) ? creep
X = [6, 5, 3].