Understanding Collatz Conjecture Objective in Python - python

I'm trying to decipher the following homework question. My code is supposed to evaluate to 190 but instead evaluates to 114. So, I don't think I'm understanding the coding requirement.
The Collatz conjecture is an example of a simple computational process
whose behavior is so unpredictable that the world's best
mathematicians still don't understand it.
Consider the simple function f(n) (as defined in the Wikipedia page
above) that takes an integer n and divides it by two if n is even and
multiplies n by 3 and then adds one to the result if n is odd. The
conjecture involves studying the value of expressions of the form
f(f(f(...f(f(n))))) as the number of calls to the function f
increases. The conjecture is that, for any non-negative integer n,
repeated application of f to n yields a sequence of integers that
always includes 1.
Your task for this question is to implement the Collatz function f in
Python. The key to your implementation is to build a test that
determines whether n is even or odd by checking whether the remainder
when n is divided by 2 is either zero or one. Hint: You can compute
this remainder in Python using the remainder opertor % via the
expression n % 2. Note you will also need to use integer division //
when computing f.
Once you have implemented f, test the your implementation on the
expression f(f(f(f(f(f(f(674))))))). This expression should evaluate
to 190.
from __future__ import division
def collatz(n):
l = []
l.append(n)
while n != 1:
if n % 2 == 0:
n = n // 2
l.append(n)
else:
n = (3*n) + 1
l.append(n)
return l
print len(collatz(674))

You just misread the intermediary question. Your programs tries to answer the bigger question... This is what should return 190:
def f(n):
return n // 2 if n % 2 == 0 else 3*n + 1
print f(f(f(f(f(f(f(674)))))))

Related

Sum of 1st N natural numbers in O(no. of digits in N)

I'm trying to write a program to find sum of first N natural numbers i.e. 1 + 2 + 3 + .. + N modulo 1000000009
I know this can be done by using the formula N * (N+1) / 2 but I'm trying to find a sort of recursive function to calculate the sum.
I tried searching the web, but I didn't get any solution to this.
Actually, the problem here is that the number N can have upto 100000 digits.
So, here is what I've tried until now.
First I tried splitting the number into parts each of length 9, then convert them into integers so that I can perform arithmetic operations using the operators for integers.
For example, the number 52562372318723712 will be split into 52562372 & 318723712.
But I didn't find a way to manipulate these numbers.
Then again I tried to write a function as follows:
def find_sum(n):
# n is a string
if len(n) == 1:
# use the formula if single digit
return int(int(n[0]) * (int(n[0]) + 1) / 2)
# I'm not sure what to return here
# I'm expecting some manipulation with n[0]
# and a recursive call to the function itself
# I've also not used modulo here just for testing with smaller numbers
# I'll add it once I find a solution to this
return int(n[0]) * something + find_sum(n[1:])
I'm not able to find the something here.
Can this be solved like this?
or is there any other method to do so?
NOTE: I prefer a solution similar to the above function because I want to modify this function to meet my other requirements which I want to try myself before asking here. But if it is not possible, any other solution will also be helpful.
Please give me any hint to solve it.
Your best bet is to just use the N*(N+1)/2 formula -- but using it mod p. The only tricky part is to interpret division by 2 -- this had to be the inverse of 2 mod p. For p prime (or simply for p odd) this is very easy to compute: it is just (p+1)//2.
Thus:
def find_sum(n,p):
two_inv = (p+1)//2 #inverse of 2, mod p
return ((n%p)*((n+1)%p)*two_inv)%p
For example:
>>> find_sum(10000000,1000000009)
4550000
>>> sum(range(1,10000001))%1000000009
4550000
Note that the above function will fail if you pass an even number for p.
On Edit as #user11908059 observed, it is possible to dispense with multiplication by the modular inverse of 2. As an added benefit, this approach no longer depends on the modulus being odd:
def find_sum2(n,k):
if n % 2 == 0:
a,b = (n//2) % k, (n+1) % k
else:
a,b = n % k, ((n+1)//2) % k
return (a*b) % k

Using recursion to calculate powers of large digit numbers

The goal is to calculate large digit numbers raised to other large digit numbers, e.g., 100 digit number raised to another 100 digit number, using recursion.
My plan was to recursively calculate exp/2, where exp is the exponent, and making an additional calculation depending on if exp is even or odd.
My current code is:
def power(y, x, n):
#Base Case
if x == 0:
return 1
#If d is even
if (x%2==0):
m = power(y, x//2, n)
#Print statment only used as check
print(x, m)
return m*m
#If d is odd
else:
m = y*power(y, x//2, n)
#Print statement only used as check
print(x, m)
return m*m
The problem I run into is that it makes one too many calculations, and I'm struggling to figure out how to fix it. For example, 2^3 returns 64, 2^4 returns 256, 2^5 returns 1024 and so on. It's calculating the m*m one too many times.
Note: this is part of solving modulus of large numbers. I'm strictly testing the exponent component of my code.
First of all there is a weird thing with your implementation: you use a parameter n that you never use, but simply keep passing and you never modify.
Secondly the second recursive call is incorrect:
else:
m = y*power(y, x//2, n)
#Print statement only used as check
print(x, m)
return m*m
If you do the math, you will see that you return: (y yx//2)2=y2*(x//2+1) (mind the // instead of /) which is thus one y too much. In order to do this correctly, you should thus rewrite it as:
else:
m = power(y, x//2, n)
#Print statement only used as check
print(x, m)
return y*m*m
(so removing the y* from the m part and add it to the return statement, such that it is not squared).
Doing this will make your implementation at least semantically sound. But it will not solve the performance/memory aspect.
Your comment makes it clear that you want to do a modulo on the result, so this is probably Project Euler?
The strategy is to make use of the fact that modulo is closed under multiplication. In other words the following holds:
(a b) mod c = ((a mod c) * (b mod c)) mod c
You can use this in your program to prevent generating huge numbers and thus work with small numbers that require little computational effort to run.
Another optimization is that you can simply use the square in your argument. So a faster implementation is something like:
def power(y, x, n):
if x == 0: #base case
return 1
elif (x%2==0): #x even
return power((y*y)%n,x//2,n)%n
else: #x odd
return (y*power((y*y)%n,x//2,n))%n
If we do a small test with this function, we see that the two results are identical for small numbers (where the pow() can be processed in reasonable time/memory): (12347**2742)%1009 returns 787L and power(12347,2742,1009) 787, so they generate the same result (of course this is no proof), that both are equivalent, it's just a short test that filters out obvious mistakes.
here is my approach accornding to the c version of this problem it works with both positives and negatives exposents:
def power(a,b):
"""this function will raise a to the power b but recursivelly"""
#first of all we need to verify the input
if isinstance(a,(int,float)) and isinstance(b,int):
if a==0:
#to gain time
return 0
if b==0:
return 1
if b >0:
if (b%2==0):
#this will reduce time by 2 when number are even and it just calculate the power of one part and then multiply
if b==2:
return a*a
else:
return power(power(a,b/2),2)
else:
#the main case when the number is odd
return a * power(a, b- 1)
elif not b >0:
#this is for negatives exposents
return 1./float(power(a,-b))
else:
raise TypeError('Argument must be interfer or float')

Wieferich prime numbers

I need help with an assigment I'm working on. the task is to write a program to find all Wieferich prime numbers between two given values. The equation to determine if it is a Wieferich prime is this:
a Wieferich prime number p is such that p2 divides 2(p − 1) − 1
This is what I have so far:
start=int(input("enter start value"))
end=int(input("enter end value"))
for c in range(start,end):
if c%2!=0:
primedet=(c**2)/((2**(c-1))-1)
if primedet%1==0:
print(c," is a Wiefrich Prime")
Every time I run it, it just prints all the odd numbers between the given values. I know that there are only two Wieferich prime numbers: 1093 and 3011. I really just not sure how to make this work. Any guidance would be appreciated.
The use of modular arithmetic make this a more easy task, because you want that 2p-1 -1 be divisible by p2, that is 2p-1 -1 = 0 (mod p2) rearrange this you get 2p-1 = 1 (mod p2) in python this is
(2**(p-1)) % (p**2) == 1
but that is inefficient because first calculate 2p-1 to then take the modulo, but don't worry, python have a efficient way of doing modular exponentiation with the 3 argument call of pow
pow(2,p-1,p**2) == 1
finally you also need that p be a prime, then with implementing a primality test you are ready to go
def isPrime(n:int) -> bool:
return True #put here the code for primality check
def find_Wieferich_prime_in(star,end) -> [int]:
resul = list()
for p in range(star,end):
if isPrime(p) and pow(2,p-1,p**2)==1:
resul.append(p)
return resul
print(find_Wieferich_prime_in(0,4000))
and that is everything that you need to find the Wieferich prime
Your other mistake is in here
primedet=(c**2)/((2**(c-1))-1)
2c-1-1 is always bigger that c2 (to a sufficient large c ) so the division c2/(2c-1-1) < 1
furthermore
primedet%1
because primedet is a float, when you do float%1 it give you the decimal part of that number, mix round issues and you will get too many zeros,
but more than that, what you are testing there is something that is not the definition of a Wieferich prime.
This is very simple. Based on your statement, the numbers have the property of being prime prime and Wieferich just by the means of the equation you gave, so (2(p - 1) - 1) % p2 == 0 returns True means you found a number. As explained by #Copperfield, this can be written as (2(p-1)) % p2 == 1. Then you can do (with the help of pow which is faster):
# I assume we have `start` and `end` given by user. Now we can safely
# start from the first odd number greater or equal to start so we can
# stride by 2 in the `range` call which will half our iteration
start = start + 1 if start % 2 == 0 else start
# next I'm using filter because it's faster then the normal `for` loop
# and gives us exactly what we need, that is the list of numbers
# that pass the equation test. Note I've also included the `end`
# number. If I were to write `range(start, end, 2)` we wouldn't
# test for `end`
restult = list(filter(lambda n: pow(2, n - 1, n*n) == 1, range(start, end + 2, 2)))

Prime number generation using Fibonacci possible?

I'm generating prime numbers from Fibonacci as follows (using Python, with mpmath and sympy for arbitrary precision):
from mpmath import *
def GCD(a,b):
while a:
a, b = fmod(b, a), a
return b
def generate(x):
mp.dps = round(x, int(log10(x))*-1)
if x == GCD(x, fibonacci(x-1)):
return True
if x == GCD(x, fibonacci(x+1)):
return True
return False
for x in range(1000, 2000)
if generate(x)
print(x)
It's a rather small algorithm but seemingly generates all primes (except for 5 somehow, but that's another question). I say seemingly because a very little percentage (0.5% under 1000 and 0.16% under 10K, getting less and less) isn't prime. For instance under 1000: 323, 377 and 442 are also generated. These numbers are not prime.
Is there something off in my script? I try to account for precision by relating the .dps setting to the number being calculated. Can it really be that Fibonacci and prime numbers are seemingly so related, but then when it's get detailed they aren't? :)
For this type of problem, you may want to look at the gmpy2 library. gmpy2 provides access to the GMP multiple-precision library which includes gcd() and fib() functions which calculate the greatest common divisor and the n-th fibonacci numbers quickly, and only using integer arithmetic.
Here is your program re-written to use gmpy2.
import gmpy2
def generate(x):
if x == gmpy2.gcd(x, gmpy2.fib(x-1)):
return True
if x == gmpy2.gcd(x, gmpy2.fib(x+1)):
return True
return False
for x in range(7, 2000):
if generate(x):
print(x)
You shouldn't be using any floating-point operations. You can calculate the GCD just using the builtin % (modulo) operator.
Update
As others have commented, you are checking for Fibonacci pseudoprimes. The actual test is slightly different than your code. Let's call the number being tested n. If n is divisible by 5, then the test passes if n evenly divides fib(n). If n divided by 5 leaves a remainder of either 1 or 4, then the test passes if n evenly divides fib(n-1). If n divided by 5 leaves a remainder of either 2 or 3, then the test passes if n evenly divides fib(n+1). Your code doesn't properly distinguish between the three cases.
If n evenly divides another number, say x, it leaves a remainder of 0. This is equivalent to x % n being 0. Calculating all the digits of the n-th Fibonacci number is not required. The test just cares about the remainder. Instead of calculating the Fibonacci number to full precision, you can calculate the remainder at each step. The following code calculates just the remainder of the Fibonacci numbers. It is based on the code given by #pts in Python mpmath not arbitrary precision?
def gcd(a,b):
while b:
a, b = b, a % b
return a
def fib_mod(n, m):
if n < 0:
raise ValueError
def fib_rec(n):
if n == 0:
return 0, 1
else:
a, b = fib_rec(n >> 1)
c = a * ((b << 1) - a)
d = b * b + a * a
if n & 1:
return d % m, (c + d) % m
else:
return c % m, d % m
return fib_rec(n)[0]
def is_fib_prp(n):
if n % 5 == 0:
return not fib_mod(n, n)
elif n % 5 == 1 or n % 5 == 4:
return not fib_mod(n-1, n)
else:
return not fib_mod(n+1, n)
It's written in pure Python and is very quick.
The sequence of numbers commonly known as the Fibonacci numbers is just a special case of a general Lucas sequence L(n) = p*L(n-1) - q*L(n-2). The usual Fibonacci numbers are generated by (p,q) = (1,-1). gmpy2.is_fibonacci_prp() accepts arbitrary values for p,q. gmpy2.is_fibonacci(1,-1,n) should match the results of the is_fib_pr(n) given above.
Disclaimer: I maintain gmpy2.
This isn't really a Python problem; it's a math/algorithm problem. You may want to ask it on the Math StackExchange instead.
Also, there is no need for any non-integer arithmetic whatsoever: you're computing floor(log10(x)) which can be done easily with purely integer math. Using arbitrary-precision math will greatly slow this algorithm down and may introduce some odd numerical errors too.
Here's a simple floor_log10(x) implementation:
from __future__ import division # if using Python 2.x
def floor_log10(x):
res = 0
if x < 1:
raise ValueError
while x >= 1:
x //= 10
res += 1
return res

Can anyone perhaps teach me how to further optimize this 'print up to the nth prime number' script? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 11 years ago.
Improve this question
I'm a 17 year old getting started with programming with the help of the Python programming language.
I've been seeking to optimize this algorithm, perhaps by eliminating one of the loops, or with a better test to check for prime numbers.
Trying to calculate and display 100000 prime numbers has the script pausing for about 6 seconds as it populates the list with primes before the primes list is returned to the console as output.
I've been experimenting with using
print odd,
to simply print every found prime number, which is faster for smaller inputs like n = 1000, but for n = 1000000 the list itself prints much faster (both in the python shell and in the console).
Perhaps the entire code/algorithm should be revamped, but the script should remain essentially the same: The user types in the number of prime numbers to be printed (n) and the script returns all prime numbers up to the nth prime number.
from time import time
odd = 1
primes = [2]
n = input("Number of prime numbers to print: ")
clock = time()
def isPrime(number):
global primes
for i in primes:
if i*i > number:
return True
if number%i is 0:
return False
while len(primes) < n:
odd += 2
if isPrime(odd):
primes += [odd]
print primes
clock -= time()
print "\n", -clock
raw_input()
I might wanna rewrite the whole script to use a sieve like the Sieve of Atkin: http://en.wikipedia.org/wiki/Sieve_of_Atkin
However, I am simply a beginner at Python (or even at programming: I started writing code only 2 weeks ago) and it would be quite a challenge for me to figure out how to code a Sieve of Atkin algorithm in Python.
I wish a google hacker out there would hand hold me through stuff like this :(
You could use prime sieve, and with a simple twist:
Define the first prime 2 as you do, set the largest number reached (max) to 2;
Generate a list of n consecutive numbers from max+1 to max+n;
Use sieve with the primes on this list. When sieving, set the beginning number for each prime to the smallest number in the list that could be divided by the prime;
If the amount is not reacher, goto 2.
This way, you could control the length of the list, and as the length grows larger, the speed will be faster. However, this is a total rework of the algorithm, and is harder to program.
Here's a sample code, which is quite crude, but this only takes less than 70% time of the original:
from math import sqrt
from time import time
primes = [2]
max = 3
n = input("Number of prime numbers to print: ")
r=2
clock = time()
def sieve(r):
global primes
global max
s = set(range(max,max+r))
for i in primes:
b=max//i
if (b*i<max):
b=b+1
b=b*i
while b<=max+r-1:
if b in s:
s.remove(b)
b=b+i
for i in s:
primes.append(i)
while len(primes) < n:
r=primes[-1]
sieve(r)
max=max+r
primes=primes[0:n]
print primes
clock -= time()
print "\n", -clock
raw_input()
There are many ways to improve this, this just shows the notion of the approach.
Also, this can blow up the memory when the number is large. I used the dynamic limit try to somewhat relieve this.
And if you are really curious (and fearless), you could look at the more complicated implementations in various open source projects. One example is Pari/GP, which is written in C++, and is blazing fast (I tested 1 to 50000000 in less than 1 min, if I remember correctly). Translating them to Python may be hard, but will be helpful, perhaps not just for yourself;-)
One simple optimizations which could be applied without hacking the code completely.
the i*i on every prime gets very wasteful as the list gets longer. Instead calculate the square root of i outside the loop and test against this value inside the loop.
However square root is itself and expensive calculation and the majority of candidate numbers will be rejected as divisible by one of the lower primes (3,5,7) so this turns out to be not such a good optimization (pessimization?). But we don't actually need to be that precise and a simple check that the prime is less than one third of the value has a similar effect without the computational cost of the square root calculation, but, at the expense of a relatively few unnecessary test.
As was already said by Ziyao Wei I'd also try a Sieve implementation. The only thing I'd improve is to use the Prime number theorem as a starting point for the used size.
Computing the inverse function isn't straightforward in pure python, but an iterative approach should be good enough and that way you could get a pretty good idea how large the sieve would have to be. Since I don't really remember the proofs for the theorem in detail and it's 6am in the morning here, someone else will have to chip in to say if the theorem guarantees any certain upper boundary that could be used to allow using the simple sieve without having to worry about growing it. iirc that's sadly not the case.
As already mentioned, the presented algorithm cannot be improved significantly. If a fast solution is requested then the Eratosthenes sieve is appropriate. The size x of the sieve can be estimated using n >= x/(ln x + 2) if x >= 55. This equation can be solved using the Newton's iteration. The presented algorithm is about 10 times faster the original:
def sieveSize(n):
# computes x such that pi(x) >= n (assumes x >= 55)
x = 1.5 * n # start
y = x - n * math.log(x) - 2 * n
while abs(y) > 0.1:
derivative = 1 - n/x
x = x - y / derivative
y = x - n * math.log(x) - 2 * n
return int(x) + 1
def eratosthenes(n):
# create a string flags: flags[i]=='1' iff i prime
size = sieveSize(n)
flags = ['1'] * size # start with: all numbers are prime
flags[0] = flags[1] = '0' # 0 and 1 are not primes
i = 0
while i * i < size:
if flags[i] == '1':
for j in range(i * i, size, i):
flags[j] = '0'
i += 1
return flags
def primes(n):
flags = eratosthenes(n)
prims = []
for i in range(0, len(flags)):
if flags[i] == '1':
prims.append(i)
return prims
prims = primes(100000)
Any number that ends in 5, other than 5, is not a prime. So you can put a statement that skips any number ending in 5 that is greater than 5.

Categories

Resources