开发者

Narcissistic Number in Prolog

开发者 https://www.devze.com 2023-03-11 07:31 出处:网络
hi everyone I\'m here again, this week I got this Homework: I should find all the numbers between 10 and 10000 which has property like the following example:

hi everyone I'm here again, this week I got this Homework:

I should find all the numbers between 10 and 10000 which has property like the following example:

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

I have this in Haskell implemented, and it works just fine(I think) and return a List like this:

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

and then I tried to write it in Prolog(as required too) like the following:

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.

the result is something like this:

?- 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.

clearly 43 and 64 should not belong to this group and the result is just ugly, can anyone help me to get output like the result in my Haskell implementation?


Two points.

  1. when you say X = you are unifying the left and right sides of =. If you want X to be a number equal to evaluating the expression, use X is <expression here> .
  2. you want to prevent a zero in the first position: num(A), A \= 0, num(B), ...

After making those changes I get:

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

You could also use bagof to collect the values. e.g. bagof(X,allNarc(X),Narcs). Narcs is then a list of your values.


You need to:

  1. Prevent the first digits being 0.
  2. Make sure that X is evaluated to the value you want. At the moment you are using term unification which is not appropriate, you need to use the is keyword.

See:

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.

Note that you can then find all the numbers using setof:

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

This is much more convenient that listing through them one by one.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号