双向和确定性二进制减量

时间:2019-04-13 09:57:39

标签: binary prolog

我想知道是否有可能仅在Prolog中单独实现双向和确定性的二进制递减器。示例运行include和for模式(-,+):

?- dec(X,[0,0,1]).
X = [1,0,1]
?- dec(X,[1,1,1]).
X = [0,0,0,1]

对于模式(+,-):

?- dec([1,0,1],X).
X = [0,0,1]
?- dec([0,0,0,1],X).
X = [1,1,1]

(可选)所有模式都不应留下任何choice points。但是强制性地,必须仅在纯Prolog中实现,因此不能剪切,不能findall,不能var等。

我已经使用二进制加法器here尝试了以下dec(X,Y) :- binary_plus([1],Y,X).的定义。但这没有通过最后一个测试用例,因为我得到了dec([0,0,0,1],X). X = [1, 1, 1]; X = [1, 1, 1, 0] ; false.

2 个答案:

答案 0 :(得分:1)

以下两个查询测试确定性。他们没有成功。两者都按原样无限运行;并以给定的N失败。为了表明打算终止,查询以:/-&为前缀。

:/-& length(Bs,N), dec(Bs, Ds1), dif(Ds1, Ds2), dec(Bs, Ds2).

:/-& length(Ds,N), dec(Bs1, Ds), dif(Bs1, Bs2), dec(Bs2, Ds).

dec([1|Bs],[0|Bs]) :-
   nil_or_ends_with_one(Bs).
dec([0|Bs],[1|Ds]) :-
   deci(Bs, Ds).

nil_or_ends_with_one([]).
nil_or_ends_with_one([E|Es]) :-
   ends_with_one(Es, E).

ends_with_one([], 1).
ends_with_one([E|Es], _) :-
   ends_with_one(Es, E).

deci([1],[]).
deci([1|Bs],[0|Bs]) :-
   Bs = [B|_],
   ends_with_one(Bs, B).
deci([0|Bs],[1|Ds]) :-
   deci(Bs, Ds).

该解决方案仍然有点笼统,因为它可以接受

?- dec([1,non_digit,1],[0,non_digit,1]).

此问题很容易解决,但似乎不值得。

答案 1 :(得分:0)

我得到了一个不同的解决方案,该解决方案不针对deep indexing Prolog,而是针对统一索引的Prolog。到目前为止,所有4个测试用例在Jekejeke Prolog中都没有留下任何选择点,后者具有完全平坦的索引编制。 :-)

% check binary number
num([]).
num([X|Y]) :- dig(X, Y).

dig(1, []).
dig(T, [X|Y]) :- aux(T, X, Y).

aux(0, X, Y) :- dig(X, Y).
aux(1, X, Y) :- dig(X, Y).

% check binary number and its pseudo decrement
dec([X|Y], Z) :- dig(X, Y, Z).

dig(1, [], []).
dig(T, [X|Y], [U|V]) :- aux(T, U, V, X, Y).

aux(0, 1, Z, X, Y) :- dig(X, Y, Z).
aux(1, 0, [X|Y], X, Y) :- dig(X, Y).

https://gist.github.com/jburse/649f828c330ff3c770834ee8bca250a8#file-tarai-p

但是完全平面索引的缺点是在对谓词进行编码以使其变为平面形式时会产生额外的开销。二进制格式也很受欢迎,如binary_plus / 3示例所示。但是最好的办法可能是既有平面又有深度,而后一种方式则存在

深dec / 2版本,永远不会留下选择点。