I came across a brain teaser problem. Im trying to simulate it, but having trouble getting the answer. The problem goes like this: there is one amoeba. every minute, an amoeba either may die, stay the same, split into 2 or split into 3 with equal probability. All of its offspring will behave the same way, independent of other amoebas. What is the probability that amoeba population will die?
My implementation in python:
import numpy as np
def simulate(n):
prob = np.array([0.25]*4)
ans = np.random.choice(np.arange(4),1,p=prob)
if ans == 0:
n = n - 1
if ans == 1:
pass
if ans == 2:
n = n * 2
if ans == 3:
n = n*3
return n
count = 0
for i in range(10000):
nold = 1
while True:
nnew = simulate(nold)
if nnew == 0: #amoeba has died
count += 1
break;
nold = nnew
Im getting an infinite loop. Can anybody help? thanks. The answer is 41%
The While loop needs to have some sort of breakpoint.
You have not set what is False.
while count < 10000:
...
Related
I need to understand the complexity of the following code. I am familiar with the concepts of all the Big O() notation and also have read a lot of blogs but I cant figure how to apply to big programs.
Following is the code for largest pallindrome number from 100 to 999:
def isPaindrome(number):
stringNum = str(number)
firstDigit_index,lastDigit_index=0,len(stringNum)-1
isPalindrome = False
while(lastDigit_index > 0 and firstDigit_index < lastDigit_index):
#print(stringNum[f],"==",stringNum[l],"......")
if(stringNum[firstDigit_index]==stringNum[lastDigit_index]):
isPalindrome = True
else:
isPalindrome = False
break
firstDigit_index = firstDigit_index + 1
lastDigit_index = lastDigit_index - 1
if(isPalindrome):
return number
else:
return 0
max = 0
startRange = 100
endRange = 999
for i in range(endRange*endRange,startRange*startRange,-1):
factors = []
result = isPaindrome(i)
if(result!=0):
for i in range(startRange,endRange+1):
if(result%i==0):
factors.append(i)
if(len(factors)>1):
sumFactor = factors[(len(factors))-1] + factors[(len(factors))-2]
mul = factors[(len(factors))-1] * factors[(len(factors))-2]
if(sumFactor>max and mul==result):
max = sumFactor
print("Largest Palindrome made from product of two 3 digit numbers(",factors[(len(factors))-1],",",factors[(len(factors))-2] ,") is", result,".")
If anyone could just make me understant step by step how to calculate I'd be grateful.
As I mentioned, your isPalindrome function is literally incorrect, as you're not changing the indexes. I changed a bit of your also, so this is the version I'm analysing. (I'm only analysing the isPalindrome function, since I actually couldn't understand what the main function is doing), sorry!
def isPalindrome(n):
num = str(n)
head, tail = 0, len(num) - 1
while tail > head:
if num[head] != num[tail]: # Not symmetrical!! WARNING!
return False
head += 1 # move position
tail -= 1 # move position
return True
This code on average is O(|n|) i.e. O(log N) where N is the number. This is because on average, the if comparison has 50% chance of breaking (returning False) and 50% of continuing. Therefore the expected number of comparisons would be |n|/4 which is O(|n|).
I had to create a program for a staircase problem where i had to design staircase with n number of bricks. The complexity is that the number of bricks in every step must be unique, and less than the previous step.
for example, using 6 bricks, i can make a staircase with step height (5,1) , (4,2) and (3,2,1) but not (3,3) or (1,2,3) or (2,4) or any other permutation.
I have designed the code but the problem is that it runs fine till n as nearly 100 or 120, but freezes if the inputs are larger than these values. I am a beginner in Python programming and learning concepts on the go.
I tried memoization, but to no avail. I need to know if there is something else i can do to make my code more optimized to run over n as 200-250?
import cProfile
def solution(n):
memory = {0: [], 1: [1], 2: [2]}
def rec(max_val, i):
t = []
r = []
for j in range(1,i):
y = i - j
if y < max_val:
if y > j:
t = [y, j]
r.append(t)
if n / 2 >= j >= 3 and j in memory:
mem = memory[j]
[r.append([y, item]) for item in mem]
else:
if y >= 3 and n / 2 >= j >= 3 and j in memory:
mem = memory[j]
for item in mem:
if y > item[0]:
r.append([y, item])
else:
v = rec(y, j)
if v:
for item in v:
t = [y, item]
r.append(t)
if r:
if i in memory:
if len(memory[i]) < len(r):
memory[i] = r
else:
memory[i] = r
return r
def main_func(n):
stair = []
max_val = 201
total = 0
for i in range (1,n):
x = n - i
if x > i:
s = [x, i]
total += 1
if i >= 3:
u = rec(max_val, i)
total += len(u)
elif x == i and i >= 3:
u = rec(max_val, i)
total += len(u)
elif x < i and i >= 3:
u = rec(x, i)
total += len(u)
return total
stairs = main_func(n)
return (stairs)
print(solution(100))
You can approach the problem recursively from the perspective of the base of the stairs. The strategy is to add up the pattern counts of the next step levels for each base size.
For example, with 6 bricks, the first call would go through base sizes n = 5,4,3,2 and make a recursive calls to know how many combinations are possible for the next step levels using the remaining bricks and with a maximum base of n-1. The sum of next levels counts will constitute the total count of possible stair patterns.
At the top of the stairs, you need at least 3 bricks to add more than one level so you can stop the recursion with a count of 1 when there are fewer than 3 bricks left. This will roll up the recursive calls to form larger totals and produce the right answer once the original call completes.
In order to optimize this process, you can use memoization and you can also short circuit the calculation using the base size provided at each recursion.
For a given base, the largest number of bricks that can be used will be the sum of numbers from 1 to that base. This can be computed using Gauss's formula: base*(base+1)/2. If you have more bricks than the maximum brick count for the base, then you can stop the recursion and return a count of zero (since you have too many remaining bricks and will not be able to fit them all over the previous level's base)
Another way to optimize the calculation is to loop through the base sizes in decreasing order. This will allow you to stop the loop as soon as you get a count of zero for the next levels, which means that there are too many remaining bricks for that base size (or any smaller base size)
Here's an example (using lru_cache for memoization):
from functools import lru_cache
#lru_cache(None)
def stairCount(N,base=None):
base = min(base or N-1,N)
if N > base*(base+1)//2: return 0
if N < 3: return 1
count = 0
while True:
nextLevels = stairCount(N-base,base-1)
if nextLevels == 0: break
count += nextLevels
base = base - 1
return count
With these optimizations, the function will respond in less than a second for up to 600 bricks (depending on the speed of your computer).
With Python's list comprehensions, you could write this function more concisely (though it would lose the decreasing base order optimization ≈ 10%):
#lru_cache(None)
def stairCount(N,base=None):
base = min(base or N-1,N)
if N > base*(base+1)//2: return 0
if N < 3: return 1
return sum(stairCount(N-b,b-1) for b in range(2,base+1))
EDIT Here's a version with a "manual" memoization (i.e. without using functools):
def stairCount(N,base=None,memo=dict()):
memoKey = (N,base)
if memoKey in memo: return memo[memoKey]
base = min(base or N-1,N)
if N > base*(base+1)//2: return 0
if N < 3: return 1
count = 0
while True:
nextLevels = stairCount(N-base,base-1,memo)
if nextLevels == 0: break
count += nextLevels
base = base - 1
memo[memoKey] = count
return count
Problem statement:
Let p(n) represent the number of different ways in which n coins can be separated into piles. For example, five coins can be separated into piles in exactly seven different ways, so p(5)=7
Find the least value of n for which p(n) is divisible by one million.
So that's a code i got using recursion to solve this problem. I know that's not the optimal aproach, but should give me the right answer... But for some reason I don't understand it gives me back that n = 2301 has a p(n) = 17022871133751703055227888846952967314604032000000, which is divisible by 1,000,000 and is the least n to do that. So why this is not the correct answer?
I checked the for n<20 and it matches. So what's wrong with my code?
import numpy as np
import sys
sys.setrecursionlimit(3000)
table = np.zeros((10000,10000))
def partition(sum, largestNumber):
if (largestNumber == 0):
return 0
if (sum == 0):
return 1
if (sum < 0):
return 0
if (table[sum,largestNumber] != 0):
return table[sum,largestNumber]
table[sum,largestNumber] = partition(sum,largestNumber-1) + partition(sum-largestNumber,largestNumber)
return table[sum,largestNumber]
def main():
result = 0
sum = 0
largestNumber = 0
while (result == 0 or result%1000000 != 0):
sum += 1
largestNumber += 1
result = int(partition(sum,largestNumber))
print("n = {}, resultado = {}".format(sum,result))
return 0
if __name__ == '__main__':
main()
I believe the NumPy data type used in your np.zeroes declaration is a restricted rather than unlimited number. The number of partitions of 2301 is in fact 17022871133751761754598643267756804218108498650480 and not 17022871133751703055227888846952967314604032000000, which you can see if you run your (correct) program with a regular table declaration like
table = [10000 * [0] for i in xrange(10000)]
and then call on the table appropriately.
I'm doing the Project Euler problem 78
Let p(n) represent the number of different ways in which n coins can be separated into piles. For example, five coins can be separated into piles in exactly seven different ways, so p(5)=7
Find the least value of n for which p(n) is divisible by one million.
I'm trying to solve this problem using recursion. I know is not the optimal solution neither the fastest one, but I want to make this work if possible. Around n = 6000 it gives me:
MemoryError: Stack overflow
And that is not the only problem. I checked online and the solution is around 53,000. My matrix goes only to 10,000x10,000. If i go to 60,000x60,000 it return a MemoryError.
Here is my code:
import sys
from time import process_time as timeit
sys.setrecursionlimit(100000)
table = [10000 * [0] for i in range(10000)]
def partition(sum, largestNumber):
if (largestNumber == 0):
return 0
if (sum == 0):
return 1
if (sum < 0):
return 0
if (table[sum][largestNumber] != 0):
return table[sum][largestNumber]
table[sum][largestNumber] = partition(sum,largestNumber-1) + partition(sum-largestNumber,largestNumber)
return table[sum][largestNumber]
def main():
result = 0
sum = 0
largestNumber = 0
while (result == 0 or result%100000 != 0):
sum += 1
largestNumber += 1
result = int(partition(sum,largestNumber))
if sum%1000 == 0:
print('{} {}'.format(sum,timeit()))
print("n = {}, resultado = {}".format(sum,result))
print('Tempo = {}'.format(timeit()))
if __name__ == '__main__':
main()
I recently started messing around with python and I wrote a program to print out the 1000th prime number but the output only shows a blinking cursor , the code is shown below:
number = 3
count= 1
while count <= 1000:
prime = True
for x in range(2, number):
if number % x == 0:
prime= False
if prime == True:
count = count + 1
if count <= 1000:
number = number + 1
print number
Any help and concise explanation would be appreciated
edit: i just realized the problem. #tichodroma solved the problem but did so by editing the OP post. so when i got to it it was already solved, how ever, he solved it by putting the print into the loop, hence the many numbers waterfall. but it should be outside the loop so as to only show the final result. also - after looking at the OP code before edit, it was written in such a way that it was taking a long time to run, and the "blinking line" was the system working in the background
def isprime(n):
'''check if integer n is a prime'''
# make sure n is a positive integer
n = abs(int(n))
# 0 and 1 are not primes
if n < 2:
return False
# 2 is the only even prime number
if n == 2:
return True
# all other even numbers are not primes
if not n & 1:
return False
# range starts with 3 and only needs to go up the squareroot of n
# for all odd numbers
for x in range(3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True
counter = 0
number = 0
while True:
if isprime(number):
counter+=1
if counter == 10000:
break
number+=1
print number