How can I reimplement this recursive function? - python

So I'm trying to solve a puzzle and I came across this code. I can't figure out what the output would be and any attempts to run it result in a "reached the maximum amount of recursion" error. Sorry in advance for the goofy variable names.
How can I modify this to achieve the same output, without the recursion error? The initial numbers I'm passing are 13379446(arg 1) and 5(arg 2).
import sys
num1 = int(sys.argv[1])
num2 = int(sys.argv[2])
def doot(num1, num2):
print num1
print num2
doritos = 0
if num2 > num1:
pass
else:
if num2 == 0:
print "if"
doritos = 1
else:
if num2 == num1:
doritos = 1
else:
wew = doot(num1 - 1, num2 - 1)
doritos = wew
wew = doot(num1 -1, num2)
doritos = doritos + wew
print doritos

Let me get you started. I'm assuming that doritos is supposed to be the return value, that is, that the code should say return dortitos instead of print doritos. Also, I'm completely ignoring the line print if.
Now what do we know? Looking at the code we see that
doot(x,y) = 0 if y > x
doot(x,0) = 1
doot(x,x) = 1 and
doot(x,y) = doot(x-1,y-1) + doot(x-1,y) otherwise
So we want to figure out the value of doot(x+h,x) where h > 0. Start with the simplest case, h=1. We already know that doot(1,0)=1, so
doot(2,1) = doot(1,0)+doot(1,1) = 1+1 = 2
doot(3,2) = doot(2,1)+doot(2,2) = 2+1 = 3
and now it's easy to guess that
doot(x+1,x)=x+1 for all x>= 0.
t's also easy to prove this by induction, if you're so inclined.
So now, work out some examples when h=2, and figure out the formula for doot(x+2,x). Then figure out the formula for doot(x+3,x) and so on, until you're ready to guess the the formula for doot(x+h,x)

Okay, I overhauled your code to use a dictionary (values) and a queue.
import sys
num1 = int(raw_input("num1: "))
num2 = int(raw_input("num2: "))
def doot(num1, num2):
print num1
print num2
doritos = 0
n1 = num1
n2 = num2
values = {}
queue = [(num1,num2)]
while queue:
num1,num2 = queue.pop()
#print queue
#print values
if (num1,num2) not in values:
if num1 >= num2:
if num2 == 0:
#print "if"
#doritos = 1
values[(num1,num2)] = 1
else:
if num2 == num1:
#doritos = 1
values[(num1,num2)] = 1
else:
#wew = doot(num1 - 1, num2 - 1)
#doritos = wew
#wew = doot(num1 -1, num2)
#doritos = doritos + wew
if (num1-1,num2-1) in values and (num1-1,num2) in values:
values[(num1,num2)] = values[(num1-1,num2-1)] + values[(num1-1,num2)]
else:
queue.append((num1,num2))
if (num1-1,num2) not in values:
queue.append((num1-1,num2))
if (num1-1,num2-1) not in values:
queue.append((num1-1,num2-1))
#print values
doritos = values[(n1,n2)]
print doritos
return doritos
doot(num1,num2)
In essence, I use the queue to keep track of the sums I don't have yet. If both of the descendants of (num1,num2) are in the dictionary, then I put it in the dictionary with the sum of their values. Otherwise, I put either or both descendant that's not in the dictionary on the queue along with itself. The other times that I don't put (num1,num2) back on the queue are when num1 == num2 or num2 == 0, in which cases I put them in the dictionary with value 1. At the end, I return the value in the dictionary that corresponds to the original inputted numbers.
Now, a word of caution: this code is horribly inefficient. I just had to reboot my computer because I tried the inputs you gave in the question, and it gobbled up all of the available RAM. So, you should instead consider what exactly is being done with the recursion, and figure out how to work forwards from the base cases instead of backwards from the input. That task, I will leave to you.

Your code is a recursive implementation of a combination function, which calculates the number of combinations of k distinct elements that can be drawn from a set of n elements.
A tidied up version of your function would look like this (note I have removed all the print statements and ensured that the function returns something - otherwise it won't work at all).
def doot(n, k):
if n < k:
return 0
if k == 0 or n == k:
return 1
return doot(n - 1, k - 1) + doot(n - 1, k)
This works fine for small values of n and k. A faster version that doesn't rely on recursion uses factorials, as shown in this answer.
import math
def nCr(n, r):
f = math.factorial
return f(n) / f(r) / f(n - r)
However, calculating the factorial of 13379446 still takes a long time and may not be accurate because the result is so huge. My system hangs when I try it. The other answer to the same question appears to work better.

Related

Dividing multiple numbers in a for loop

Trying to divide multiple numbers in a for loop, output is incorrect answer
Created a variable for the answer, in each for loop it will make answer equal to the previous loops answer divided by the integer from the for loops list.
def div(x):
ans = 0
for i in x:
ans = ans / int(i)
b = int(input("How many numbers would you like to " + opt + "?"))
c = range(0,b)
d = list()
for i in c:
d.append(input("What number would you like to " + opt + "?"))
print(div(d))
If 3 numbers are input to the list (d). I want to divide these 3 numbers and make the variable (ans) equal to the quotient
Example:
Input 3 numbers - 200, 10, 2
Result: 10
Actual Results from script: 0.0
You have two problems:
First, our function does not return a value. You can fix this by adding return ans at the end of the function.
Second, if you start with ans = 0, dividing ans will only get you more zeros.
Here's one solutions, using a placeholder to skip over the solution:
def div(x):
ans = None
for i in x:
if ans is None:
ans = i
else:
ans = ans / int(i)
return ans
Here's a slightly more elegant alternative, using an arbitrary argument list.
def div(init, *divisors):
ans = init
for x in divisors:
ans /= x # divide and assign together
return ans
div(100, 10, 2) # returns 5
div(*[100, 10, 2]) # returns 5
By declaring a function parameter with *, any extra parameters given will be packed into it as a list. You can then pass arguments to it without putting them in a list, or you can use another * to unpack the list into multiple arguments.
The div function doesn't actually return anything, so it should be printing None ?
this should fix your problem:
def div(x):
ans = 0
for i in x:
ans = ans / i
return ans

How can I make a simple calculator in python 3?

I'm making this calculator using python 3, and this is what I have so far:
print("Welcome to Calculator!")
class Calculator:
def addition(self,x,y):
added = x + y
return added
def subtraction(self,x,y):
subtracted = x - y
return subtracted
def multiplication(self,x,y):
multiplied = x * y
return multiplied
def division(self,x,y):
divided = x / y
return divided
calculator = Calculator()
print("1 \tAddition")
print("2 \tSubtraction")
print("3 \tMultiplication")
print("4 \tDivision")
operations = int(input("What operation would you like to use?: "))
x = int(input("How many numbers would you like to use?: "))
if operations == 1:
a = 0
sum = 0
while a < x:
number = int(input("Please enter number here: "))
a += 1
sum = calculator.addition(number,sum)
print("The answer is", sum)
if operations == 2:
s = 0
diff = 0
while s < x:
number = int(input("Please enter number here: "))
s += 1
diff = calculator.subtraction(number,diff)
print("The answer is", diff)
if operations == 3:
m = 0
prod = 1
while m < x:
number = int(input("Please enter number here: "))
m += 1
prod = calculator.multiplication(number, prod)
print("The answer is", prod)
if operations == 4:
d = 0
quo = 1
while d < x:
number = int(input("Please enter number here: "))
d += 1
quo = calculator.division(number, quo)
print("The answer is", quo)
Addition and multiplication works just fine, subtraction and division are the problems here. One example for subtraction is if I tried using two numbers, 9 and 3, I would get -6... That is definitely incorrect. As for division, if I tried dividing two numbers, 10 and 2, I would get 0.2, which is also wrong. For division I've tried switching number and quo, and with the same problem (10 / 2), I would get 0.05... Also, I don't want to use any of the built-in functions for python, so just help me fix these errors the easiest way possible.
Your algorithm is wrong for subtraction and division. Let's look at subtraction:
s = 0
diff = 0
while s < x:
number = int(input("Please enter number here: "))
s += 1
diff = calculator.subtraction(number,diff)
Step through this in your head. If you're operating on two numbers (9 and 3), you will get diff = 9 - 0 = 9 on the first iteration and diff = 3 - 9 = (-6) on the next. That won't work.
Subtraction is addition if all the terms (but the first) are negated. If you think about it like that it's fairly simple:
terms = []
for _ in range(x): # this is a more idiomatic way to iterate `x` times
number = int(input("Please enter number here: "))
terms.append(number)
head, tail = terms[0], terms[1:]
result = head
for term in tail:
result -= tail
return result
You can certainly condense this further
terms = [int(input("Please enter number here: ")) for _ in range(x)]
terms[1:] = [x * (-1) for x in terms[1:]]
return sum(terms)
Similarly with division, step through in your head:
d = 0
quo = 1
while d < x:
number = int(input("Please enter number here: "))
d += 1
quo = calculator.division(number, quo)
print("The answer is", quo)
With 10 and 2, you get first quo = 10 / 1 = 10 then quo = 2 / 10 = 0.2. Like we can generalize subtraction to be tail-negated addition, we can generalize division to be tail-inverted multiplication.
24 / 2 / 3 / 4 == 24 * (1/2) * (1/3) * (1/4)
And we can write the algorithm similarly.
terms = [int(input("Please enter number here: ")) for _ in range(x)]
head, tail = terms[0], terms[1:]
result = head
for term in tail:
result /= term
Note that all of these can also be written with functools.reduce and one of the operator functions
terms = [int(input("Number please! ")) for _ in range(int(input("How many numbers? ")))]
sum_ = functools.reduce(operator.add, terms)
diff = functools.reduce(operator.sub, terms)
prod = functools.reduce(operator.mul, terms)
diff = functools.reduce(operator.truediv, terms)
Consider the subtraction option (with the test input you supplied in the question):
We say we give 2 numbers.
For the first number we give 9. So diff = number - diff = 9 - 0 = 0.
Now we enter the next number, 3, therefore diff = number - diff = 0 - 3 = -3, now if it were to work correctly, we need to switch around calculation of diff, so it should be diff = diff - number, and now if we run it it will give us -12, which is the technically the correct answer, as we are asking -9-3 = -12, now I'm assuming you actually want to find 9-3 = 6, the only "simple" fix to this, is to set diff as the first number, in this case 9, and then doing what I said above (giving the expected 9 - 3 = 6) The reason the division function does not work is the same as subtraction, and you can use similar logic as above to fix it.
In addition to this, making an addition, subtraction, multiplication and division method defeats the point of methods, that is to prevent using the same code several times, and having to write less, but in this case, running calculator.addition(a, b) is longer and less flexible than simply using a + b
Also python has an in-built calculator function, called eval, which will take a string and run it as python code, meaning it supports BIDMAS, several operators, mathematical functions (assuming you have imported them), etc.

Infinite while loop in Python (finding prime number and GCD)

I am currently trapped by a infinite loop in my program and I really don't know what is the fault in it.
Here is my code:
from reference import brute_prime, euclid_gcd, extended_euclid
def rsa(min_p, min_q, min_e):
p = brute_prime(min_p)
q = brute_prime(min_q)
n = p * q
phi = (p - 1) * (q - 1)
e_prime = brute_prime(min_e)
while euclid_gcd(e_prime, phi) != 1:
e_prime = brute_prime(min_e)
print(e_prime)
e_prime += 1
return e_prime
#d = extended_euclid(e_prime, phi)
#tup1 = (d, e_prime, n)
#return tup1
My aim here is to use brute_prime and euclid_gcd to find e, by iteratively finding the next smallest prime number e_prime using brute_prime, and testing whether gcd(e′,ϕ)=1. If successful, terminate, if not, increment e_prime and continue.
Note that these functions that I called are all imported and there is nothing wrong in the function. What is wrong?
EDIT:
When trying to see the result of each iteration I tried something like this
print(rsa(11, 13, 3))
And the loop gives me 3 every single time.
EDIT:
This is brute_prime
def brute_prime(number):
#Making sure that the input from number will be type int
#setting two convenient limits for future use in the loop
number = int(number)
point_begin = 2
point_end = int((number**0.5)) + 1
#Two specific exceptions in the function that will execute and ignores
#later commands so that it is a tiny bit more efficient...
if number == 2:
return 2
elif number == 1:
return 1
while True:
condition = True
for i in range(point_begin, point_end):
if number % i == 0:
condition = False
break
if condition:
return number
else:
number += 1
EDIT:
This is Euclid_gcd
def euclid_gcd(num1, num2):
while num2:
num1, num2 = num2, num1 % num2
return int(num1)
Your while loop in RSA function looks buggy as min_e is not being updated, so same value is used in each iteration thus the loop is stuck, check your logic.
or use this:
while euclid_gcd(e_prime, phi) != 1:
e_prime = brute_prime(min_e)
min_e = e_prime + 1 # check for next prime-number co-prime to phi
Also note, 1 is not prime. For 1 as input, brute_prime should return 2.
Perhaps unrelated, but why not do something like
e_prime = brute_prime(min_e)
#This loop will not calculate and return me e_prime.
#Instead it just keeps running and exits later with nothing.
while euclid_gcd(e_prime, phi) != 1:
e_prime = brute_prime(min_e)
e_prime += 1
return e_prime

Get sum of numbers using a Function and For Loop

I want to define a function, sumAll(n) that sums all numbers from 1 to n.
For example, when I call sumAll(10) should return the answer 55...
Because:
1+2+3+4+5+6+7+8+9+10 = 55
The function sumAll needs to use a for loop to carry out this summation, and it will have to use a sum variable that increases in value over each iteration of the for loop.
I have a working function that does not use a for loop, but I need to know how to use a for loop to accomplish this as well.
Here is the working program:
def sumAll(n):
if n == 0:
return 0
return n + sumAll(n - 1)
number = int(raw_input("Please enter a number: \n"))
print ("The answer is: ") + str(sumAll(number))
How do I use a "for" loop to accomplish this?
Am I right in assuming the "for loop" should be nested in the "sumAll" function?
I have tried many times to do this using a for loop and I keep getting a infinite result and errors...
Here is my code:
def sumAll(n):
y = n + sumAll(n -1)
return y
num = int(raw_input("Please enter a number")
for n in range(num):
num = sumAll(num)
print num
By for loop
def sumAll(n):
sum_all = 0
for i in range(1, n+1):
sum_all = sum_all + i
return sum_all
number = int(raw_input("Please enter a number: \n"))
print ("The answer is: ") + str(sumAll(number))
Output:
Please enter a number:
10
The answer is: 55
You can also use list Comprehension:
print sum([i for i in range(number+1)])
Output:
55
You can also use a mathematical series formula:
def sumAll(n):
return n * (n + 1) / 2
you can even do it without a loop:
def sumAll(n):
return sum(range(1,n+1))
print(sumAll(10)) # -> 55
if you insist on using a loop:
def sumAll(n):
s = 0
for i in range(1,n+1):
s += i
return s
but the mathematical solution is simply:
def sumAll(n):
return n * (n + 1) / 2
# in python 3:
# return n * (n + 1) // 2
(there are n elements with an average value of (n+1)/2; this will always be an integer since either n or n+1 is even; the proof by induction is often the first example when math students learn about induction...).
You will get an error with sum(1, 2, 3, 4)
TypeError: sum expected at most 2 arguments, got 4
sum((1, 2, 3, 4)) # works cuz tuple inside
sum([1, 2, 3, 4]) # works cuz list inside
so the func will need to gather elements into a tuple, e.g.
numbers = 1, 2, 3, 4
print(sum(numbers)) # already a tuple so works
use * with your parameter to gather the caller's args into a tuple.
* enabbles any-number of args to be supplied by caller and they are converted into a tuple parameter.
def sumall(*args):
return sum(args)
print(sumall(1))
print(sumall(1, 2))
print(sumall(1, 2, 3))
print(sumall(1, 2, 3, 4))
produces the expected answers. Credit: author Downey asks for this exercises solution in chapter 12 of Think Python (2016)

python lists append

I was about to code a program which evaluates a polynomial. But the code below is just a try-out for that. The code below gives an output that stops when "counter = t"... I want it to give an output up to when counter=0. How can that be? I wanted to treat every number(input) as a coefficient of the polynomial. If I was successful doing this, I'm planning to make a list then for every, say, element in the list, I will then multiply it to a certain number raised to its index then add them up so that I've evaluated a polynomial.. Am I clear? And will my plan work out?? Thank you so much.. Please help..
t = input("Enter degree of Polynomial: ")
while t < 0:
print ("Not possible! ")
t = input("Enter degree of Polynomial: ")
counter = 0
while counter < t:
x = input("n: ")
if x <= 0:
print "Not possible!"
else:
print x**t
t-=1
counter += 1
THe ouput goes like this:
Enter degree of polynomial: 5
n: 5
3125
n:4
256
n:3
27
then it ends.. it should continue asking for an input n up to five times..
Try to use raw_input() and keep in mind that raw_input() returns always a string. So you have to convert the returned string to an integer like:
>>> x = int(raw_input("foo: "))
Then it is possible to test something like x > 2 etc. Without casting to integers the following would happen:
>>> "2" > 1
True
>>> "2" > 3
True
First of all: Well done - it's only a little mistake: Remove the "syntactic whitespace" in your last line, or remove it completly
Secondly: Don't forget to add the values ;-) - and with regards to your headline, this is best done with a python list.
The problem seems (to me) that you are having the loop depend on 2 variables, where you perhaps expected it to be only dependent on 1.
Perhaps this works a little better:
while t > 0:
x = input("n: ")
if x <= 0:
print "Not possible!"
else:
print x**t
t-=1
Something like this?
while True:
degree = int(raw_input("Enter degree of Polynomial: "))
if degree >= 0:
break
print ("Not possible!")
x = float(raw_input("x = "))
y = 0.0
for exponent in reversed(range(degree)):
k = float(raw_input("k[{0}] = ".format(exponent)))
y += k * (x ** exponent)
print("y = ", y)
This solves a polynomial of the form:
y = (k[N-1] * (x ^ N-1) + (k[N-2] * (x ^ N-2) + ... + k[0]

Categories

Resources