Prolog 中的前缀
Prefix in Prolog
我是 Prolog 的新手。
我对谓词前缀有疑问,但有点不同。
我想得到一个列表的前缀,但是直到一个元素
列表可以有重复元素。
一个例子:
prefix(Element, List, Prefix)
prefix(c, [a,b,c,d,e,f], [a, b])
不包含该元素。
目前我只有这个
prefix(X, [X|T], []).
prefix(X, [Y|T], [Y|Z]):-
prefix(X, T, Z).
但是不行。
L = [a,b,c] ? prefix(b, L, Prefix).
no
?-
谢谢
这是一个使用定从句文法的解决方案dcg and the non-terminal all_seq//2
:
prefix(X, Xs, Ys) :-
phrase( ( all_seq(dif(X), Ys), [X], ... ), Xs).
... --> [] | [_], ... .
所以语法(在 phrase/2
内)是:
There is
1. an initial sequence Ys
with all elements different to X
, followed by 2. X
, followed by 3. anything.
仍然有一个缺点,使用 DCG 时经常会出现这种情况:实施并不像它可能的那样确定,因此留下了多余的选择点。
prefix(X,[X|T],[]).
prefix(X,[Y|T],Z) :- prefix(X,T,M) , Z = [Y|M].
输出:
?- L = [a,b,c,d,e,f] , prefix(d,L,G).
L = [a, b, c, d, e, f],
G = [a,
b, c] .
?- L = [a,b,c,d,e,f] , prefix(e,L,G).
L = [a, b, c, d, e, f],
G = [a,
b, c, d] .
编辑 #1
原始代码有效,使用 (,) 而不是 (?) 如下。
prefix(X,[X|T],[]).
prefix(X,[Y|T],[Y|Z]) :- prefix(X,T,Z).
输出:
?- prefix(d , [a,b,c,d,e] , G).
G = [a, b, c]
?- L = [a,b,c] , prefix(b, L, Prefix).
L = [a, b, c],
Prefix = [a] .
编辑#2
正如评论中提到的用户 false,我可以确认你是对的,但在我的解决方案中,我假设列表包含唯一元素:
prefix(d,[d,d],[d])
成功 - 它应该会失败,
使用 dif/2
,您可以明确声明对于 Element
之前的任何成员 X
,X \== Element
:
prefix(Element, [Element|_], []).
prefix(Element, [Head|List], [Head|Prefix]) :-
dif(Element, Head),
prefix(Element, List, Prefix).
或者同样,因为我想在我的答案的第一次迭代中使用 append/3
:
prefix(Element, List, Prefix) :-
append(Prefix, [Element|_Suffix], List),
maplist(dif(Element), Prefix).
后缀基本相同:
suffix(Element, List, Suffix) :-
append(_Prefix, [Element|Suffix], List),
maplist(dif(Element), Suffix).
如果你不想使用maplist(dif(Element), List)
:
all_dif(_, []).
all_dif(X, [H|T]) :- dif(X, H), all_dif(X, T).
我是 Prolog 的新手。 我对谓词前缀有疑问,但有点不同。
我想得到一个列表的前缀,但是直到一个元素 列表可以有重复元素。
一个例子:
prefix(Element, List, Prefix)
prefix(c, [a,b,c,d,e,f], [a, b])
不包含该元素。
目前我只有这个
prefix(X, [X|T], []).
prefix(X, [Y|T], [Y|Z]):-
prefix(X, T, Z).
但是不行。
L = [a,b,c] ? prefix(b, L, Prefix).
no
?-
谢谢
这是一个使用定从句文法的解决方案dcg and the non-terminal all_seq//2
:
prefix(X, Xs, Ys) :-
phrase( ( all_seq(dif(X), Ys), [X], ... ), Xs).
... --> [] | [_], ... .
所以语法(在 phrase/2
内)是:
There is 1. an initial sequence
Ys
with all elements different toX
, followed by 2.X
, followed by 3. anything.
仍然有一个缺点,使用 DCG 时经常会出现这种情况:实施并不像它可能的那样确定,因此留下了多余的选择点。
prefix(X,[X|T],[]).
prefix(X,[Y|T],Z) :- prefix(X,T,M) , Z = [Y|M].
输出:
?- L = [a,b,c,d,e,f] , prefix(d,L,G).
L = [a, b, c, d, e, f],
G = [a, b, c] .?- L = [a,b,c,d,e,f] , prefix(e,L,G).
L = [a, b, c, d, e, f],
G = [a, b, c, d] .
编辑 #1
原始代码有效,使用 (,) 而不是 (?) 如下。
prefix(X,[X|T],[]).
prefix(X,[Y|T],[Y|Z]) :- prefix(X,T,Z).
输出:
?- prefix(d , [a,b,c,d,e] , G).
G = [a, b, c]
?- L = [a,b,c] , prefix(b, L, Prefix).
L = [a, b, c],
Prefix = [a] .
编辑#2
正如评论中提到的用户 false,我可以确认你是对的,但在我的解决方案中,我假设列表包含唯一元素:
prefix(d,[d,d],[d])
成功 - 它应该会失败,
使用 dif/2
,您可以明确声明对于 Element
之前的任何成员 X
,X \== Element
:
prefix(Element, [Element|_], []).
prefix(Element, [Head|List], [Head|Prefix]) :-
dif(Element, Head),
prefix(Element, List, Prefix).
或者同样,因为我想在我的答案的第一次迭代中使用 append/3
:
prefix(Element, List, Prefix) :-
append(Prefix, [Element|_Suffix], List),
maplist(dif(Element), Prefix).
后缀基本相同:
suffix(Element, List, Suffix) :-
append(_Prefix, [Element|Suffix], List),
maplist(dif(Element), Suffix).
如果你不想使用maplist(dif(Element), List)
:
all_dif(_, []).
all_dif(X, [H|T]) :- dif(X, H), all_dif(X, T).