Stopping arithmetico-geometric sentence - python

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

Related

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))

Dynamic programming for primitive calculator

I'm dealing with the problem, that is pretty similar to change coins problem.
I need to implement a simple calculator, that can perform the following three operations with the current number x: multiply x by 2, multiply x by 3, or add 1 to x.
Goal is given a positive integer n, find the minimum number of operations needed to obtain the number n starting from the number 1.
I made a greedy approach to that, bur it shows incorrect results
import sys
def optimal_sequence(n):
sequence = []
while n >= 1:
sequence.append(n)
if n % 3 == 0:
n = n // 3
elif n % 2 == 0:
n = n // 2
else:
n = n - 1
return reversed(sequence)
input = sys.stdin.read()
n = int(input)
sequence = list(optimal_sequence(n))
print(len(sequence) - 1)
for x in sequence:
print(x)
For example:
Input: 10
Output:
4
1 2 4 5 10
4 steps. But the correct one is 3 steps:
Output:
3
1 3 9 10
I read about dynamic programming, and hope I could implement it here. But, I can't get how to use it properly in particular case, can someone give me an advice?
Just solve it with a simple recursion and Memoization:
Code:
d = {}
def f(n):
if n == 1:
return 1, -1
if d.get(n) is not None:
return d[n]
ans = (f(n - 1)[0] + 1, n - 1)
if n % 2 == 0:
ret = f(n // 2)
if ans[0] > ret[0]:
ans = (ret[0] + 1, n // 2)
if n % 3 == 0:
ret = f(n // 3)
if ans[0] > ret[0]:
ans = (ret[0] + 1, n // 3)
d[n] = ans
return ans
def print_solution(n):
if f(n)[1] != -1:
print_solution(f(n)[1])
print n,
def solve(n):
print f(n)[0]
print_solution(n)
print ''
solve(10)
Hint: f(x) returns a tuple (a, b), which a denotes the minimum steps to get x from 1, and b denotes the previous number to get the optimum solution. b is only used for print the solution.
Output:
4 # solution for 10
1 3 9 10
7 # solution for 111
1 2 4 12 36 37 111
You may debug my code and to learn how it works. If you are beginner at DP, you could read my another SO post about DP to get a quick start.
Since Python can't recurse a lot (about 10000), I write an iterative version:
# only modified function print_solution(n) and solve(n)
def print_solution(n):
ans = []
while f(n)[1] != -1:
ans.append(n)
n = f(n)[1]
ans.append(1)
ans.reverse()
for x in ans:
print x,
def solve(n):
for i in range(1, n):
f(i)[0]
print_solution(n)
print ''
solve(96234) # 1 3 9 10 11 22 66 198 594 1782 5346 16038 16039 32078 96234

Python function returning first value twice

I've written this function to calculate sin(x) using Taylor series to any specified degree of accuracy, 'N terms', my problem is the results aren't being returned as expected and I can't figure out why, any help would be appreciated.
What is am expecting is:
1 6.28318530718
2 -35.0585169332
3 46.5467323429
4 -30.1591274102
5 11.8995665347
6 -3.19507604213
7 0.624876542716
8 -0.0932457590621
9 0.0109834031461
What I am getting is:
1 None
2 6.28318530718
3 -35.0585169332
4 46.5467323429
5 -30.1591274102
6 11.8995665347
7 -3.19507604213
8 0.624876542716
9 -0.0932457590621
Thanks in advance.
def factorial(x):
if x <= 1:
return 1
else:
return x * factorial(x-1)
def sinNterms(x, N):
x = float(x)
while N >1:
result = x
for i in range(2, N):
power = ((2 * i)-1)
sign = 1
if i % 2 == 0:
sign = -1
else:
sign = 1
result = result + (((x ** power)*sign) / factorial(power))
return result
pi = 3.141592653589793
for i in range(1,10):
print i, sinNterms(2*pi, i)
I see that you are putting the return under the for which will break it out of the while loop. You should explain if this is what you mean to do. However, given the for i in range(1,10): means that you will ignore the first entry and return None when the input argument i is 1. Is this really what you wanted? Also, since you always exit after the calculation, you should not do a while N > 1 but use if N > 1 to avoid infinite recursion.
The reason why your results are off is because you are using range incorrectly. range(2, N) gives you a list of numbers from 2 to N-1. Thus range(2, 2) gives you an empty list.
You should calculate the range(2, N+1)
def sinNterms(x, N):
x = float(x)
while N >1:
result = x
for i in range(2, N):
Your comment explains that you have the lines of code in the wrong order. You should have
def sinNterms(x, N):
x = float(x)
result = x
# replace the while with an if since you do not need a loop
# Otherwise you would get an infinite recursion
if N > 1:
for i in range(2, N+1):
power = ((2 * i)-1)
sign = 1
if i % 2 == 0:
sign = -1
# The else is not needed as this is the default
# else:
# sign = 1
# use += operator for the calculation
result += (((x ** power)*sign) / factorial(power))
# Now return the value with the indentation under the if N > 1
return result
Note that in order to handle things set factorial to return a float not an int.
An alternative method that saves some calculations is
def sinNterms(x, N):
x = float(x)
lim = 1e-12
result = 0
sign = 1
# This range gives the odd numbers, saves calculation.
for i in range(1, 2*(N+1), 2):
# use += operator for the calculation
temp = ((x ** i)*sign) / factorial(i)
if fabs(temp) < lim:
break
result += temp
sign *= -1
return result

understanding def function in python

I was trying to compute e (2.718283) in python and I realized you couldn't simply divide so I defined a function to divide and round to five digits and I also defined a function to find factorials , here it is -
.
def div(x,y):
t = x + 0.00
p = y + 0.00
a = t / p
round(a,5)
print a
def fact(n):
c = 1
d = 1
while c < n:
p = c * d
d = c*d
c = c + 1
if c >= n:
break
p = p*n
print p
m = 0
while m < 20:
e = div(1,fact(m)) + q
q = div(1,fact(m + 1)) + q
if m >= 20:
break
print e `
I execute it and I get this UnboundLocalError: local variable 'p' referenced before assignment . But fact(3) seems to be working perfectly ..
What is going on ?
PS : i'm not yet used to formatting here but I have indented properly in the actual code
EDIT : as requested
line 20, in <module>
e = div(1,fact(m)) + q
File "/home/anirudh/Desktop/TEST PY/Hark-1.py", line 16, in fact
p = p*n
UnboundLocalError: local variable 'p' referenced before assignment
There are a couple of bugs:
q isn't defined anywhere before it's used in e = div(1,fact(m)) + q
You don't assign the result of round(a,5) to anything.
If the while c < n: loop isn't entered, p won't be defined when p = p*n is executed.
Both the fact and the div functions don't return anything. (They implicitly return None.)
There's no need to check if m >= 20:.
See, first of all there are already some cleaner and descent inbuilt methods in Python for calculating the factorial.
import math
print math.factorial(3) #6
print math.factorial(4) #24
And if you want to get the float value after dividing two integers then, you can simply typecast any one of them to the float, it is not necessary to convert both of them.
float_ans = p/float(q)
#or
float_ans = float(p)/q
Using this information, you can calculate the value of e, by simply:
#Knowing the fact that e = 1 + 1/1! + 1/2! + 1/3! + 1/4! + 1/5! ....
import math
e = 0
"""
As factorial of 20 is a very large value and you won't require that much of
precision, I have cut down the no of iterations from 20 to 7 only, it also gives
you a fair amount of precision, you can always change the range to increase and
decrease the precision accordingly.
"""
for num in range(0,7):
e+=(float(1)/math.factorial(num))
print e
2.71805555556

Factorial doesn't output an integer

I'm not a very experienced programmer but I just wrote this in Python to try and find e, using the definition that e is the sum of 1/0! + 1/1! + 1/2! etc...
The problem I'm having is def factorial doesn't output an integer. I realize it wouldn't given how it's written but I'm not sure how I can make it. total is what I would want outputted as an int from def factorial.
e = 0
def factorial(m):
n = m - 1
total = 1
if n > 0:
total = m
while n > 0:
total = total * n
n = n - 1
for w in range(0,100):
s = factorial(w)
e = e + ( 1 / s )
print(e)
def factorial(m):
n = m - 1
total = 1
if n > 0:
total = m
while n > 0:
total = total * n
n = n - 1
return total
EDIT: The problem is that, in order to get information from factorial, you have to use a return statement. Anything after the return is evaluated, and used as the value of s in s = factorial(w).
The code by Feffernoose works. But to improve the performance in your case, you would better use the "yield" statement to build a iterable object.
e = 0
def factorial(m):
assert(m>1)
current = 0
total = 1
while current<=m:
yield total
current += 1
total *= current
for w in factorial(100):
e = e + ( 1 / w )
print(e)
Update: in the solution with "return", you approximately need O(n*n) time for the factorial value computation. But with "yield", you only need O(n).

Categories