Prolog中的自恋数字

时间:2011-06-07 21:49:34

标签: prolog

大家好,我又来了,本周我做了这个家庭作业:

我应该找到1010000之间的所有数字,其中包含如下示例的属性:

89 = 8^1 + 9^2
2427 = 2^1 + 4^2 + 2^3 + 7^4 = 2 + 16 + 8 + 2401

我在Haskell中实现了这个,并且它运行得很好(我认为)并返回一个像这样的List:

[89,135,175,518,598,1306,1676,2427]

然后我尝试在Prolog中编写它(如果需要),如下所示:

num(0).
num(1).
num(2).
num(3).
num(4).
num(5).
num(6).
num(7).
num(8).
num(9).

allNarc(X):- num(A),num(B),num(C),num(D),
             X = A*1000+B*100+C*10+D,Y = A**1+B**2+C**3+D**4,
             X =:= Y,X>10.
allNarc(X):- num(B),num(C),num(D),
             X = B*100+C*10+D,Y = B**1+C**2+D**3,
             X =:= Y,X>10.
allNarc(X):- num(C),num(D),
             X = C*10+D,Y = C**1+D**2,
             X =:= Y,X>10.

结果是这样的:

?- allNarc(X).
X = 1*1000+3*100+0*10+6 ;
X = 1*1000+6*100+7*10+6 ;
X = 2*1000+4*100+2*10+7 ;
X = 0*100+4*10+3 ;    <- 43
X = 0*100+6*10+3 ;    <- 63
X = 1*100+3*10+5 ;
X = 1*100+7*10+5 ;
X = 5*100+1*10+8 ;
X = 5*100+9*10+8 ;
X = 8*10+9 ;
false.

显然4364不属于这个组,结果只是丑陋,任何人都可以帮助我获得输出,就像我的Haskell实现中的结果一样吗?

2 个答案:

答案 0 :(得分:3)

两点。

  1. 当您说X =时,您正在统一=的左右两侧。如果您希望X是一个等于评估表达式的数字,请使用X is <expression here>
  2. 您希望阻止第一个位置的零:num(A), A \= 0, num(B), ...
  3. 进行这些更改后,我得到了:

    ?- allNarc(X).
    X = 1306 ? ;
    X = 1676 ? ;
    X = 2427 ? ;
    X = 135 ? ;
    X = 175 ? ;
    X = 518 ? ;
    X = 598 ? ;
    X = 89 ? ;
    no
    

    您还可以使用bagof来收集值。例如bagof(X,allNarc(X),Narcs). Narcs是您的值列表。

答案 1 :(得分:2)

你需要:

  1. 防止第一个数字为0。
  2. 确保将X评估为您想要的值。目前,您使用的是不合适的字词统一,您需要使用is关键字。
  3. 请参阅:

    num(0).
    num(1).
    num(2).
    num(3).
    num(4).
    num(5).
    num(6).
    num(7).
    num(8).
    num(9).
    posnum(A) :- num(A), A \= 0.
    
    allNarc(X):- posnum(A),num(B),num(C),num(D),
                 X is A*1000+B*100+C*10+D,Y is A**1+B**2+C**3+D**4,
                 X =:= Y,X>10.
    allNarc(X):- posnum(B),num(C),num(D),
                 X is B*100+C*10+D,Y is B**1+C**2+D**3,
                 X =:= Y,X>10.
    allNarc(X):- posnum(C),num(D),
                 X is C*10+D,Y is C**1+D**2,
                 X =:= Y,X>10.
    

    请注意,您可以使用setof找到所有数字:

    ?- setof(X,allNarc(X),XL).
    XL = [89, 135, 175, 518, 598, 1306, 1676, 2427].
    

    通过逐个列出它们会更加方便。