Prolog 将列表拆分为单独的列表

Prolog 将列表拆分为单独的列表,prolog,logical-purity,Prolog,Logical Purity,我必须为我的列表定义更多的约束 我想将我的列表拆分为单独的列表 例如: List=[[1,1],[_,0],[_,0],[_,0],[3,1],[_,0],[9,1],[2,0],[4,0]] 我需要从主列表中获得三个列表: [[_,0],[_,0],[_,0]] and [[_,0]] and [[2,0],[4,0]] 所以我总是需要一组列表,在一个带有[X,1]的术语之间 如果你能给我小费就太好了。不需要解决方案,只需要一个提示如何解决这个问题 Jörg您可以使用类似于append/3

我必须为我的列表定义更多的约束

我想将我的列表拆分为单独的列表

例如:

List=[[1,1],[_,0],[_,0],[_,0],[3,1],[_,0],[9,1],[2,0],[4,0]]
我需要从主列表中获得三个列表:

[[_,0],[_,0],[_,0]] and [[_,0]] and [[2,0],[4,0]]
所以我总是需要一组列表,在一个带有[X,1]的术语之间

如果你能给我小费就太好了。不需要解决方案,只需要一个提示如何解决这个问题


Jörg

您可以使用类似于
append/3
的谓词。例如,要在第一次出现atom
x
时拆分列表,您可以说:

?- L =  [a,b,c,d,x,e,f,g,x,h,i,j], once(append(Before, [x|After], L)).
L = [a, b, c, d, x, e, f, g, x|...],
Before = [a, b, c, d],
After = [e, f, g, x, h, i, j].
正如@false所指出的,添加一个额外的需求可能会改变结果,但这就是使用
append/3
的好处:

“在
x
上拆分列表,以便第二部分以
h
开头:

?- L =  [a,b,c,d,x,e,f,g,x,h,i,j], After = [h|_], append(Before, [x|After], L).
L = [a, b, c, d, x, e, f, g, x|...],
After = [h, i, j],
Before = [a, b, c, d, x, e, f, g].

这只是提示。

您可以使用类似于
append/3
的谓词。例如,要在其中第一次出现atom
x
时拆分列表,您可以说:

?- L =  [a,b,c,d,x,e,f,g,x,h,i,j], once(append(Before, [x|After], L)).
L = [a, b, c, d, x, e, f, g, x|...],
Before = [a, b, c, d],
After = [e, f, g, x, h, i, j].
正如@false所指出的,添加一个额外的需求可能会改变结果,但这就是使用
append/3
的好处:

“在
x
上拆分列表,以便第二部分以
h
开头:

?- L =  [a,b,c,d,x,e,f,g,x,h,i,j], After = [h|_], append(Before, [x|After], L).
L = [a, b, c, d, x, e, f, g, x|...],
After = [h, i, j],
Before = [a, b, c, d, x, e, f, g].

这只是提示。

不清楚“一组列表”是什么意思。在您的示例中,您从符合
[[1,1]
标准的
[1,1]
开始。那么,一开始不应该有一个空的列表吗?或者你是说一切都是从这样一个标记开始的? 如果周围还有更多的标记呢

首先,需要定义标记元素的标准。这两种情况都适用:适用和不适用,因此这是介于两者之间的元素

marker([_,1]).

nonmarker([_,C]) :-
   dif(1, C).
注意,使用这些谓词,我们意味着每个元素都必须是
[[uu,.]
。你没有说,但这是有道理的

split(Xs, As, Bs, Cs) :-
   phrase(three_seqs(As, Bs, Cs), Xs).

marker -->
   [E],
   {marker(E)}.

three_seqs(As, Bs, Cs) -->
   marker,
   all_seq(nonmarker, As),
   marker,
   all_seq(nonmarker, Bs),
   marker,
   all_seq(nonmarker, Cs).
有关
all_seq//2
的定义,请参见


人们可以用
all_seq(marker,[[u])代替
marker
,不清楚“列表组”是什么意思。在您的示例中,您从符合
[[1,1]
标准的
[1,1]
开始。那么,一开始不应该有一个空的列表吗?或者你是说一切都是从这样一个标记开始的? 如果周围还有更多的标记呢

首先,需要定义标记元素的标准。这两种情况都适用:适用和不适用,因此这是介于两者之间的元素

marker([_,1]).

nonmarker([_,C]) :-
   dif(1, C).
注意,使用这些谓词,我们意味着每个元素都必须是
[[uu,.]
。你没有说,但这是有道理的

split(Xs, As, Bs, Cs) :-
   phrase(three_seqs(As, Bs, Cs), Xs).

marker -->
   [E],
   {marker(E)}.

three_seqs(As, Bs, Cs) -->
   marker,
   all_seq(nonmarker, As),
   marker,
   all_seq(nonmarker, Bs),
   marker,
   all_seq(nonmarker, Cs).
有关
all_seq//2
的定义,请参见


代替
marker
,可以编写
all_seq(marker,[[u])

此实现尝试保留列表项,而不限制列表项为
[[uu,][/code>,如
做
我可以看出,实施上述限制确实很有意义。。。不过,我还是想把它提出来,谈谈更普遍的问题

以下内容基于并具体化了谓词,
marker\u truth/2
marker\u真值(M,T)
M
的“标记”属性具体化为真值
T
true
false

上面显示的第二个答案肯定不是我们想要的。 显然,
splitlistIf/3
此时应该有split
Ls
, 因为目标
是_标记([9,1])
成功了。没有。相反,我们得到的答案是一个冻结的
dif/2
目标,这个目标永远不会被唤醒,因为它正在等待匿名变量
\u E
的实例化

猜猜谁该受责备!
marker\u truth/2
的第二句:

marker_truth(Xs,false) :- dif(Xs,[_,1]). % BAD
?- marker_truth(M,Truth).                   % most general use
Truth = true,  M = [_A,1] ;
Truth = false, freeze(M, nonMarker__1(M)).
所有这些代码,用于表示
的安全逻辑否定是\u标记([\u1])
?丑

让我们看看它(至少)是否有助于上述问题(给出如此多无用答案的问题)

这不是我们想要的答案。为了了解原因,让我们看看以下类似用法的答案:

在最一般的情况下,有两个答案--这就是具体化谓词的行为方式

让我们相应地重新编码
marker\u truth/2

marker_truth(Xs,Truth) :- subsumes_term([_,1],Xs), !, Truth = true.
marker_truth(Xs,Truth) :- Xs \= [_,1],             !, Truth = false.
marker_truth([_,1],true).
marker_truth(Xs   ,false) :- nonMarker__1(Xs).

nonMarker__1(T) :- var(T),      !, freeze(T,nonMarker__1(T)).
nonMarker__1(T) :- T = [_|Arg], !, nonMarker__2(Arg).
nonMarker__1(_).

nonMarker__2(T) :- var(T),    !, freeze(T,nonMarker__2(T)).
nonMarker__2(T) :- T = [_|_], !, dif(T,[1]).
nonMarker__2(_).
让我们使用新的
marker\u truth/2实现重新运行上述查询:

marker_truth(Xs,false) :- dif(Xs,[_,1]). % BAD
?- marker_truth(M,Truth).                   % most general use
Truth = true,  M = [_A,1] ;
Truth = false, freeze(M, nonMarker__1(M)).

此实现尝试保留列表项,但不将列表项限制为
[\u,\u]
,如 做 我可以看出,实施上述限制确实很有意义。。。不过,我还是想把它提出来,谈谈更普遍的问题

以下内容基于并具体化了谓词,
marker\u truth/2
marker\u真值(M,T)
M
的“标记”属性具体化为真值
T
true
false

上面显示的第二个答案肯定不是我们想要的。 显然,
splitlistIf/3
此时应该有split
Ls
, 因为目标
是_标记([9,1])
成功了。没有。相反,我们得到的答案是一个冻结的
dif/2
目标,这个目标永远不会被唤醒,因为它正在等待匿名变量
\u E
的实例化

猜猜谁该受责备!
marker\u truth/2
的第二句:

marker_truth(Xs,false) :- dif(Xs,[_,1]). % BAD
?- marker_truth(M,Truth).                   % most general use
Truth = true,  M = [_A,1] ;
Truth = false, freeze(M, nonMarker__1(M)).
所有这些代码,用于表示
的安全逻辑否定是\u标记([\u1])
?丑

让我们看看它(至少)是否有助于上述问题(给出如此多无用答案的问题)

这不是我们想要的答案。为了了解原因,让我们看看以下类似用法的答案:

在最一般的情况下,有两个答案--这就是具体化谓词的行为方式

让我们相应地重新编码
marker\u truth/2

marker_truth(Xs,Truth) :- subsumes_term([_,1],Xs), !, Truth = true.
marker_truth(Xs,Truth) :- Xs \= [_,1],             !, Truth = false.
marker_truth([_,1],true).
marker_truth(Xs   ,false) :- nonMarker__1(Xs).

nonMarker__1(T) :- var(T),      !, freeze(T,nonMarker__1(T)).
nonMarker__1(T) :- T = [_|Arg], !, nonMarker__2(Arg).
nonMarker__1(_).

nonMarker__2(T) :- var(T),    !, freeze(T,nonMarker__2(T)).
nonMarker__2(T) :- T = [_|_], !, dif(T,[1]).
nonMarker__2(_).
让我们使用新的i