Reputation: 1827
I am given a list, an element to be replaced and the replacement for that element. I managed to do it for all occurrences of the element in that list:
replace([],X,Y,[]).
replace([X|T], X, Y, Z) :-
replace(T, X, Y, Z1),
Z = [Y|Z1].
replace([H|T], X, Y, [H|Z]) :-
replace(T, X, Y, Z).
However now I must only replace the first occurrence of that element. My thought process writing:
replace([X|T], X, Y, Z) :-
replace(T, X, Y, Z1),
Z = [Y|Z1].
was:
Z
is the result of [X|T],X,Y
if Z1
is the result of T
,XY
and Z = [Y|Z1]
. Following the same thought process I tried writing the function that only replaces the first occurrence of the element like so:
An idea for implementing only the first occurrence would be from a replace/4
to go in a replace/5
where I count if I replaced or not like so:
replace_single(L,X,Y,Z) :-
replace2(L,X,Y,0,Z).
replace2([],X,Y,C,[]).
replace2([X|T], X, Y, C, Z) :-
\+ (C = 0),
replace2(T, X, Y, C, Z1),
Z = [X|Z1],
C is 1.
replace2([H|T], X, Y, C, [H|Z]) :-
replace2(T, X, Y, C, Z).
Obviously it will not work, I am a little bit lost. Could someone give me a tip or so of how I could think to solve the problem or the solution itself?
Upvotes: 2
Views: 2767
Reputation: 85
Another way to do it will be:-
replace(E1,L1,E2,L2) :-
same_length(L1,L2),
append(BeforeElement,[E1|AfterElement],L1),
append(BeforeElement,[E2|AfterElement],L2).
where BeforeElement stands for prefix of the list before the element and After Element stands for suffix of the list after the element.
Upvotes: 0
Reputation: 58244
Another approach would be to use a DCG:
rep1(X, Y, [Z|T]) --> [Z], { dif(Z, X) }, rep1(X, Y, T).
rep1(X, Y, [Y|T]) --> [X], rest(T).
rep1(_, _, []) --> [].
rest([]) --> [].
rest([H|T]) --> [H], rest(T).
| ?- phrase(rep1(a, 1, L), [a,b,c,a,d]).
L = [1,b,c,a,d] ? ;
| ?- phrase(rep1(a, 1, [x, y, 1, b]), L).
L = [x,y,1,b] ? a
L = [x,y,a,b]
You can write your predicate as:
replace(X, Y, L, R) :- phrase(rep1(X, Y, R), L).
Upvotes: 1
Reputation: 18726
We define replace/4
based upon same_length/2
, append/3
, maplist/2
, and prolog-dif:
replace(Xs,X,Y,Ys) :-
same_length(Xs,Ys),
append(Prefix,[X|Suffix],Xs),
maplist(dif(X),Prefix),
append(Prefix,[Y|Suffix],Ys).
Sample queries:
?- replace(Xs,2,two,[1,two,3,4,5,1,2,3,4,5,1,2]).
Xs = [1,2,3,4,5,1,2,3,4,5,1,2]
; false.
?- replace([1,2,3,4,5,1,2,3,4,5,1,2],2,two,Ys).
Ys = [1,two,3,4,5,1,2,3,4,5,1,2]
; false.
Upvotes: 1