Moc*_*ing 5 prolog failure-slice
我正在尝试创建一个函数,将可变长度列表按顺序拆分为三个偶数长度列表.以下将其拆分为三个,但进程一次一个地将它们插入到每个列表中.
我想要的一个例子是:
[1, 2, 3, 4, 5] -> [1, 2], [3, 4], [5]
Run Code Online (Sandbox Code Playgroud)
另一个例子是:
[8, 7, 6, 5, 4, 3, 2, 1] -> [8, 7, 6], [5, 4, 3], [2, 1].
Run Code Online (Sandbox Code Playgroud)
以下代码通过一次插入一个列表来拆分它们:
div([], [], [], []).
div([X], [X], [], []).
div([X,Y], [X], [Y], []).
div([X,Y,Z|End], [X|XEnd], [Y|YEnd], [Z|ZEnd]):-
div(End, XEnd, YEnd, ZEnd).
Run Code Online (Sandbox Code Playgroud)
此代码输出:
[1, 2, 3, 4, 5] -> [1, 4], [2, 5], [3]
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?
@Boris的答案不会在第一个参数列表的长度未知时终止.要看到这一点,没有必要比故障切片的第一个目标更进一步:
div(L, L1, L2, L3) :-
length(L, Len), false,
% here you compute for example Len1 and Len2
length(L1, Len1),
length(L2, Len2),
append(L1, L1_suffix, L),
append(L2, L3, L1_suffix).
另一方面,您的原始程序具有相当不错的终止属性.cTI给出了以下最佳终止特性:
div(A,B,C,D) terminates_if b(A);b(B);b(C);b(D).
Run Code Online (Sandbox Code Playgroud)
换句话说,为了确保终止,您只需要一个参数(A或者B或C或者D)作为有限和基础的具体列表(这b(..)意味着什么).这是一个非常强大的终止条件.这些论点不合适真的很可惜!为什么不概括你的程序?唯一的问题是它限制了列表元素.所以我将用_s 替换列表元素的所有变量名:
gdiv([], [], [], []).
gdiv([_], [_], [], []).
gdiv([_,_], [_], [_], []).
gdiv([_,_,_|End], [_|XEnd], [_|YEnd], [_|ZEnd]):-
gdiv(End, XEnd, YEnd, ZEnd).
Run Code Online (Sandbox Code Playgroud)
该程序具有相同的终止属性.
唉,现在有点太笼统了.鲍里斯的解决方案现在可以改变用途:
divnew(Zs, As, Bs, Cs) :-
gdiv(Zs, As, Bs, Cs),
append(As, BsCs, Zs),
append(Bs, Cs, BsCs).
Run Code Online (Sandbox Code Playgroud)
我表达同样的首选方式是:
divnew(Zs, As, Bs, Cs) :-
gdiv(Zs, As, Bs, Cs),
phrase( ( seq(As), seq(Bs), seq(Cs) ), Zs).
Run Code Online (Sandbox Code Playgroud)
请参阅其他答案以获得定义seq//1.