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.
- 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, useX is <expression here>
. - 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:
- Prevent the first digits being 0.
- 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.
精彩评论