二进制到整数在Prolog中

huangapple go评论48阅读模式
英文:

Binary to Integer in Prolog

问题

好的,以下是翻译好的部分:

现在我才开始学习Prolog的基础知识,被分配了一个附加问题,要根据以下二进制数的定义将二进制数字转换为整数:

bin(bin(X),bin(Y,Z)):-
    bin(X),
    bin(Y,Z).
bin(bin(X),bin(Y)):-
    bin(X),
    bin(Y).
bin(zero).
bin(one).
% 所以,例如,10010 变成:
% bin(bin(one),bin(bin(zero),bin(bin(zero),bin(bin(one),bin(zero)))))

现在我承认,我甚至还没有开始解决这个问题。考虑到我对这门语言的有限了解,这似乎非常令人望而却步,所以我只有当前的基本情况:

bin_int(bin(zero),0).
bin_int(bin(one),1).
bin_int(bin(B),X):-bin_int(B,X).

就像我说的,我理解有限。这显然需要递归,但我对如何处理它一无所知。
我会在工作中发布更新,但现在只是伪代码,所以请谅解。

因此,在B变为'one'或'zero'之前,它必须是两个bin,并且我已经陷入困境。
就像我如何编写B必须是一个bin()元组,以及如何处理元组中的第二个bin是否包含自己的元组或不包含的情况?
如果有人对如何处理这个问题有任何想法,我将非常感激一些帮助。谢谢!

英文:

Ok so. Still learning the basics in prolog and was given the bonus question on an assignment of converting a binary number into an integer based on the following definition for a binary num:

bin(bin(X),bin(Y,Z)):-
    bin(X),
    bin(Y,Z).
bin(bin(X),bin(Y)):-
    bin(X),
    bin(Y).
bin(zero).
bin(one).
% So for example, 10010 becomes:
% bin(bin(one),bin(bin(zero),bin(bin(zero),bin(bin(one),bin(zero)))))

Now I'll admit, I haven't haven't even begun to approach this one. It feels very daunting given my limited understanding of the language, and so I've only got the current base cases:

bin_int(bin(zero),0).
bin_int(bin(one),1).
bin_int(bin(B),X):-bin_int(B,X).

Like I said, limited understanding.
It's obviously gonna be recursive but I'm absolutely on how to go about it.
I'll post updates as work on it but for now it's just pseudocode so bear with me.

So, until B is 'one' or 'zero' it is going to have to be two bins and I'm already stuck.
Like how do I write that B must be a bin() tuple and how do I handle the second bin in the tuple having a tuple in itself or not?
Anybody got any as to how to go about this one I'd greatly appreciate some help. Thanks!

答案1

得分: 1

以下是翻译好的部分:

这个练习中提供了两种类型的`bin`数据:一种是类似于`bin(D)`表示一个单一的数字,另一种是`bin(D, Rest)`表示一个数字后面跟着一个剩余部分(另一个数字或序列)。

这里是重新命名和重新排列的代码:

    digit(zero).
    digit(one).
    
    sequence(digit(X), digit(Y)) :-
        digit(X),
        digit(Y).
    sequence(digit(X), sequence(Y, Z)) :-
        digit(X),
        sequence(Y, Z).
        
    binary(digit(Binary)) :-
        digit(Binary).
    binary(sequence(A, B)) :-
        sequence(A, B)。

这不是清晰多了吗?多亏了代码稍微重新排列(非递归规则在递归规则之前),我们可以请求Prolog为我们列举一些解决方案,以探索其行为方式:

    ?- binary(B).
    B = digit(zero) ;
    B = digit(one) ;
    B = sequence(digit(zero), digit(zero)) ;
    B = sequence(digit(zero), digit(one)) ;
    B = sequence(digit(one), digit(zero)) ;
    B = sequence(digit(one), digit(one)) ;
    B = sequence(digit(zero), sequence(digit(zero), digit(zero))) ;
    B = sequence(digit(zero), sequence(digit(zero), digit(one))) ;
    B = sequence(digit(zero), sequence(digit(one), digit(zero))) ;
    B = sequence(digit(zero), sequence(digit(one), digit(one))) ;
    B = sequence(digit(zero), sequence(digit(zero), sequence(digit(zero), digit(zero)))) ;
    B = sequence(digit(zero), sequence(digit(zero), sequence(digit(zero), digit(one)))) ;
    B = sequence(digit(zero), sequence(digit(zero), sequence(digit(one), digit(zero)))) .   % 等等。

请注意,这种列举并不是公平的:具有前导`digit(one)`的嵌套序列永远不会被列举。

现在回答您的问题:

> 像我怎么写B必须是一个bin()元组

就像您之前所做的一样。在Prolog中,您描述的是什么是真的。您不需要描述什么是不真实的。如果您定义了一个谓词如下:

    binary_integer(digit(zero), 0).
    binary_integer(digit(one), 1).
    binary_integer(sequence(Digit, Rest), ...) :- ...

那么,任何第一个参数无法与`digit(X)`或`sequence(X, Y)`匹配的调用都将失败。您不需要为非二进制情况做任何特殊处理。

> 以及如何处理元组中的第二个bin是否包含一个元组或不包含的情况?

递归处理。如果您有一个递归规则来处理`sequence(Digit, Rest)`,而`Rest`本身是一个`sequence(Digit2, Rest2)`,那么它将被处理。

基本上,您想编写(除了表示`zero`和`one`两种数字的两个规则之外)如下的规则:

    binary_integer(sequence(Digit, Rest), N) :-
        "Length is the number of binary digits in Rest",
        Base is Digit << Length,
        binary_integer(Rest, RestValue),
        N is Base + RestValue。

“Length is the number of binary digits in Rest”是留给您练习的部分。

<details>
<summary>英文:</summary>

There are two types of `bin` data given in the exercise: One type is something like `bin(D)` representing a single digit, the other is `bin(D, Rest)` representing a *sequence* of a digit followed by a rest (another digit or sequence).

Here&#39;s the code renamed and rearranged:

    digit(zero).
    digit(one).
    
    sequence(digit(X),digit(Y)):-
        digit(X),
        digit(Y).
    sequence(digit(X),sequence(Y,Z)):-
        digit(X),
        sequence(Y,Z).
        
    binary(digit(Binary)) :-
        digit(Binary).
    binary(sequence(A, B)) :-
        sequence(A, B).

Isn&#39;t this much clearer already? Thanks to the slightly rearranged code (non-recursive rules before recursive ones), we can ask Prolog to enumerate some solutions for us to explore how this behaves:

    ?- binary(B).
    B = digit(zero) ;
    B = digit(one) ;
    B = sequence(digit(zero), digit(zero)) ;
    B = sequence(digit(zero), digit(one)) ;
    B = sequence(digit(one), digit(zero)) ;
    B = sequence(digit(one), digit(one)) ;
    B = sequence(digit(zero), sequence(digit(zero), digit(zero))) ;
    B = sequence(digit(zero), sequence(digit(zero), digit(one))) ;
    B = sequence(digit(zero), sequence(digit(one), digit(zero))) ;
    B = sequence(digit(zero), sequence(digit(one), digit(one))) ;
    B = sequence(digit(zero), sequence(digit(zero), sequence(digit(zero), digit(zero)))) ;
    B = sequence(digit(zero), sequence(digit(zero), sequence(digit(zero), digit(one)))) ;
    B = sequence(digit(zero), sequence(digit(zero), sequence(digit(one), digit(zero)))) .   % etc.

Note that the enumeration isn&#39;t fair: Nested sequences with a leading `digit(one)` will never be enumerated.

Now for your questions:

&gt; Like how do I write that B must be a bin() tuple

Exactly like you did. In Prolog, you describe what is true. Everything you don&#39;t describe is not true. You do not need to describe what is not true. If you define a predicate like

    binary_integer(digit(zero), 0).
    binary_integer(digit(one), 1).
    binary_integer(sequence(Digit, Rest), ...) :- ...

then any call where the first argument is not unifiable with `digit(X)` or `sequence(X, Y)` will fail. You do not need to do anything special for non-binary cases.

&gt; and how do I handle the second bin in the tuple having a tuple in itself or not?

Recursively. If you have a recursive rule to handle `sequence(Digit, Rest)`, and the `Rest` is itself a `sequence(Digit2, Rest2)`, then it will be handled.

Basically you want to write (in addition to the two rules for digits `zero` and `one`) a rule like:

    binary_integer(sequence(Digit, Rest), N) :-
        &quot;Length is the number of binary digits in Rest&quot;,
        Base is Digit &lt;&lt; Length,
        binary_integer(Rest, RestValue),
        N is Base + RestValue.

The `&quot;Length is the number of binary digits in Rest&quot;` is left as an exercise.

</details>



huangapple
  • 本文由 发表于 2023年6月19日 09:42:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76503176.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定