replacing elements in atoms in Prolog - dictionary

I'm writing a prolog predicate which replace an element with another in a given atom. The predicate I wrote is like this:
replace_var(Expr0, Var, Val, Expr) :-
Expr0 =.. Chars,
chars_replaced(Chars, Rs),
Expr =.. Rs.
chars_replaced(Chars, Rs) :-
maplist(rep, Chars, Rs).
rep(Var,Val).
rep(C, C) :- dif(C,var).
The result I want it to return is something like:
-?replace_var(hello, l, w, X).
X = hewwo.
The problem is about the rep() predicate. I don't know how to write it or how to pass the Val and Var to the predicate.
Please give me some suggestions. Thanks!

this is wrong
Expr0 =.. Chars
you need instead
atom_chars(Expr0, Chars)
and this one really puzzle me
rep(Var,Val).
rep(C, C) :- dif(C,var).
what do you mean, specially the second one ?
anyway, the whole could be
replace_var(Expr0, Var, Val, Expr) :-
atom_chars(Expr0, Cs),
maplist(rep(Var, Val), Cs, Ts),
atom_chars(Expr, Ts).
rep(C, T, C, T).
rep(_, _, C, C).
disclaimer: untested code

Related

Prolog – How to recursively generate all combinations of two lists as a two-dimensional array

I tried to generate all the combinations of the elements in two lists.
For example, List([1,2,3],[1,2,3],L). should return L = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
This is the code I wrote:
matrix(L1, L2, M, Res).
matrix([], L2, [], []).
matrix([H1|T1], L2, M, [M|Res]):- matrix(T1, L2, M_temp, Res), combo(L2, H1, [], M).
combo ([], _, Acc, Acc) :- !.
combo ([H2|T2], H_tmp, Acc, M) :- combo (T2, H_tmp, Acc, M_tmp), M = [[H_tmp,H2]|M_tmp].
but the result is: L = [[[1,1],[1,2],[1,3]],[[2,1],[2,2],[2,3]],[[3,1],[3,2],[3,3]]]
because I add the list as element instead of append each list element to Res. No success of implementing the the append.
append([1,2,3],[1,2,3],L).
append_lst([], L2, L2).
append_lst([H|T], L2, Res) :- append_lst(T, L2, Acc), Res = [H|Acc].
I think my approach is wrong.
Could you help me, please?
Well, Prolog doesn't have arrays: it just has lists. But, assuming your have two lists/sets, say
[1,2,3]
[a,b,c]
and want to generate a list containing the Cartesian product of the two sets:
[
[1,a], [1,b], [1,c],
[2,a], [2,b], [2,c],
[3,a], [3,b], [3,c],
]
The simplest way is to use findall/3 and member/2:
matrix( Xs, Ys, M ) :- findall( [X,Y] , ( member(X,Xs), member(Y,Ys) ) , M ).
And if you wanted to roll your own, it's not much more difficult. You might notice that we're using a helper predicate with an additional argument that will give us back the unbound tail of the list we're building, which gets closed when we run out of Xs.
Here's the code:
pairs( [] , _ , [] ) . % Once we exhausted the Xs, we're done.
pairs( [X|Xs] , Ys , Ps ) :- % But if we have an X, then...
pair(X,Ys,Ps, P0 ), % - pair that X with every Y, and
pairs(Xs,Ys,P0) % - and recurse down
. % Easy!
pair( _ , [] , Ps , Ps ) . % Once we've exhausted the Ys, we're done
pair( X , [Y|Ys] , [X:Y|Ps] , P0 ) :- % Otherwise, construct the X:Y pair, and
pair(X,Ys,Ps,P0) % - recurse down.
. % Even easier!

Rewriting tail recursion prolog code into simple recursion

I'm quite new in prolog and I want to practice rewriting a tail-recursion code into a simple recursion to understand better the process, but I did not succeed in it. If anybody can help with it I would really appreciate it.
Note: Converting tail-recursive (tail-call) code to non tail-recursive code is not a wise thing to normally do in Prolog. This question is only for academic purposes of learning.
The code:
some_predicate(T,1,3,0,D),
%the tail has elements with ID and Numbers like [(1,3),(2,5),(4,3)])
%in the D I count steps if different conditions are fulfilled
%I would like to write something like: some_predicate(T,1,3,D) without the Acc
some_predicate(_, _, 1, D, D):-!.
some_predicate([], _, _, D, D):-!.
some_predicate([(UP,_)|_], ID, H, D, D):-
UP >= ID + H,
!.
some_predicate([(UP,UH)|T], _, H, D, RetD):-
H > UH,
TH is H - 1,
TD is D + 1,
some_predicate(T, UP, TH, TD, RetD),
!.
some_predicate([(UP,UH)|T], _, _,D, RetD):-
TD is D + 1,
some_predicate(T, UP, UH, TD, RetD),
!.
My attempt
some_predicate(_, _, 1,0):-!.
some_predicate([], _, _,0):-!.
some_predicate([(UP,_)|_], ID, H, 0):-
UP >= ID + H,
!.
some_predicate([(UP,UH)|Er], _, H, D):-
H > UH,
some_predicate(Er, UP, TH, TD),
H is TH - 1,
D is TD + 1,
!.
some_predicate([(UP,UH)|Er], _, _,D):-
some_predicate(Er, UP, UH, TD),
D is TD + 1,
!.
A comment in the question says that you would like to rewrite the code without an accumulator, but it doesn't use an accumulator. The general schema for predicates using a list accumulator would be something like this:
foo(X, Ys) :-
foo(X, [], Ys).
foo(X, Acc, Acc) :-
bar(X).
foo(X, Acc, Ys) :-
baz(X, Y, Z),
foo(Z, [Y | Acc], Ys).
The recursive call involving the list accumulator gets a bigger list than the accumulator was before. You add something to the accumulator before you pass it to the recursive call.
Your program instead uses the common pattern of "list iteration" (comments with a better name are welcome) in Prolog which does the opposite of recursion using an accumulator:
foo([], Y) :-
bar(Y).
foo([X | Xs], Y) :-
baz(X),
foo(Xs, Y).
(This uses similar names to the predicate before, but I'm not saying that they are equivalent.)
The list constructor [_ | _] is in the head of the clause, not in a recursive call. The list in the recursive call is smaller than the list in the head. You remove something from the list before you pass the tail to the recursive call.
This is therefore not an answer your question, just a hint that you need to start from the right place: Some predicate definition that really does use an accumulator list. The simplest interesting case is probably reversing a list.

Prolog list recursion, add elements in list

I need to write a recursion in prolog, which adds elements of two lists. Let's say we have a list, A = [a,b,c], and B = [d,e,f] and the final list, R, should look like this: R = [a+d, b+e, c+f].
I came up only with this:
xxx([a], [b], [a+b]).
xxx([H1|T1], [H2|T2], W) :- xxx(T1, T2, W), .(H1+H2, W).
But it gives me uncaught exception: error(syntax_error('user_input:5 (char:15) expression or ] expected in list'),read_term/3). I also tried this:
xxx([a], [b], [a+b]).
xxx([H1|T1], [H2|T2], W) :- xxx(T1, T2, W), append(H1+H2, W, []).
With no success: uncaught exception: error(syntax_error('user_input:4 (char:16) expression or ] expected in list'),read_term/3)
Im using Gnu prolog (gprolog)
xxx([], [], []).
xxx([E|Es], [F|Fs], [E+F|EFs]) :-
xxx(E, F, EFs).
or
..., maplist(ex, Es, Fs, EFs), ...
ex(E, F, E+F).
or
..., maplist(\E^F^(E+F)^true, Es, Fs, EFs), ...
using library(lambda)

count repeated terms in prolog

I want to ask about prolog programming. I have:
byCar(auckland,hamilton).
byCar(valmont,metz).
byTrain(metz,frankfurt).
byPlane(frankfurt,bangkok).
byPlane(bangkok,auckland).
travell(From,To,go(From,To,car)) :- byCar(From,To).
travell(From,To,go(From,To,train)) :- byTrain(From,To).
travell(From,To,go(From,To,plane)) :- byPlane(From,To).
travell(From,To,go(From,Step,Via,Go)) :- travell(From,Step,go(From,Step,Via)),travell(Step,To,Go).
Then I ask in winprolog:
?- travell(valmont,hamilton,Go).
It answered
Go = go(valmont,metz,car,go(metz,frankfurt,train,go(frankfurt,bangkok,plane,go(bangkok,auckland,plane,go(auckland,hamilton,car)))))
My question is, is it possible to count how many 'go' it have? like my example before it has 5 'go'
would be easier if you could uniform go/3 and go/4 arity. Anyway, try
count_last_arg(Struct,Func,Count) :-
count_last_arg(Struct,Func,0,Count).
count_last_arg(Struct,Func,N,Count) :-
Struct =.. L, last(L, LL), LL =.. [Func|_]
-> N1 is N+1,
count_last_arg(LL,Func,N1,Count)
; Struct =.. [Func|_]
-> Count is N+1
; Count is N.

Division in prolog

I'm trying to define the division in prolog using the remainder theorem and the well-ordering principle.
I've got thus far:
less(0, s(0)).
less(0, s(B)) :- less(0, B).
less(s(A), s(s(B))) :- less(A, s(B)).
add(A,0,A) :- nat(A).
add(A,s(B),s(C)) :- add(A,B,C). % add(A,B+1,C+1) = add(A,B,C)
add2(A,0,A).
add2(A,s(B),s(C)) :- add2(A,B,C). % add(A,B+1,C+1) = add(A,B,C)
times(A,0,0).
times(A,s(B),X) :- times(A,B,X1),
add(A,X1,X).
eq(0,0).
eq(s(A), s(B)) :- eq(A, B).
% A / B = Q (R) => A = B * Q + R
div(A, B, Q, R) :- less(R, B), eq(A, add(times(Q, R), R)).
But the definition of div is somehow wrong. Could someone please give me a hint?
PS: I shouldn't be using eq, but I couldn't get is or = to work.
In SWI-Prolog, you can try ?- gtrace, your_goal. to use the graphical tracer and see what goes wrong. Instead of eq(A, add(times(Q, R), R)), you should write for example: times(Q, R, T), add(T, R, A), since you want to use the "times/3" and "add/3" predicates, instead of just calling the "eq/2" predicate with a compound term consisting of "add/2" and "times/2" as its second argument. There are other problems with the code as well, for example, the definition of nat/1 is missing, but I hope this helps somewhat.

Resources