So I'm trying to work out in Prolog how to take an input, and return whether it is a perfect number or not. Currently i'm close but can't figure out why it isn't working the way I want.
I am approaching this through recursion. If X %N == 0, then N and TT(total) is added to TT1. N will decrease by one and the function will be called recursively until it reaches 1, then the total will be compared to the input number X.
My code is:
factors(X,N,TT) :-
( 0 is X mod N -> TT1 is N + TT ),
TT = TT1,
( N > 1 -> N1 is N-1, factors(X, N1, TT1)
; TT1 = X
).
perfect(X) :-
factors(X, X-1, 0).
Currently it is returning that all inputs are false. I hope this isn't majorly incorrect and only needs to be tweaked.
Cheers
Here a solutions, hope it helps
factors(_,N,N,_).
factors(X,N,NT,Sum):-
N < NT,
( 0 is X mod N ->
Sum1 = Sum + N
; Sum1 = Sum),
N1 is N + 1,
factors(X,N1,NT,Sum1).
perfect(X):-
XT is X/2 + 1,
factors(X,1,XT,0).
Related
I want to find all the divisors of a natural number.and output a list.
now my code looks like this:
divisors(0,[]).
divisors(N,[N1|P]):-
N1=N,
RES is (N mod N1),
N1 is N-1,
RES==0,
divisors(N,P).
divisors(N,[N1|P]):-
N1=N,
RES is (N mod N1),
N1 is N-1,
RES\=0,!, fail.
but it doesn't work. tell me, what am I doing wrong?
I've seen what can be done via findall, but I want to do it differently.The idea is as follows. Subtract one from the number (whose divisors we are looking for) each time and if the original number is divided by a new number, then write it to the head of the list.
(I just realized..That I don 't remember N anywhere ..since with recursive calls, it will already be different. I'm completely confused..)
(I just realized..That I don 't remember N anywhere ..since with recursive calls, it will already be different. I'm completely confused..)
That's right, there is no concept of nested scope in Prolog. Instead, we pass everything we need further down among the predicate's arguments, possibly using additional arguments.
Minimal edit to fix your code:
divisors(N,L):- divisors(N,N,L).
divisors(N,0,[]):- !.
divisors(N,N1,[N1|P]):- % use N1
%N1=N,
RES is (N mod N1),
N2 is N1-1,
RES==0,
divisors(N,N2,P).
divisors(N,N1,P):- % skip N1
%N1=N,
RES is (N mod N1),
N2 is N1-1,
RES\=0, %!, fail
divisors(N,N2,P). % same P
The result list L is instantiated in the top-down fashion.
Examples:
49 ?- divisors(12,L).
L = [12, 6, 4, 3, 2, 1].
50 ?- divisors(37,L).
L = [37, 1].
The brute force way of finding all the divisors of a natural number would be something like this:
divisors( 0 , [] ) . % zero is a special case
divisors( N , Ds ) :- % otherwise, the general case applies
integer(N), % - N must be an integer, and
N > 0, % - N must be positive (and greater than 0)
divisors(1,N,Ds) % - invoke our helper predicate to try all possible divisors from 1–N inclusive
. % - Easy!
divisors( D , N , [D|Ds] ) :- % case 1: D is a divisor of N
D < N , % - D must be less than N, and
0 =:= N mod D, % - D must be an integer divisor of N,
!, % - eliminate the choice point
D1 is D+1, % - increment D
divisors(D1,N,Ds) % - recurse down, with D prepended to the result list
. %
divisors( D , N , Ds ) :- % case 2: D is not a divisor of N
D < N , % - D must be less than N, and
0 =\= N mod D, % - D must not be an integer divisor of N
!, % - eliminate the choice point
D1 is D+1, % - increment D
divisors(D1,N,Ds) . % - recurse down, discarding the current D
divisors( N , N , [N] ) % case 3: every number is its own divisor.
. %
How can I solve x ^ ( 1 / y ) mod m fast, where x, y, m are all positive integers?
This is to reverse the calculation for x ^ y mod m. For example
party A hands party B agree on positive integer y and m ahead of time
party A generates a number x1 (0 < x1 < m), and hands party B the result of x1 ^ y mod m, call it x2
party B calculates x2 ^ ( 1 / y ) mod m, so that it gets back x1
I know how to calculate x1 ^ y mod m fast, but I don't know how to calculate x2 ^ (1 / y) mod m fast. Any suggestions?
I don't know how to call this question. Given x ^ y mod m is called modular exponentiation, is this called modular root?
I think you're asking this question: Given y, m, and the result of x^y (mod m) find x (assuming 0 <= x < m).
In general, this doesn't have a solution -- for example, for y=2, m=4, 0^2, 1^2, 2^2, 3^2 = 0, 1, 0, 1 (mod 4), so if you're given the square of a number mod 4, you can't get back the original number.
However, in some cases you can do it. For example, when m is prime and y is coprime to m-1. Then one can find y' such that for all 0 <= x < m, (x^y)^y' = x (mod m).
Note that (x^y)^y' = x^(yy'). Ignoring the trivial case when x=0, if m is prime Fermat's Little Theorem tells us that x^(m-1) = 1 (mod m). Thus we can solve yy' = 1 (mod m-1). This has a solution (which can be found using the extended Euclidean algorithm) assuming y and m-1 are coprime.
Here's working code, with an example with y=5, m=17. It uses the modular inverse code from https://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm
def egcd(a, b):
if a == 0: return b, 0, 1
g, x, y = egcd(b%a, a)
return g, y - (b//a) * x, x
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise AssertionError('no inverse')
return x % m
def encrypt(xs, y, m):
return [pow(x, y, m) for x in xs]
def decrypt(xs, y, m):
y2 = modinv(y, m-1)
return encrypt(xs, y2, m)
y = 5
m = 17
e = encrypt(range(m), y, m)
print decrypt(e, y, m)
RSA is based on the case when m is the product of two distinct primes p, q. The same ideas as above apply, but one needs to find y' such that yy' = 1 (mod lcm((p-1)(q-1))). Unlike above, one can't do this easily only given y and m, because there are no known efficient methods for finding p and q.
I'm attempting to create a program where given N, I need Q = 0...N.
So if given N = 1: Q = 0. If given N = 5: Q = 0, Q = 1,...,Q = 4
My attempt so far:
values(N,Q) :- values_helper(0,N,Q).
values_helper(N, N, Q).
values_helper(X,N,Q) :- X0 is X + 1, X0 < N, values_helper(X0,N,X0).
My logic behind it is that I increment X until it reaches the value of N, at which point the program stops. However, I'm not getting any bindings for Q, just an empty set. I also know that I'm neglecting to stop at N - 1.
EDIT: Fixed up ambiguities with the description.
Both of your values_helper clauses don't do what you expect. The first one succeeds if the first 2 arguments are the same, and doesn't impose any constraints on Q. What you actually want is that Q is set equal to the first argument, as long as it's smaller than the second argument:
values_helper(Q, N, Q) :- Q < N.
In the second clause, again you don't use Q anywhere. The recursive call should be values_helper(X0, N, Q), giving:
values_helper(X, N, Q) :- X0 is X + 1, X0 < N, values_helper(X0, N, Q).
These clauses give the expected output:
?- values(5,Q).
Q = 0 ? ;
Q = 1 ? ;
Q = 2 ? ;
Q = 3 ? ;
Q = 4 ? ;
no
Note that for any N <= 0, this terminates without finding any value for Q, which I believe is the expected behavior.
I have been trying to solve a problem on spoj.
Here is the link to the problem.
http://www.spoj.pl/problems/TAP2012B/
From what I have interpreted, I need to find the number of solutions of the equation xy+yz+xz = N
where n is given to us.
x>=y>=z
z can be zero.
But x and y cannot.
I tried doing solving this via implementing 3 for loops (bad approach).
It is giving the right answer but it is too slow.
Also, other people have solved it in almost no time (0.00)
So I am sure there is a very different approach to this problem.
For N = 20,
the number of different solutions is 5 :
(6,2,1)
(5,4,0)
(10,2,0)
(4,2,2,)
(20,1,0)
Maybe there is some brillian solution built on number-theory. But simply rethinking the task can reduce algorithm complexity as well.
For instance, we don't need a third loop as we can calculate z as (N - x*y)/(x+y). And we don't have to run y all the way to x every time, as we know, that z is not negative, therefore N >= xy.
N = 9747
for x in range(1, N+1):
max_y = min( N / x, x)
for y in range(1, max_y+1):
if (N - x*y) % (x+y) == 0:
z = (N - x*y) / (x+y)
if z <= y:
print x,y,z
You are approaching towards the right direction there will be 3 nested loops but try to reduce the no. of times the loop operates.... Follow the question and conditions carefully.....
You are obviously learning, so it would have had been better if you would do everything yourself, but you now have a great solution from akalenuk, and I hope that you will learn a few things from it as well.
If you are learning python at the same time, I will give you an equivalent solution to akalenuk's, but this time with list comprehension which is a very useful mechanism:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, min( N/x, x) + 1 )
for z in [ (N - x*y) / (x+y) ]
if (N - x*y) % (x+y) == 0
if z <= y]
The point is in pruning the solution space. The code above is already quite optimised. You might start with something like:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, x+1 )
for z in range(y+1)
if N == x*y + y*z + x*z]
This would run quite long. So, the first point of optimization may be adding the condition on y:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, x+1 )
if x*y <= N
for z in range(y+1)
if N == x*y + y*z + x*z]
This already cuts down the time considerably, as for non-promising y the z-loop is not run at all. Then, you notice that you may actually replace that if-statement by explicit computation of maximum y, as akalenuk did:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, min(x, N/x) +1)
for z in range(y+1)
if N == x*y + y*z + x*z]
This will again speed it up.
As you are learning, I recommend you try all these, and your own, time it, and learn from it.
I also recommend to try and time different, similar solutions
I've got a predicate taking a single argument. When there is a solution, this single argument should equal some other argument I have (I have a predicate that goes from one argument to three).
I can print the solution easily to see that the algorithm works. However, I just get false/no when the program runs. I think this is something to do with me giving the program a variable and asking it to return the same variable but altered by the program's execution. I've never had this situation before.
Any ideas guys?
If anyone as any suggestions about the code as a whole then I would welcome comments about that too.
Thanks very much and happy new year :).
% Eulers totient function
phi( M ) :-
phi( 0, 0, M ).
phi( Count, Inter, M ) :-
Count = M,
print(Inter),
M is Inter.
phi( Count, Inter, M ) :-
Count \= M,
coprime( Count, M ),
InterNew is Inter + 1,
CountNew is Count + 1,
phi( CountNew, InterNew, M ).
phi( Count, Inter, M ) :-
Count \= M,
\+ coprime( Count, M ),
CountNew is Count + 1,
phi( CountNew, Inter, M ).
UPDATE: This problem is one of the '99 Prolog problems' at : http://sites.google.com/site/prologsite/prolog-problems/2 and it's question 2.09.
UPDATE: coprime/2 predicate was asked for:
% coprime is defined as two integers having a gcd of 1
coprime( X, Y ) :-
gcd( X, Y, 1 ).
which uses gcd predicate:
% calculating the greatest common divisor of two numbers
% recursive version of Euclidian algorithm
gcd( G, 0, G ).
gcd( Lo, Hi, G ) :-
Hi \= 0,
Inter is Lo mod Hi,
gcd( Hi, Inter, G ).
The false/no answer results from the call M is Inter, which tries to establish equality between the totient Inter and the input number M. Since φ(n) is never equal to n except when n = 1, this almost always fails.
You may have intended to assign the value of Inter to M, but this impossible because M is always bound.