Miller–Rabin SPOJ WA - prime-factoring

I am trying to implement Miller-Rabin for the first time. My code is giving correct answer for all the testcases, i tried but still on SPOJ it is giving wrong answer.
Problem Statement: I am supposed to print "YES" if entered number is prime otherwise "NO"
Please help:
Problem Link: http://www.spoj.com/problems/PON/
CODE:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define LL long long
LL expo(LL a,LL b,LL c)
{
LL x=1,y=a;
if(b==0)
return 1;
while(b)
{
if(b%2==1)
x=(x*y)%c;
y=(y*y)%c;
b=b/2;
}
return x;
}
int main()
{
LL t,s,x,a,n,prime,temp;
scanf("%lld",&t);
srand(time(NULL));
while(t--)
{
scanf("%lld",&n);
if(n<2)
puts("NO");
else if(n==2)
puts("YES");
else if(n%2==0)
puts("NO");
else
{
s=n-1;
prime=1;
while(s%2==0)
s=s/2;
for(int i=0;i<20;i++)
{
a=rand()%(n-1)+1;
x=expo(a,s,n);
temp=s;
while((temp!=n-1)&&(x!=1)&&(x!=n-1))
{
x=(x*x)%n;
temp*=2;
}
if((x!=n-1)&&(temp%2==0))
{
prime=0;
break;
}
}
if(prime==0)
puts("NO");
else
puts("YES");
}
}
return 0;
}

Keep in mind that puts appends a newline character '\n' to the string that you're giving. You can try with printf instead.

I think your calculation of s and d is incorrect:
function isStrongPseudoprime(n, a)
d := n - 1; s := 0
while d % 2 == 0
d := d / 2; s := s + 1
t := powerMod(a, d, n)
if t == 1 return ProbablyPrime
while s > 0
if t == n - 1 return ProbablyPrime
t := (t * t) % n
s := s - 1
return Composite
I discuss the Miller-Rabin method in an essay at my blog.

You are getting wrong answer because of integer overflow as you are multiplying 2 long number which can't be holded in a single long long type.
Here is a solution in python to overcome the issue
import random
_mrpt_num_trials = 25 # number of bases to test
def is_probable_prime(n):
assert n >= 2
# special case 2
if n == 2:
return True
# ensure n is odd
if n % 2 == 0:
return False
# write n-1 as 2**s * d
# repeatedly try to divide n-1 by 2
s = 0
d = n - 1
while True:
quotient, remainder = divmod(d, 2)
if remainder == 1:
break
s += 1
d = quotient
assert(2 ** s * d == n - 1)
def try_composite(a):
if pow(a, d, n) == 1:
return False
for i in range(s):
if pow(a, 2 ** i * d, n) == n - 1:
return False
return True
for _ in range(_mrpt_num_trials):
a = random.randrange(2, n)
if try_composite(a):
return False
return True
for i in range(int(input())):
a = int(input())
if is_probable_prime(a):
print("YES")
else:
print("NO")

Related

cant understand the calculation of return statement of binary program with recursion in c

Program of binary conversion with recursion
it is working fine but i cant understand the meaning of one statement
Can any one help me to explain following
return (num % 2) + 10 * binary_conversion(num / 2);
while having input of 13
i am lil confused getting like this num =13;
13%2 = 1 + 10 * 6 = 66 , something stupid like calculation
int binary_conversion(int);
int main()
{
int num, bin;
printf("Enter a decimal number: ");
scanf("%d", &num);
bin = binary_conversion(num);
printf("The binary equivalent of %d is %d\n", num, bin);
}
int binary_conversion(int num)
{
if (num == 0)
{
return 0;
}
else
{
return (num % 2) + 10 * binary_conversion(num / 2);
}
}
Your confusions stems from not understanding the operation of recursion. It's time to interview the function with print statements. This will allow you to follow the control and data flow of the routine.
int binary_conversion(int num)
{
printf("ENTER num = %d\n", num);
if (num == 0)
{
printf("BASE CASE returns 0\n");
return 0;
}
else
{
printf("RECURSION: new bit = %d, recur on %d\n", num % 2, num / 2);
return (num % 2) + 10 * binary_conversion(num / 2);
}
}

Sequence function error?

I'm getting an error on line 3 "TypeError: 'int' object is not iterable," and its been bothering me. Any advice/fixes appreciated.
Example test: collatz_counts(4) → 3 # 4 -> 2 -> 1 (3 steps)
Code I have:
def collatz_counts(x):
num = 0
for i in (x):
if i == 1:
num += 1
return num
elif i % 2 == 0:
num(i) / 2
num += 1
num.append(i)
else:
num = (i*2) + 3
num += 1
num.append(i)
return num
This can be solved recursively:
def collatz_length(n):
if n == 1:
return 1
return 1 + collatz_length(3*n+1 if n%2 else n//2)
Which lends itself to be memoized if you are going to be calling for a range of numbers, e.g. in Py3
import functools as ft
#ft.lru_cache(maxsize=None)
def collatz_length(n):
if n == 1:
return 1
return 1 + collatz_length(3*n+1 if n%2 else n//2)
Which will run through the first million collatz sequences in about 2.31s vs about 28.6s for the iterative solution.
Use a while loop. Just modify x in place until you get to 1 and keep track of the number of steps each time you run a cycle.
def collatz_counts(x):
steps = 0
while x != 1:
if x % 2:
x = x * 3 + 1
else:
x = x // 2
steps += 1
return steps

Tweaking a Function in Python

I am trying to get the following code to do a few more tricks:
class App(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.answerLabel = Label(self, text="Output List:")
self.answerLabel.grid(row=2, column=1, sticky=W)
def psiFunction(self):
j = int(self.indexEntry.get())
valueList = list(self.listEntry.get())
x = map(int, valueList)
if x[0] != 0:
x.insert(0, 0)
rtn = []
for n2 in range(0, len(x) * j - 2):
n = n2 / j
r = n2 - n * j
rtn.append(j * x[n] + r * (x[n + 1] - x[n]))
self.answer = Label(self, text=rtn)
self.answer.grid(row=2, column=2, sticky=W)
if __name__ == "__main__":
root = Tk()
In particular, I am trying to get it to calculate len(x) * j - 1 terms, and to work for a variety of parameter values. If you try running it you should find that you get errors for larger parameter values. For example with a list 0,1,2,3,4 and a parameter j=3 we should run through the program and get 0123456789101112. However, I get an error that the last value is 'out of range' if I try to compute it.
I believe it's an issue with my function as defined. It seems the issue with parameters has something to do with the way it ties the parameter to the n value. Consider 0123. It works great if I use 2 as my parameter (called index in the function) but fails if I use 3.
EDIT:
def psi_j(x, j):
rtn = []
for n2 in range(0, len(x) * j - 2):
n = n2 / j
r = n2 - n * j
if r == 0:
rtn.append(j * x[n])
else:
rtn.append(j * x[n] + r * (x[n + 1] - x[n]))
print 'n2 =', n2, ': n =', n, ' r =' , r, ' rtn =', rtn
return rtn
For example if we have psi_j(x,2) with x = [0,1,2,3,4] we will be able to get [0,1,2,3,4,5,6,7,8,9,10,11] with an error on 12.
The idea though is that we should be able to calculate that last term. It is the 12th term of our output sequence, and 12 = 3*4+0 => 3*x[4] + 0*(x[n+1]-x[n]). Now, there is no 5th term to calculate so that's definitely an issue but we do not need that term since the second part of the equation is zero. Is there a way to write this into the equation?
If we think about the example data [0, 1, 2, 3] and a j of 3, the problem is that we're trying to get x[4]` in the last iteration.
len(x) * j - 2 for this data is 10
range(0, 10) is 0 through 9.
Manually processing our last iteration, allows us to resolve the code to this.
n = 3 # or 9 / 3
r = 0 # or 9 - 3 * 3
rtn.append(3 * x[3] + 0 * (x[3 + 1] - x[3]))
We have code trying to reach x[3 + 1], which doesn't exist when we only have indices 0 through 3.
To fix this, we could rewrite the code like this.
n = n2 / j
r = n2 - n * j
if r == 0:
rtn.append(j * x[n])
else:
rtn.append(j * x[n] + r * (x[n + 1] - x[n]))
If r is 0, then (x[n + 1] - x[n]) is irrelevant.
Please correct me if my math is wrong on that. I can't see a case where n >= len(x) and r != 0, but if that's possible, then my solution is invalid.
Without understanding that the purpose of the function is (is it a kind of filter? or smoothing function?), I prickled it out of the GUI suff and tested it alone:
def psiFunction(j, valueList):
x = map(int, valueList)
if x[0] != 0:
x.insert(0, 0)
rtn = []
for n2 in range(0, len(x) * j - 2):
n = n2 / j
r = n2 - n * j
print "n =", n, "max_n2 =", len(x) * j - 2, "n2 =", n2, "lx =", len(x), "r =", r
val = j * x[n] + r * (x[n + 1] - x[n])
rtn.append(val)
print j * x[n], r * (x[n + 1] - x[n]), val
return rtn
if __name__ == '__main__':
print psiFunction(3, [0, 1, 2, 3, 4])
Calling this module leads to some debugging output and, at the end, the mentionned error message.
Obviously, your x[n + 1] access fails, as n is 4 there, so n + 1 is 5, one too much for accessing the x array, which has length 5 and thus indexes from 0 to 4.
EDIT: Your psi_j() gives me the same behaviour.
Let me continue guessing: Whatever we want to do, we have to ensure that n + 1 stays below len(x). So maybe a
for n2 in range(0, (len(x) - 1) * j):
would be helpful. It only produces the numbers 0..11, but I think this is the only thing which can be expected out of it: the last items only can be
3*3 + 0*(4-3)
3*3 + 1*(4-3)
3*3 + 2*(4-3)
and stop. And this is achieved with the limit I mention here.

Compound assignment operators, what happens if the value is modified (in the meanwhile)?

Consider the following pseudocode (language agnostic):
int f(reference int y) {
y++;
return 2;
}
int v = 1;
v += f(v);
When the function f changes y (that is v) while evaluating v += f(v), is the original value of v "frozen" and changes to v "lost"?
v += f(v); // Compute the address of v (l-value)
// Evaluate v (1)
// Execute f(v), which returns 2
// Store 1 + 2
printf(v); // 3
In most languages += operator (as well as any other compound assignment operator, as well as simple assignment operator) has right-to-left associativity. That means f(v) value will be evaluated first, then its result will be added to the current value of v.
So in your example it should be 4, not 3:
C++: (demo)
int f(int& v) {
v++;
return 2;
}
int main() {
int v = 1;
v += f(v);
cout << v; // 4
}
Perl: (demo)
sub f {
$_[0]++;
return 2;
}
my $v = 1;
$v += f($v);
print $v; # 4

I'm trying to do Ackermann's Function on IBasic

Ackermann's Function is a recursive mathematical algorithm that can be used to test how well a computer performs recursion. Design a function ackermann(m,n), which solves Ackermann's Function. Use the following logic in your function:
If m = 0, then return n + 1
If n = 0 then return ackermann(m-1, 1)
Otherwise, return ackermann(m-1, ackermann(m, n-1))
The program stops after it hits 13. Can anyone tell me what I have done wrong?
declare main()
declare ackermann(m:int, n:int)
openconsole
main()
print:print "Press any key to quit...",
do:until inkey$<>""
closeconsole
end
sub main()
def counter, m, n:int
counter = 0
for counter = 1 to 100
print ackermann(counter)
next counter
return
sub ackermann(m, n)
if m = 0
return = n + 1
else
if n = 0
return = ackermann(m - 1, 1)
else
return = ackermann(m - 1, ackermann(m, n - 1))
endif
endif
return
Your print statement is
print ackermann(counter)
but your function is
sub ackermann(m, n)
You need to send a second parameter in the first call.
Do note that Ackermann's function grows incredibly quickly - values above m,n > (3,4) are going to have a LOT of digits and if you go more than even about (4,4) you'll quickly find numbers that could quite possibly fill up your memory entirely with digits...
Refer to Wikipedia to see the magnitude of the numbers you are trying to compute...
declare main()
declare ackermann(m:int, n:int)
openconsole
main()
print:print "Press any key to quit...",
do:until inkey$<>""
closeconsole
end
sub main()
print Ackermann(3,5)
return
sub ackermann(m, n)
if m = 0
return = n + 1
else
if n = 0
return = ackermann(m - 1, 1)
else
return = ackermann(m - 1, ackermann(m, n - 1))
endif
endif
return