Prolog: replace an element in a list at a specifie

2020-03-08 09:24发布

I'd like to have a Prolog predicate that can replace an element in a list at a specified index.

Example:

% replace(+List,+Index,+Value,-NewList).
?- L=[a,b,c,d], replace(L,1,z,L2).
L2 = [a,z,c,d]

I don't know how to do this. Thanks for your help! Loïc.

标签: list prolog
8条回答
一纸荒年 Trace。
2楼-- · 2020-03-08 09:41

If we use same_length/2, append/3, and length/2, we don't need to write recursive code:

list_nth0_item_replaced(Es, N, X, Xs) :-
   same_length(Es, Xs),
   append(Prefix, [_|Suffix], Es),
   length(Prefix, N),
   append(Prefix, [X|Suffix], Xs).

Sample query given by the OP:

?- list_nth0_item_replaced([a,b,c,d], 1, z, Xs).
   Xs = [a,z,c,d]
;  false.

This works "in the other direction", too!

?- list_nth0_item_replaced(Xs, 1, z, [a,z,c,d]).
   Xs = [a,_A,c,d]
;  false.

Even better, we do not even need to specify the concrete index:

?- list_nth0_item_replaced(Es, N, X, [a,z,c,d]).
   N = 0, X = a, Es = [_A, z, c, d]
;  N = 1, X = z, Es = [ a,_A, c, d]
;  N = 2, X = c, Es = [ a, z,_A, d]
;  N = 3, X = d, Es = [ a, z, c,_A]
;  false.

?- list_nth0_item_replaced([a,b,c,d], N, X, Xs).
   N = 0, Xs = [X,b,c,d]
;  N = 1, Xs = [a,X,c,d]
;  N = 2, Xs = [a,b,X,d]
;  N = 3, Xs = [a,b,c,X]
;  false.
查看更多
劫难
3楼-- · 2020-03-08 09:41

What about doing it in a straight-forward way like this?

:- use_module(library(clpfd)).

list_nth0_item_replaced([_|Xs], 0, E, [E|Xs]).
list_nth0_item_replaced([X|Xs], N, E, [X|Ys]) :-
   N #> 0,
   N #= N0+1,
   list_nth0_item_replaced(Xs, N0, E, Ys).

Here's the use-case the OP specified:

?- list_nth0_item_replaced([a,b,c,d],1,z,Ls).
   Ls = [a,z,c,d]
;  false.

Above code is pure, so we can ask more general queries—and expect logically sound answers:

?- list_nth0_item_replaced([a,b,c,d], N, X, Ls).
   N = 0, Ls = [X,b,c,d]
;  N = 1, Ls = [a,X,c,d]
;  N = 2, Ls = [a,b,X,d]
;  N = 3, Ls = [a,b,c,X]
;  false.
查看更多
登录 后发表回答