Python Second Level Parameter not Passing into Third Level - python

I am completing a project for school and am wondering what I did wrong in this code.
In Python, parameters passed through more nested functions should be able to be referenced, but the n parameter is not able to be compared to 0 in myFunc2, the error "local variable referenced before assignment." The doctests included show that, for example, it should run cycle(f1, f2, f3) with add1, times2, and add3 (which work just fine), run myFunc(n) with 0 passed as n, and myFunc2(x) with 5 passed as x. (Also works fine) I'm just curious why the n parameter doesn't seem to be coming through?
I was able to find a work around where I just make a global variable and use it in place of n and that solved the issue, but my goal is to understand where I went wrong.
def cycle(f1, f2, f3):
def myFunc(n):
def myFunc2(x):
while n > 0:
if n > 0:
x = f1(x)
n -= 1
if n > 0:
x = f2(x)
n -= 1
if n > 0:
x = f3(x)
n -= 1
return x
return myFunc2
return myFunc
>>> def add1(x):
... return x + 1
>>> def times2(x):
... return x * 2
>>> def add3(x):
... return x + 3
>>> my_cycle = cycle(add1, times2, add3)
>>> identity = my_cycle(0)
>>> identity(5)
5
>>> add_one_then_double = my_cycle(2)
>>> add_one_then_double(1)
4
>>> do_all_functions = my_cycle(3)
>>> do_all_functions(2)
9
>>> do_more_than_a_cycle = my_cycle(4)
>>> do_more_than_a_cycle(2)
10
>>> do_two_cycles = my_cycle(6)
>>> do_two_cycles(1)
19

Related

Incorporating a second parameter into recursion function and printing result

I'm trying to write a function to print a sequence of count steps recursively. The function prints count steps of the double plus 5 sequence from the start value.
I was able to figure out the general recursion for just the start parameter alone, but I cannot figure out how to include my second parameter count, for how many times the function should run, and how to have it print the result inside the function itself. (I have it printing outside currently)
Here is my current code:
def sequence_rec(start):
if start == 1:
return 1
else:
return sequence_rec(start-1)*2 + 5
for start in range(1, 10):print(sequence_rec(start))
I want the function to use two parameters instead of just the one I currently have:
def sequence_rec(start, count):
if start == 1:
return 1
else:
return sequence_rec(start-1)*2 + 5
I want the output to look something like this:
>sequence_rec(1, 2)
1 7 19
Current recursion work:
def sequence_rec(start, count):
if count == 0:
return
else:
value = sequence_rec(start * 2 + 5, count - 1)
print(value)
sequence_rec(1, 3)
One option would be to wrap your recursive function in an iterative function that does the printing you want:
>>> def print_sequence(n):
... for i in range(1, n+2):
... print(sequence_rec(i))
...
>>> print_sequence(2)
1
7
19
>>>
In general it's good practice to have each function do one simple thing; this makes it easy to reuse your function by combining them in different ways.
That said, if you wanted the printing to be a side effect of sequence_rec you could simply do:
>>> def sequence_rec(start):
... if start == 1:
... ret = 1
... else:
... ret = sequence_rec(start - 1) * 2 + 5
... print(ret)
... return ret
...
>>> sequence_rec(3)
1
7
19
(edit) The function you describe in your comments doesn't make sense as a recursive function since it's not moving toward a base case. Try iteration instead:
>>> def sequence_iter(start, count):
... for _ in range(count + 1):
... print(start)
... start = start * 2 + 5
...
>>> sequence_iter(2, 5)
2
9
23
51
107
219
If you need to do it with recursion, the tactic is to decrement count each time:
>>> def sequence_rec(start, count):
... if count < 0:
... return
... print(start)
... sequence_rec(start * 2 + 5, count - 1)
...
>>> sequence_rec(2, 5)
2
9
23
51
107
219

how to solve 3x+1 on python

from random import randrange
a = randrange(1, 9)
print (a)
if (a % 2) == 0:
y = a / 2
while True:
if (y % 2) == 0:
y = y / 2
print (y)
else:
b = (a * 3) + 1
while True:
if (b % 2) == 0:
b = b / 2
else:
b = (a * 3) + 1
print (b)
"I want to make a math problem solver in python that can find a random number
between 1 and 9. Then if it is odd so it multiply it with 3 and add 1 in it and if it
is even so it divide it by two and this process keep repeating. For example a number
computer choose is 7 so :
7*3 + 1 = 22
22/2 = 11
11*3 = 33
and so on.
It shouldn't stop until the answer is 0.Here is my code in which I tried but not sure where should I make it right?"
You have too many lines in there. You need to loop to stop repeating when the number becomes 1 (it will never become 0):
from random import randrange
a = randrange(1, 9)
while a != 1:
print(a)
if a % 2 == 0:
a = a // 2
else:
a = (a * 3) + 1
print(a)
You can use the following code to check for any number or any range of numbers. This code is created by using the recursive function approach.
def f(x): #creating a function
if x!=4:
a.append(x)
if x%2==0:
while x%2==0:
x=x/2
a.append(x)
x=3*x+1
f(x)
For checking a particular value, run this:
a=[]
f(2**100+1) #2 to the power 10, plus 1
a[-1]
For checking for a range of values, run this:
for i in range(1,100):
a=[]
f(i)
print(i, "gives output" ,a)
I call it impossible maths because never reaches zero, it just keeps on looping forever Collatz problem. But this function does that, it does not take any parameter.
import random as r
def impossible_math():
x = r.ran(1,9)
while x !=0:
if x%2 ==0:
x = x/2
print(x)
else:
x = (x*3)+1
print(x)
x = impossible_math()

Stopping arithmetico-geometric sentence

I have a function u_terme that computes values of the sequence 3u + 1. I would like a stop function reached(M) that returns the lowest u value at which a given functional value is reached.
However, my code below doesn't work: it exits immediately and prints a single 0. Help?
def u_terme(x):
i = 0
u = 0
while i < x:
u = (3 * u) + 1
i = i + 1
print(u)
def reached(M):
x = 0
f = 0
while f >= M:
f = u_terme(x)
x = x + 1
print(x)
ANALYSIS:
u_terme fails to return any value.
reached exits immediately: your while loop quits as soon as f < M.
You have that logic reversed: you want to continue while f <= M.
Also, please use meaningful variable names.
REPAIR:
Make u_term return the computed value:
def u_terme(x):
u = 0
for i in range(x):
u = 3*u + 1
# print x, u
return u
Make reached iterate properly and return its result:
def reached(limit):
val = 0
func_val = 0
while func_val < limit:
val += 1
func_val = u_terme(val)
print val, func_val
return val
print reached(50)
Output:
1 1
2 4
3 13
4 40
5 121
5
Output:
17
Unfortunately the question is so unclear that it is difficult to provide a definitive answer. For example, what are allowable values of M?
At the first look, however, it is obvious that your u_terme() function has no return value (well, that is, it always return None). This means that f in the reached() function after the first iteration will be None and the loop will terminate.
Just because back-in-forth in comments doesn't work to well, I think this is the correct simplified, more efficient version of the code:
def u_terme(u):
return (3 * u) + 1
def reached(M):
x = 0
u = 0
while u < M:
u = u_terme(u)
x += 1
return x
print(reached(50)) # 5
EDIT
To help with the confusion in the comments. This new u_terme doesn't do what the previous one did. The previous one took a number x and computed u x times. This new one just returns the next value based on the previous one. This avoids duplicate work.
This code shows how to use it to get the expected values:
def u_terme(u):
return (3 * u) + 1
u = 0
for i in range(5):
print(i, u)
u = u_terme(u)
# Output:
# 0 0
# 1 1
# 2 4
# 3 13
# 4 40
EDIT 2
Just for fun, here's another way to do this. Why this is correct is an exercise left to the reader. :-)
def reached(M):
u = 0
x = 0
while u < M:
u += 3**x
x += 1
return x

Project Euler/Python: find sum of multiples of 3 and 5. Program not proceeding past input

I'm new to programming and i'm doing the Project Euler challenges to give me a reason to learn.
Find below my very simple python code
x = 1
thirdDivide = 0
fifthDivide=0
total = 0
print('Enter the max value')
maxValue = input()
while (x != maxValue):
thirdDivide = x / 3
fifthDivide = x / 5
if (thirdDivide).is_integer():
total = total + x
x = x + 1
elif (fifthDivide).is_integer():
total = total + x
x = x + 1
print ("The sum of the multiples of 3 and 5 between 0 and " + maxValue + " is " + total)
When I run it it asks for my max value, then ceases doing anything.
Thanks!
Assuming you are in Python 3, the fixes for using strings instead of floats, or floats instead of strings, infite loop is following:
x = 1
thirdDivide = 0
fifthDivide=0
total = 0
maxValue = float(input('Enter the max value: '))
while (x != maxValue):
thirdDivide = x / 3
fifthDivide = x / 5
if (thirdDivide).is_integer():
total = total + x
elif (fifthDivide).is_integer():
total = total + x
x = x + 1
print("The sum of the multiples of 3 and 5 between 0 and " + str(maxValue) + " is " + str(total))
Note, I dont check for correctness of your algoritm and whether it calculates what it is supposed to do. But now it produces some results and compiles.
You can solve it with a functional approach using filter and reduce:
def f(acc, v): return acc + v
def g(x): return x % 3 == 0 or x % 5 == 0
print reduce(f, filter(g, range(1000)))
How it works:
filter: takes two arguments:
The first is a function g applied for every element of range(1000). g takes one argument x and check if is multiple of 3 or 5 (checking the remainder of the modulo operation %).
The second is the range from 0 to 1000.
reduce: takes two arguments:
The first is a function f that takes two arguments: an accumulator acc and a variable v that represents the current element in the list.
The second argument is the filtered range returned before by filter.
Output:
with range(10) = 23
with range(1000) = 233168
Using lambda functions (same logic just different syntax):
print reduce(lambda acc, v: acc + v, filter(lambda x: x % 3 == 0 or x % 5 == 0, range(1000)))
You only increment x if thirdDivide.is_integer() or fifthDivide.is_integer() are true. So if neither it true, you'll just loop infinitely on the same value of x.
If neither thirdDivide nor fifthDivide is an integer, x is never updated -- you enter an infinite loop. You need to make sure you have a "base case" so that the iteration variable is always changing. Here's a slightly cleaner algorithm:
total = 0
for i in range(0, x):
if i % 3 == 0 or i % 5 == 0:
total += i
I think you'll find that for most iteration, for loops are easier to reason about. Happy coding!
As many said before, you are stuck in an infinite loop with x not being incremented. If you added a "else" statement at the end and printed the output you could see what they are talking about. You can do this in one line of code.
print(sum(x for x in range(maxValue) if x % 3 == 0 or x % 5 == 0))

When running the program nothing happens and it goes back to the command prompt

Basically, when i run the program nothing happens in the command prompt and it skips it and goes back to where the prompt was before I ran the program. I called Prime() at the bottom of the code and made sure that I have called all other codes within each code. It doesn't give me any errors when I run it. It just basically skips the program when run.
def Prime():
X = 3
N = 2
Prime1()
def Prime1():
global X
global N
global Y
global A
A = (X / N)
A = round(A,1) + 1
Y = (X%N)
if(N < A or N == A):
Prime2()
else:
print(X)
X = X + 2
Prime1()
def Prime2():
global X
global R
global N
global Y
global A
Y = (X%N)
N = N + 1
if(Y == 0):
X = X + 2
Prime1()
Prime()
With your values X = 3 and N = 2 your condition
if (N < A or N == A)
is true so the else part with your print(X) statement is not executed and in Prime2 Y has the value 1 so your programm is done and exits without any printed output.
And I would suggest you to have a look at the Python Tutorial how to write code in python, and create a better structure for your application without that amount of global variables. Try to pass the values as arguments and return a result etc.

Categories