Related
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.
I am trying to make this Prolog query:
placeRedBlocks(4, X), findall(Y, loopReplace(X, Y), A).
which outputs this:
A = [[r, r, r, b], [r, r, r, r], [b, r, r, r]],
X = [b, b, b, b]
work in the code if I only type in
placeRedBlocks(4, X).
The code I am using:
printList([ ]).
printList([H|T]) :- print(H), nl, printList(T).
placeRedBlocks(Length, List) :-
findall('b', between(1, Length, _), List).
replace([_|T], 0, X, [X|T]).
replace([H|T], I, X, [H|R]):-
I > -1,
NI is I-1,
% write([H|T]),
replace(T, NI, X, R), !.
% replace(L, _, _, L).
placeRedBlockUnit(A,_,0,_,A):- !.
placeRedBlockUnit(Line,Index,NumElm,Elm,NLine) :-
replace(Line,Index,Elm,BLine),
Index1 is Index+1,
NumElm1 is NumElm-1,
placeRedBlockUnit(BLine,Index1,NumElm1,Elm,NLine).
loopReplace(ListToReplace, NewList) :-
length(ListToReplace, Len),
TotalCount is Len-3,
between(0, TotalCount, Iterations),
between(3, Len, Size),
placeRedBlockUnit(ListToReplace, Iterations, Size, 'r', NewList).
Unfortunately, if I change placeRedBlocks to this it doesn't work.
placeRedBlocks(Length, List) :-
findall('b', between(1, Length, _), List),
findall(Y, loopReplace(List, Y), _).
and I only get:
X = [b, b, b, b]
What is happening here?
Is it possible for it to return back to the same list?
I realized that as long as I use a variable twice in a predicate I don't need to make it a parameter to my predicate.
Changing this
placeRedBlocks(Length, List) :-
findall('b', between(1, Length, _), List)
to this
placeRedBlocks(Length, List3) :-
findall('b', between(1, Length, _), List),
findall(Y, loopReplace(List, Y), List2),
append([List], List2, List3).
made me able to use the queries in the predicate while also keeping the predicate at 2 parameters.
i want to get a sublist of all elements that assemble specific word for example
for the call
assemble([hello,'',world,hi,bye,good,well], 'hello world', A).
program should print
A=[hello,'',world]
for the call
assemble([abc,123,ab,c,123],'abc123', A).
program should print
A=[abc,123];
A=[ab,c,123];
thanks for your help.
matchwords(W1, W2, Results) :-
setof(R, matchw(W1, W2, R), RSet), % Collect all the matching substrings
% and their lengths
reverse(RSet, Set), % Order by longest first
highest(Set, Results). % keep only the highest ones
matchw(W1, W2, N-Result) :-
atom_chars(W1, A1),
atom_chars(W2, A2),
matchl(A1, A2, R),
length(R, N),
atom_chars(Result, R).
matchl([H|T1], [H|T2], [H|T]) :-
matchl(T1, T2, T).
matchl([H1|T1], [H2|T2], R) :-
H1 \= H2,
( matchl(T1, [H2|T2], R) ; matchl([H1|T1], T2, R) ).
matchl([], _, []).
matchl([_|_], [], []).
highest([_-W], [W]).
highest([N1-W1,N2-_|_], [W1]) :-
N1 > N2.
highest([N1-W1,N2-W2|T], [W1|WT]) :-
N1 = N2,
highest([N2-W2|T], WT).
I am working on a prolog problem which goes like this,
replace all the occurrences of WordList in List with the respective characters in the CharsList to produce the NewList.
e.g. newList([s,e,e,y,o,u,a,t,e],[c,u,8],[s,e,e,’’,y,o,u,'',l,a,t,e,r,'',k,a,t,e], X) binds X to [c,'',u,'',l,8,r,'',k,8].
I have managed to do is this
word(_, _, [], []).
word(M, S, [M|T], [S|T1]) :- word(M, S, T, T1).
word(M, S, [H|T], [H|T1]) :- H \= M, word(M, S, T, T1).
which does this
| ?- word(see, c, [see,you,later,kate], X).
X = [c,you,later,kate]
I'm kinda stuck on what to do next for a list. Can anyone give some pointers about what direction I should take?
If i use substitution like above and sublists could it be done?
subst(_,[],_,[]).
subst(X,[X|L],A,[A|M]):-!,subst(X,L,A,M).
subst(X,[Y|L],A,[Y|M]):-subst(X,L,A,M).
sublist([X|L], [X|M]):- prefix(L,M),!.
sublist(L,[_|M]):- sublist(L,M).
prefix([],_).
prefix([X|L],[X|M]):-prefix(L,M).
append/2 it's a simple library predicate made available from SWI-Prolog lists library, handy to work on lists...
newList(Ws, Cs, L, L2) :-
correspond(Ws, Cs, W, C),
append([Skip, W, Rest], L),
append([Skip, [C], Rest], L1),
!, newList(Ws, Cs, L1, L2).
newList(_, _, L, L).
correspond([X,Y,Z|_], [C|_], [X,Y,Z], C).
correspond([_,_,_|Ws], [_|Cs], W, C) :-
correspond(Ws, Cs, W, C).
This snippet arbitrarly assumes a matching of 3 characters from WordList. I will let you to generalize as required...
Well, I'd probably do something like this:
replace( [] , _ , [] ) .
replace( [Word|Words] , Map , [Replacement|Replacements] ) :-
transform( Word , Map , Replacement ) ,
replace( Words , Map , Replacements )
.
transform( X , M , Y ) :- ( member( X:Y , M ) -> true ; X=Y ) .
That should let you say something like
replace( [see,you,later,kate] , [see:c,you:u,later:l8r,kate:k8], X ) .
and get back
X = [c,u,l8r,k8] .
newList(Ws, Cs, L, L2) :- correspond(Ws, Cs, W, C),
append([Skip, W, Rest], L),
append([Skip, [C], Rest], L1),!,
newList(Ws, Cs, L1, L2).
newList(_, _, L, L).
correspond([X,Y,Z|_], [C|_], [X,Y,Z], C).
correspond([_,_,_|Ws], [_|Cs], W, C):- correspond(Ws, Cs, W, C).
append([], []).
append([L|Ls], As) :- join(L, Ws, As),
append(Ls, Ws).
join([],X,X).
join([X|L1],L2,[X|L3]):- join(L1,L2,L3).
like that works even in ISO.
code by CapelliC
/* substitute(X,Y,Xs,Ys) is true if the list Ys is the result of substituting Y for all occurrences of X in the list Xs.
This is what I have so far:
subs(_,_,[],[]).
subs(X,Y,[X|L1],[Y|L2]):- subs(X,Y,L1,L2).
subs(X,Y,[H|L1],[H|L2]):- X\=H, not(H=[_|_]), subs(X,Y,L1,L2).
subs(X,Y,[H|_],[L2]):- X\=H, H=[_|_], subs(X,Y,H,L2).
My code works except it omits the elements following the nested list. For example:
?- subs(a,b,[a,[a,c],a],Z).
Z = [b, [b, c]] .
What should I add to this program?
Here is how you could write it using (... -> ... ; ...):
subs(_, _, [], []).
subs(X, Y, [H1|T1], [H2|T2]) :-
(H1 == X ->
H2 = Y
; is_list(H1) ->
subs(X, Y, H1, H2),
subs(X, Y, T1, T2)
;
H1 = H2,
subs(X, Y, T1, T2)
).
The problem is that once you find a nested list, you forget about whatever is behind that nested list. Instead, after recursing with the nested nest, simply continue as before. Thus, you should change the last clause as follows:
subs(X,Y,[H|L1],[H2|L2]):- X\=H, H=[_|_], subs(X,Y,H,H2), subs(X, Y, L1, L2).
Aside from that, there are a couple of ways in which you can improve the code:
Use cuts (!/0) to stop backtracking. In this way you don't have to repeat yourself.
You can use is_list/1 to test whether an argument is a list.
It's okay to use more spaces. Really.
So, an alternative solution is (now using \+/1 instead of not/1):
subs(_, _, [], []).
subs(X, Y, [X|T1], [Y|T2]) :- subs(X, Y, T1, T2), !.
subs(X, Y, [H|T1], [H|T2]) :- \+ is_list(H), subs(X, Y, T1, T2), !.
subs(X, Y, [H1|T1], [H2|T2]) :- subs(X, Y, H1, H2), subs(X, Y, T1, T2).
Demonstration:
?- subs(a, b, [a, [a, [d, f, a]], a, b, a, [g]], Z).
Z = [b, [b, [d, f, b]], b, b, b, [g]].