问题
I want to find all of the cube roots that their cubes + their remainder add up to a number to user inputs. So for example, the query:
?- smallerCube(X,20).
Would give the result:
1 remainder 19
2 remainder 12
Since 1^3 = 1 (remainder 19), 2^3 = 8(remainder 12) and 3^3 = 27 which is bigger than the initial input of 20, and hence it's not being calculated here.
So far this is my code:
cubeLess(X,B,R) :-
X =< B,
X1 is X*X*X,
R is B-X1.
smallerCube(X,B) :- int(X),
X2 is X*X*X,
X2 =< B,
cubeLess(X2,B,R),
write(X), write(' rest '), writeln(R).
int(1).
int(N) :- int(N1), N is N1+1.
I use cubeLess to get the remainder, int to generate numbers from 1 onward. However, when I run the following query:
?- smallerCube(X,130)
I get the following weird result:
1 rest 129
X = 1
2 rest -382
X = 2
3 rest -19553
X = 3 ;
Why did it work for X=1, but gave negative results for X=2,3?
回答1:
Use clpfd!
:- use_module(library(clpfd)).
No need to worry about using clpfd for the 1st time—you'll get the meaning in a moment for sure!
smallerCube_(X, Remainder, Maximum) :- X #>= 0, Remainder #>= 0, Remainder + X^3 #= Maximum.
First, the most general query of smallerCube_/3
:
?- smallerCube_(X, Remainder, 20). X in 1..2, _A in 1..8, Remainder in 12..19, X^3 #= _A, Remainder+_A #= 20.
One answer—two solutions: let's see them separated!
?- smallerCube_(X, Remainder, 20), indomain(X). X = 1, Remainder = 19 % 20 #= 1^3 + 19 ; X = 2, Remainder = 12. % 20 #= 2^3 + 12
Here's the second query the OP wanted to run:
?- smallerCube_(X, Remainder, 130), indomain(X). X = 1, Remainder = 129 % 130 #= 1^3 + 129 ; X = 2, Remainder = 122 % 130 #= 2^3 + 122 ; X = 3, Remainder = 103 % ... ; X = 4, Remainder = 66 % ... ; X = 5, Remainder = 5. % 130 #= 5^3 + 5
Done! So what's next? Of course, that is up to you, so:
- Why not re-invest the time clpfd saved you?
- Why not read this very compact CLP(FD) primer as a jumpstart?
来源:https://stackoverflow.com/questions/35087702/finding-all-cube-roots-with-a-number-as-a-limit