【问题标题】:Prolog - Binary addition?Prolog - 二进制加法?
【发布时间】:2015-03-31 23:08:15
【问题描述】:

我需要编写一个 Prolog 谓词来计算列表中表示的 2 个二进制数的总和。 列表已经反转,例如 ([0,1] base 2) = (2 base 10)。

它应该适用于模式 binary_plus(+,+,-),例如

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

以binary_plus(-,-,+)模式为例

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

不允许使用剪切符号、findall、否定或 if-then-else。

这是我的代码:

is_binary([]).
is_binary([X]):- X is 1.
is_binary([X|Xs]):-
    append(_,[1],Xs),
    member(X,[0,1]),    
    is_binary(Xs).

binary_plus([],X,X):-
    is_binary(X).
binary_plus(X,[],X):- 
    is_binary(X).

binary_plus([0|Xs],[Y|Ys],[Y|Zs]):-
    binary_plus(Xs,Ys,Zs).
binary_plus([1|Xs],[0|Ys],[1|Zs]):-
    binary_plus(Xs,Ys,Zs).
binary_plus([1|Xs],[1|Ys],[0|Zs]):-
    binary_plus(Xs,[1],Ws),
    binary_plus(Ws,Ys,Zs).

我不知道我错在哪里,因为有一些我无法解决的奇怪问题, 因此,如果有人可以帮助我,我将不胜感激。 谢谢。

【问题讨论】:

  • is_binary([X]):- X is 1. 应该是 is_binary([X]) :- X = 1. 或更好,is_binary([1]).。术语X is 1 是表达式赋值。虽然碰巧有效,但=/2 是为了统一,这就是你想要的。
  • +1 表示不使用!/0、if-then-else 等非常明智的要求!这些结构通常会使您的程序变得非单调且不那么通用。

标签: binary prolog addition


【解决方案1】:

在描述列表时,请始终考虑使用 DCG 表示法。例如,在您的情况下,请考虑将其写为:

:- use_module(library(clpfd)).

binary_addition(Xs, Ys, As) :-
        phrase(binary_addition_(Xs, Ys, 0), As).

binary_addition_([], [], 0)     --> [].
binary_addition_([], [], 1)     --> [1].
binary_addition_([X|Xs], [], C) --> binary_addition_([X|Xs], [C], 0).
binary_addition_([], [Y|Ys], C) --> binary_addition_([C], [Y|Ys], 0).
binary_addition_([X|Xs], [Y|Ys], C0) -->
        { [X,Y] ins 0..1,
          Sum #= X + Y + C0 },
        sum_carry(Sum, C),
        binary_addition_(Xs, Ys, C).

sum_carry(0, 0) --> [0].
sum_carry(1, 0) --> [1].
sum_carry(2, 1) --> [0].

示例查询及其解决方案:

?- binary_addition([1,0],[0,1,1], Sum).
Sum = [1, 1, 1] .

?- binary_addition([1,1],[1,0,1], Sum).
Sum = [0, 0, 0, 1] .

?- binary_addition([0,1],[1,1], Sum).
Sum = [1, 0, 1] .

请注意,它也适用于另一个方向:

?- binary_addition(Xs, Ys, [1,1]).
Xs = [1, 1],
Ys = [] ;
Xs = [],
Ys = [1, 1] ;
Xs = [_G2510, 1],
Ys = [_G2522],
_G2510 in 0..1,
_G2510+_G2522#=1,
_G2522 in 0..1 ;
etc.

如果您想要反向列表,只需将reverse/2 目标添加到binary_addition/3

【讨论】:

  • 非常感谢您的快速回答!但我刚开始使用 prolog,我不允许使用这种技术。我编辑了我的帖子。
  • @DaniLiat,mat 的解决方案没有任何你的问题说你不允许使用的结构。
【解决方案2】:

这是我对没有任何东西的二进制加法的看法。我了解您不要使用 clpfd:

binary_plus(A,B,C) :- binary_plus_0(A,B,C).

binary_plus_0([],    [],    []).
binary_plus_0([],    [B|Bs],[B|Bs]).
binary_plus_0([A|As],[],    [A|As]).
binary_plus_0([A|As],[B|Bs],[C|Cs]) :- binary_plus_0(A,B,C,As,Bs,Cs).

binary_plus_0(0,0,0,As,Bs,Cs) :- binary_plus_0(As,Bs,Cs).
binary_plus_0(0,1,1,As,Bs,Cs) :- binary_plus_0(As,Bs,Cs).
binary_plus_0(1,0,1,As,Bs,Cs) :- binary_plus_0(As,Bs,Cs).
binary_plus_0(1,1,0,As,Bs,Cs) :- binary_plus_1(As,Bs,Cs).

binary_plus_1([],    [],    [1]).
binary_plus_1([],    [B|Bs],Cs)     :- binary_plus_0([1],[B|Bs],Cs).
binary_plus_1([A|As],[],    Cs)     :- binary_plus_0([A|As],[1],Cs).
binary_plus_1([A|As],[B|Bs],[C|Cs]) :- binary_plus_1(A,B,C,As,Bs,Cs).

binary_plus_1(0,0,1,As,Bs,Cs) :- binary_plus_0(As,Bs,Cs).
binary_plus_1(0,1,0,As,Bs,Cs) :- binary_plus_1(As,Bs,Cs).
binary_plus_1(1,0,0,As,Bs,Cs) :- binary_plus_1(As,Bs,Cs).
binary_plus_1(1,1,1,As,Bs,Cs) :- binary_plus_1(As,Bs,Cs).

【讨论】:

  • 在 SWI-Prolog 中,这留下了一个选择点:?- binary_plus([0,1,1],[0,0,1],X)。 X = [0, 1, 0, 1] ;错误的。 :-( :-(
  • 在我的 Prolog 系统中,(+,+,-) 模式查询没有留下选择点。但是 (+,-,+) 查询有一些非规范化结果:?- binary_plus([0,1,1],X,[0,1,0,1])。 X = [0,0,1]; X = [0,0,1,0] 。也许这可以解决?
猜你喜欢
  • 2020-05-11
  • 1970-01-01
  • 1970-01-01
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多