Implementing isPrime in Scala using tail recursion - algorithm

I'm working on an exercise which requires me to implement isPrime in scala using tail recursion. I do have an implementation however, I'm having issues with producing the right base case.
So my algorithm involves checking all numbers from 2 to N/2, since N/2 would be the largest factor of N.
def isPrime(n: Int): Boolean = {
def isPrimeUntil(t: Int): Boolean = {
if(t == 2) true
else n % t != 0 && isPrimeUntil(t - 1)
}
isPrimeUntil(n/2)
}
So basically if I want to check if 15 is a prime I will check all numbers from 7 to 2.
Here is my trace:
isPrimeUntil(7) -> true && isPrimeUntil(6)
-> true && isPrimeUntil(5)
-> false && isPrimeUntil(4)
Because of short-circuit evaluation, the function returns false at this point.
However, my implementation fails for the basic case of checking if 3 is prime.

3 isn't your only problem. It also returns true for 4 ...
Your base case should be 1, not 2:
def isPrimeUntil(t: Int): Boolean = t == 1 || t > 1 && n%t != 0 && isPrimeUntil(t-1)

Although Krzystof correctly pointed that the source of the problem is integer division, I don't like his solution. I believe that the proper fix is change the test to
if(t <= 2) true
With such check in the case of n = 3 and so n/2 = 1 it will stop without going to t = 0.
Some benefits:
The modified check (t <= 2) on almost any modern hardware is as efficient as the check for (t == 2)
IMHO it better conveys the logic
It is very inefficient way to write (n.toDouble/2).ceil.toInt that way. It's easier and faster to write (n+1)/2 instead of doing 2 conversion (to double and back to int)
It doesn't require an excessive check for all odd n ((n+1)/2 is never the smallest divisor for an odd n where there is a difference between n/2 and ceil(n/2))

Related

random-acess machine (RAM) - Test square-free n

I'm writing a random-acess machine (RAM) using a simulator that tests whether a given natural number is square-free. My goal is to then analyze its complexity.
At high-level I would use the following test function
def isSquareFree(n):
if n % 2 == 0:
n = n / 2
if n % 2 == 0:
return False
for i in range(3, int(sqrt(n) + 1)):
if n % i == 0:
n = n / i
if n % i == 0:
return False
return True
My problem is, I am not sure how to calculate the square root of n using RAM-commands and can't find much resources online. So I am reconsidering if this is actually the right way to do it.
What are alternative ways to test if a natural number is square-free, that can be implemented using RAM?
Thanks.
If you just want to avoid the sqrt in your code you can simply test for i*i<=n. This probably is a good idea anywise, as calculating the square root is a quite hard thing to do.
Thus I would change your code to:
def isSquareFree(n):
i=2
while i*i <= n:
if n % i == 0:
n = n / i
if n % i == 0:
return False
i = i+1
return True
The above only uses pretty atomic operations, so I hope this will help you. But I am not familiar with RAM programming so I am not sure whether this solves your problem.

newbie : Ruby programming for factorials

So I got this question as an assignment in Computer class and I literally have no idea why the solution was such. I am hoping someone can explain it thoroughly to me.
My problem is:
How does one know that n*(n-1)*(n-2)*...*2*1 is actually just the math expression n! Is this just a magical formula that I have to remember? (Yes, I don't know much math beyond arithmetic)
Is there a better way of programming factorials
Write a method that takes an integer n in; it should return
n*(n-1)*(n-2)*...*2*1. Assume n >= 0.
As a special case, factorial(0) == 1.
Difficulty: easy.
def factorial(n)
if n < 0
return nil
end
result = 1
while n > 0
result = result * n
n -= 1
end
return result
end
puts("factorial(0) == 1: #{factorial(0) == 1}")
puts("factorial(1) == 1: #{factorial(1) == 1}")
puts("factorial(2) == 2: #{factorial(2) == 2}")
puts("factorial(3) == 6: #{factorial(3) == 6}")
puts("factorial(4) == 24: #{factorial(4) == 24}")
Yes, that is the definition of a factorial. One knows it by having learned the definition.
There are many ways to code up a factorial. Yours happens to be the most basic one. As you learn more about Ruby, you will start to be able to write more idiomatic code. For example...
def factorial_functional(n)
n < 0 ? nil : (1..n).inject(1, &:*)
end
def factorial_recursive(n)
return if n < 0
return 1 if n == 0
n * factorial_recursive(n - 1)
end
It is arguable what is "better", since there are so many factors: readability, conciseness, speed, memory usage... And readability is directly related to the target audience: I'm sure your code is more readable to you than either of my examples, but to someone experienced it is much more of a hassle to go through your longer code.
Amadan already showed better ways of writing the factorials method, but I believe you were also asking for an explanation of the solution you brought in.
# The method `factorial` receives a number `n` and returns `n!`.
def factorial(n)
if n < 0 # If the number `n` is negative
return nil # `n!` can't be calculated, so return nothing.
end # Otherwise, go on...
result = 1 # `result` is 1. For now...
while n > 0 # While the number `n` is positive
result = result * n # `result` becomes `result` times `n`.
n -= 1 # Decrease the number `n` by one.
end
# Once the number `n` becomes zero, `result` is
# equal to the multiplication of all numbers from 1
# to what `n` was at the very beginning.
return result # Return `result`
end
I would also like to contribute the following "better" way of defining the factorial method that can be read, more or less, in plain English:
def factorial(number)
return unless number.is_a? Integer and number >= 0
total = 1
number.downto 1 do |this_number|
total = total * this_number
end
return total
end

calculating power in a recursive way coffeescript case of exponent == 0

I am trying to write fun calculating in a recursive way powers for given base and exponent (only postive integers with 0 are assumed to be correct input)
Code is here: http://jsfiddle.net/andilab/hcqBe/
It does not work for the case of 0.
pow = (a,p) ->
if p >= 1
if p == 1
a
else
p = p-1
a*pow(a,p)
else
1
Have I done something wrong?

Probabilistic Sieve of Eratosthenes

Consider the following algorithm.
function Rand():
return a uniformly random real between 0.0 and 1.0
function Sieve(n):
assert(n >= 2)
for i = 2 to n
X[i] = true
for i = 2 to n
if (X[i])
for j = i+1 to n
if (Rand() < 1/i)
X[j] = false
return X[n]
What is the probability that Sieve(k) returns true as a function of k ?
Let's define a series of random variables recursively:
Let Xk,r denote the indicator variable, taking value 1 iff X[k] == true by the end of the iteration in which the variable i took value r.
In order to have fewer symbols and since it makes more intuitive sense with the code, we'll just write Xk,i which is valid although would have been confusing in the definition since i taking value i is confusing when the first refers to the variable in the loop and the latter to the value of the variable.
Now we note that:
P(Xk,i ~ 0) = P(Xk,i-1 ~ 0) + P(Xk,i-1 ~ 1) * P(Xk-1,i-1 ~ 1) * 1/i
(~ is used in place of = just to make it understandable, since = would otherwise take two separate meanings and looks confusing).
This equality holds by virtue of the fact that either X[k] was false at the end of the i iteration either because it was false at the end of the i-1, or it was true at that point, but in that last iteration X[k-1] was true and so we entered the loop and changed X[k] with probability of 1/i. The events are mutually exclusive, so there is no intersection.
The base of the recursion is simply the fact that P(Xk,1 ~ 1) = 1 and P(X2,i ~ 1) = 1.
Lastly, we note simply that P(X[k] == true) = P(Xk,k-1 ~ 1).
This can be programmed rather easily. Here's a javascript implementation that employs memoisation (you can benchmark if using nested indices is better than string concatenation for the dictionary index, you could also redesign the calculation to maintain the same runtime complexity but not run out of stack size by building bottom-up and not top-down). Naturally the implementation will have a runtime complexity of O(k^2) so it's not practical for arbitrarily large numbers:
function P(k) {
if (k<2 || k!==Math.round(k)) return -1;
var _ = {};
function _P(n,i) {
if(n===2) return 1;
if(i===1) return 1;
var $ = n+'_'+i;
if($ in _) return _[$];
return _[$] = 1-(1-_P(n,i-1) + _P(n,i-1)*_P(n-1,i-1)*1/i);
}
return _P(k,k-1);
}
P(1000); // 0.12274162882390949
More interesting would be how the 1/i probability changes things. I.e. whether or not the probability converges to 0 or to some other value, and if so, how changing the 1/i affects that.
Of course if you ask on mathSE you might get a better answer - this answer is pretty simplistic, I'm sure there is a way to manipulate it to acquire a direct formula.

Can I reduce the computational complexity of this?

Well, I have this bit of code that is slowing down the program hugely because it is linear complexity but called a lot of times making the program quadratic complexity. If possible I would like to reduce its computational complexity but otherwise I'll just optimize it where I can. So far I have reduced down to:
def table(n):
a = 1
while 2*a <= n:
if (-a*a)%n == 1: return a
a += 1
Anyone see anything I've missed? Thanks!
EDIT: I forgot to mention: n is always a prime number.
EDIT 2: Here is my new improved program (thank's for all the contributions!):
def table(n):
if n == 2: return 1
if n%4 != 1: return
a1 = n-1
for a in range(1, n//2+1):
if (a*a)%n == a1: return a
EDIT 3: And testing it out in its real context it is much faster! Well this question appears solved but there are many useful answers. I should also say that as well as those above optimizations, I have memoized the function using Python dictionaries...
Ignoring the algorithm for a moment (yes, I know, bad idea), the running time of this can be decreased hugely just by switching from while to for.
for a in range(1, n / 2 + 1)
(Hope this doesn't have an off-by-one error. I'm prone to make these.)
Another thing that I would try is to look if the step width can be incremented.
Take a look at http://modular.fas.harvard.edu/ent/ent_py .
The function sqrtmod does the job if you set a = -1 and p = n.
You missed a small point because the running time of your improved algorithm is still in the order of the square root of n. As long you have only small primes n (let's say less than 2^64), that's ok, and you should probably prefer your implementation to a more complex one.
If the prime n becomes bigger, you might have to switch to an algorithm using a little bit of number theory. To my knowledge, your problem can be solved only with a probabilistic algorithm in time log(n)^3. If I remember correctly, assuming the Riemann hypothesis holds (which most people do), one can show that the running time of the following algorithm (in ruby - sorry, I don't know python) is log(log(n))*log(n)^3:
class Integer
# calculate b to the power of e modulo self
def power(b, e)
raise 'power only defined for integer base' unless b.is_a? Integer
raise 'power only defined for integer exponent' unless e.is_a? Integer
raise 'power is implemented only for positive exponent' if e < 0
return 1 if e.zero?
x = power(b, e>>1)
x *= x
(e & 1).zero? ? x % self : (x*b) % self
end
# Fermat test (probabilistic prime number test)
def prime?(b = 2)
raise "base must be at least 2 in prime?" if b < 2
raise "base must be an integer in prime?" unless b.is_a? Integer
power(b, self >> 1) == 1
end
# find square root of -1 modulo prime
def sqrt_of_minus_one
return 1 if self == 2
return false if (self & 3) != 1
raise 'sqrt_of_minus_one works only for primes' unless prime?
# now just try all numbers (each succeeds with probability 1/2)
2.upto(self) do |b|
e = self >> 1
e >>= 1 while (e & 1).zero?
x = power(b, e)
next if [1, self-1].include? x
loop do
y = (x*x) % self
return x if y == self-1
raise 'sqrt_of_minus_one works only for primes' if y == 1
x = y
end
end
end
end
# find a prime
p = loop do
x = rand(1<<512)
next if (x & 3) != 1
break x if x.prime?
end
puts "%x" % p
puts "%x" % p.sqrt_of_minus_one
The slow part is now finding the prime (which takes approx. log(n)^4 integer operation); finding the square root of -1 takes for 512-bit primes still less than a second.
Consider pre-computing the results and storing them in a file. Nowadays many platforms have a huge disk capacity. Then, obtaining the result will be an O(1) operation.
(Building on Adam's answer.)
Look at the Wikipedia page on quadratic reciprocity:
x^2 ≡ −1 (mod p) is solvable if and only if p ≡ 1 (mod 4).
Then you can avoid the search of a root precisely for those odd prime n's that are not congruent with 1 modulo 4:
def table(n):
if n == 2: return 1
if n%4 != 1: return None # or raise exception
...
Based off OP's second edit:
def table(n):
if n == 2: return 1
if n%4 != 1: return
mod = 0
a1 = n - 1
for a in xrange(1, a1, 2):
mod += a
while mod >= n: mod -= n
if mod == a1: return a//2 + 1
It looks like you're trying to find the square root of -1 modulo n. Unfortunately, this is not an easy problem, depending on what values of n are input into your function. Depending on n, there might not even be a solution. See Wikipedia for more information on this problem.
Edit 2: Surprisingly, strength-reducing the squaring reduces the time a lot, at least on my Python2.5 installation. (I'm surprised because I thought interpreter overhead was taking most of the time, and this doesn't reduce the count of operations in the inner loop.) Reduces the time from 0.572s to 0.146s for table(1234577).
def table(n):
n1 = n - 1
square = 0
for delta in xrange(1, n, 2):
square += delta
if n <= square: square -= n
if square == n1: return delta // 2 + 1
strager posted the same idea but I think less tightly coded. Again, jug's answer is best.
Original answer: Another trivial coding tweak on top of Konrad Rudolph's:
def table(n):
n1 = n - 1
for a in xrange(1, n // 2 + 1):
if (a*a) % n == n1: return a
Speeds it up measurably on my laptop. (About 25% for table(1234577).)
Edit: I didn't notice the python3.0 tag; but the main change was hoisting part of the calculation out of the loop, not the use of xrange. (Academic since there's a better algorithm.)
Is it possible for you to cache the results?
When you calculate a large n you are given the results for the lower n's almost for free.
One thing that you are doing is repeating the calculation -a*a over and over again.
Create a table of the values once and then do look up in the main loop.
Also although this probably doesn't apply to you because your function name is table but if you call a function that takes time to calculate you should cache the result in a table and just do a table look up if you call it again with the same value. This save you the time of calculating all of the values when you first run but you don't waste time repeating the calculation more than once.
I went through and fixed the Harvard version to make it work with python 3.
http://modular.fas.harvard.edu/ent/ent_py
I made some slight changes to make the results exactly the same as the OP's function. There are two possible answers and I forced it to return the smaller answer.
import timeit
def table(n):
if n == 2: return 1
if n%4 != 1: return
a1=n-1
def inversemod(a, p):
x, y = xgcd(a, p)
return x%p
def xgcd(a, b):
x_sign = 1
if a < 0: a = -a; x_sign = -1
x = 1; y = 0; r = 0; s = 1
while b != 0:
(c, q) = (a%b, a//b)
(a, b, r, s, x, y) = (b, c, x-q*r, y-q*s, r, s)
return (x*x_sign, y)
def mul(x, y):
return ((x[0]*y[0]+a1*y[1]*x[1])%n,(x[0]*y[1]+x[1]*y[0])%n)
def pow(x, nn):
ans = (1,0)
xpow = x
while nn != 0:
if nn%2 != 0:
ans = mul(ans, xpow)
xpow = mul(xpow, xpow)
nn >>= 1
return ans
for z in range(2,n) :
u, v = pow((1,z), a1//2)
if v != 0:
vinv = inversemod(v, n)
if (vinv*vinv)%n == a1:
vinv %= n
if vinv <= n//2:
return vinv
else:
return n-vinv
tt=0
pri = [ 5,13,17,29,37,41,53,61,73,89,97,1234577,5915587277,3267000013,3628273133,2860486313,5463458053,3367900313 ]
for x in pri:
t=timeit.Timer('q=table('+str(x)+')','from __main__ import table')
tt +=t.timeit(number=100)
print("table(",x,")=",table(x))
print('total time=',tt/100)
This version takes about 3ms to run through the test cases above.
For comparison using the prime number 1234577
OP Edit2 745ms
The accepted answer 522ms
The above function 0.2ms

Resources