prolog max_min_eval/2 solution issue - prolog

I want to create a predicate max_min_eval/2 or max_min_eval(List,Result) which read a list like this [1,min,2,max,4,max,3] -> (((1 min 2) max 4) max 3) in eclipse prolog and put the Result into a varialble. How can I do this?
This is my code:
%% seperate_lists/3
%% seperate_lists(List,Lets,Nums)
seperate_lists([], [], []) .
seperate_lists([X|Xs] , [X|Lets] , Nums) :-
not(number(X)),
!,
seperate_lists(Xs,Lets,Nums).
seperate_lists( [X|Xs] , Lets, [X|Nums] ) :-
number(X),
!,
seperate_lists(Xs,Lets,Nums).
seperate_lists([_|Xs], Lets, Nums) :-
seperate_lists(Xs,Lets,Nums).
%% max_min_eval/2
%% max_min_eval(List,Result)
max_min_eval_aux(_,[Result],Result).
max_min_eval_aux(Lets, Nums, Result) :-
[LH|LT] = Lets,
[NH1,NH2|NT] = Nums,
(
('max' = LH, max(NH1,NH2,Result), append([Result],NT,NewNums), NewLets = LT, max_min_eval_aux(NewLets,NewNums,Result));
('min' = LH, min(NH1,NH2,Result), append([Result],NT,NewNums), NewLets = LT, max_min_eval_aux(NewLets,NewNums,Result))
).
max_min_eval(List,Result) :-
seperate_lists(List,Lets,Nums),
max_min_eval_aux(Lets,Nums,Result).
The problem is that it doesn't work for ?- max_min_eval([1,max,10,min,2],Result), only works for 3 element list like this ?- max_min_eval([1,max,4],Result) or ?- max_min_eval([2,min,5],Result)

You may greedily evaluate the expression:
max_min_eval([First|Tail], Res):-
max_min_eval(Tail, First, Res).
max_min_eval([],Res, Res).
max_min_eval([Op, R|Tail], L, Res):-
max_min_eval_op(Op, L, R, L1),
max_min_eval(Tail, L1, Res).
max_min_eval_op(max, L, R, Res):-
max(L, R, Res).
max_min_eval_op(min, L, R, Res):-
min(L, R, Res).
Add these procedures if your prolog processor does not have max/3 and min/3:
max(A,B,M):- M is max(A,B).
min(A,B,M):- M is min(A,B).
Sample run:
?- max_min_eval([1,min,2,max,4,max,3], R).
R = 4.

Related

How to write the predicate Frequest(InList, OutList)?

I need to write the predicate Frequest(InList, OutList) to find the list
OutList of all elements that occur most frequently in the given InList.
Here is my code, help me write more professional and understandable for everyone please.
`counter([], _, 0).
counter([X|T], X, C) :- counter(T, X, C1), C is C1 + 1.
counter([X|T], Y, C) :- X == Y, counter(T, Y, C).
max_count([], , 0).
max_count([E|L], L1, C):-
counter(L1, E, C1),
maxcount(L, L1, C2),
C is max(C1, C2), !.
max_count_el([], , _, []) :- !.
max_count_el([X|L], L1, M, LR) :-
ffff(L, L1, M, LR2),
( counter(L1, X, C),
C == M,
+ member(X, LR2),
append(LR2, [X], LR);
LR = LR2
).
frequentest(L1, L2):-
max_count(L1, L1, R),
max_count_el(L1, L1, R, L2), !.`

Prolog program comprehension

This is the program I have:
foo(L,[H|R1]) :-
foo(L,R1,H).
foo([H],[],H).
foo([H|T],[H|T1],R) :-
foo(T,T1,R).
This is the query:
foo([1,2,3,4,5,6],X).
I don't understand what this program does, can someone help me and explain how does it work?
You could try to refactor it. If I start with:
foo(L, [H|R1]) :-
foo(L, R1, H).
foo([H], [], H).
foo([H|T], [H|T1], R) :-
foo(T, T1, R).
I can change the argument order foo(1,2,3) to foo(2,3,1):
foo(L,[H|R1]) :-
foo(R1, H, L).
foo([], H, [H]).
foo([H|T1], R, [H|T]) :-
foo(T1, R, T).
Now I can change the 2-nd argument of foo, and pass [H] instead of H:
foo(L, [H|R1]) :-
foo(R1, [H], L).
foo([], H, H).
foo([H|T1], R, [H|T]) :-
foo(T1, R, T).
Now you can rename the predicates to roll and append:
roll(L, [H|R1]) :-
append(R1, [H], L).
append([], H, H).
append([H|T1], R, [H|T]) :-
append(T1, R, T).
In Prolog, there is no need to understand the source code. Instead, let Prolog do this for you. Just ask the most general query:
?- foo(L,R).
L = [_A],
R = [_A]
; L = [_A,_B],
R = [_B,_A]
; L = [_A,_B,_C],
R = [_C,_A,_B]
; L = [_A,_B,_C,_D],
R = [_D,_A,_B,_C]
; L = [_A,_B,_C,_D,_E],
R = [_E,_A,_B,_C,_D]
; L = [_A,_B,_C,_D,_E,_F],
R = [_F,_A,_B,_C,_D,_E]
; L = [_A,_B,_C,_D,_E,_F,_G],
R = [_G,_A,_B,_C,_D,_E,_F]
; L = [_A,_B,_C,_D,_E,_F,_G,_H],
R = [_H,_A,_B,_C,_D,_E,_F,_G]
; ... .
Do you see a pattern here?
To understand it easier, put the recursive clause above the base one:
foo( [H | T], [H | T1], R) :- foo( /* T = [_|_] */
T, T1, R).
foo( [R], [], R).
So we advance along the two lists (that hold the same elements, H) until we hit the last element in the first list ([R]), at which point the second list is exhausted ([]), and we get hold of that last element (R).
This means that foo( A, B, R) :- append( B, [R], A).. Thus,
foo( L, [E | R1]) :- % foo( L, R1, E).
append( R1, [E], L). % R1 ++ [E] = L
i.e. foo( L, M) relates two lists L, M, where L is M with its first element E "flipped" to the list's end:
L : .............E
M : E.............
% ---- R1 -----

Prolog Shift n times a list function either way

I have to define a predicate nshift/3 that shift a list N times either way.
Examples:
?- nshift(3,[a,b,c,d,e,f,g,h],Shifted).
Shifted = [d,e,f,g,h,a,b,c]
?-­nshift(1,[1,2,3,4,5],Shifted).
Shifted = [2,3,4,5,1]
?-­nshift(-2,[a,b,c,d,e,f,g,h],Shifted).
Shifted = [g,h,a,b,c,d,e,f]
I created a code that would take care of the first two examples but I'm having problem with the last example where the N time is -2. Can somebody help me.
My code:
my_shift([], []).
my_shift([H|T], L) :-
append(T, [H], L).
nshift(0, L, L) :- !.
nshift(N, L1, L2) :-
N1 is N-1,
my_shift(L1, L),
nshift(N1, L, L2).
I have this old code
rotate(right, L, [T|H]) :- append(H, [T], L).
rotate(left, [H|T], L) :- append(T, [H], L).
Then, I think you could adapt your nshift/3 testing if the first argument is < 0, something like
nshift(0, L, L) :- !.
nshift(N, L1, L2) :-
N < 0, rotate(right, L1, L), N1 is N+1, nshift(N1, L, L2).
nshift(N, L1, L2) :-
N > 0, rotate(left, L1, L), N1 is N-1, nshift(N1, L, L2).
As hinted in another answer, your type of shift is usually called rotate. Rotates with non-negative N can be written in a nicely declarative way as
naive_rotate(N, Xs, Ys) :-
length(Bs, N),
append(As, Bs, Xs),
append(Bs, As, Ys).
While this works, people will be quick to point out that its termination properties are poor: when you backtrack into rotate/3, i.e. ask for more solutions, it will not terminate. This can be addressed by adding redundant conditions on the list lengths, viz.
rotate(N, Xs, Ys) :-
same_length(Xs, Ys),
leq_length(Bs, Xs),
length(Bs, N),
append(As, Bs, Xs),
append(Bs, As, Ys).
same_length([], []).
same_length([_|Xs], [_|Ys]) :- same_length(Xs, Ys).
leq_length([], _).
leq_length([_|Xs], [_|Ys]) :- leq_length(Xs, Ys).
This now works nicely for various query patterns, e.g.
?- rotate(2, [a,b,c,d,e], Ys). % gives Ys = [d,e,a,b,c]
?- rotate(2, Xs, [a,b,c,d,e]). % gives Xs = [c,d,e,a,b]
?- rotate(N, [a,b,c,d,e], Ys). % 5 solutions
?- rotate(N, Xs, [a,b,c,d,e]). % 5 solutions
?- rotate(N, Xs, Ys). % many solutions
You can then write your original nshift/3 as
nshift(N, Xs, Ys) :-
( N>=0 -> rotate(N, Xs, Ys) ; M is -N, rotate(M, Ys, Xs) ).

List in certain range

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).

how to stochastic search n-queen in prolog?

i'm implement stochastic search in prolog.
code is
queens_rand([],Qs,Qs) :- !.
queens_rand(UnplacedQs,SafeQs,Qs) :-
random_sort(UnplacedQs, UnplacedQs1),
select(UnplacedQs,UnplacedQs1,Q),
not_attack(SafeQs,Q,1),
queens_rand(UnplacedQs1,[Q|SafeQs],Qs),
!.
queen_solve_rand(N) :-
alloc(1,N,Ns),
queens_rand(Ns,[], Q),
write(Q), nl.
random_sort([],_) :- !.
random_sort(_,[]) :- !.
random_sort(Xs, Ys) :-
length(Ys, L),
rnd_select(Xs,L, Ys),
write('Ys : '),write(Ys),nl.
remove_at(X,[X|Xs],1,Xs).
remove_at(X,[Y|Xs],K,[Y|Ys]) :- K > 1,
K1 is K - 1, remove_at(X,Xs,K1,Ys).
rnd_select(_,0,[]).
rnd_select(Xs,N,[X|Zs]) :- N > 0,
length(Xs,L),
I is random(L) + 1,
remove_at(X,Xs,I,Ys),
N1 is N - 1,
rnd_select(Ys,N1,Zs).
not_attack([],_,_) :- !.
not_attack([Y|Ys],X,N) :-
X =\= Y+N, X =\= Y-N,
N1 is N+1,
not_attack(Ys,X,N1).
select([X|Xs],Xs,X).
select([Y|Ys],[Y|Zs],X) :- select(Ys,Zs,X).
but it returns false. i can't understand prolog well, but i have to implement it. and i cant find where is wrong.
Yyou should remove this rule : random_sort(_,[]) :- !.. It means that whatever is the first arg, the result is [].

Resources