how to solve 3x+1 on python - 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()

Related

The code will print i after the conditions, but it won't print the sum of i. Error states that 'int' object is not iterable

x = int(input("Pick one small number: "))
y = int(input("And a bigger number: "))
if x > y:
print ("Doesn't work. ")
elif x < y:
for i in range(x,y):
if i%7 == 0 and i%5 !=0:
z = sum(i)
print (z)
You probably want to sum i one at a time like this:
z = 0
for n in range(x,y):
if n%7 == 0 and n%5 !=0:
n += i
print("Running total:", z)
print("Final total:", z)
If you want to use sum instead you have to apply it to a list:
filtered_list = []
for n in range(x,y):
if n % 7 == 0 and n % 5 !=0:
filtered_list.append(n)
print("Final total:", sum(filtered_list))
or using a generator expression:
print(sum(n for n in range(x, y) if n%7 == 0 and n%5 !=0))
There is also a shortcut to get all the multiples of 7 within range(x, y) :
multiples = range(x + 7 - x % 7, y, 7)
Then you only have to check the second condition (not divisible by 5)
print(sum(n for n in multiples if n%5 !=0))
You could also create 2 sets and calculate the difference:
def multiples(start, stop, d):
""" This function returns the set of all multiples of d between start and stop """
return set(range(start + divisor - start % divisor, stop, divisor))
print(sum(multiples(x, y, 7) - multiples(x, y, 5))
Finally a more maths approach. Your if condition is selecting the multiples of 7 and filtering out the numbers that are multiples of both 5 and 7. This is equivalent to subtracting the sum of the multiples of the least common multiple of 5 and 7 (which is 35) from the sum of the multiples of 7 within the range...
# we need a function from the math module that calculates the greatest common denominator
# we will use this to help calculate the least common multiple
from math import gcd
def sum_of_multiples(start, stop, mult):
""" Calculate sum of multiples of mult that lie in the range start, stop """
start //= mult
stop //= mult
return mult * (stop - start) * (stop + start + 1) / 2
lcm = 5 * 7 // gcd(5, 7) # The least common multiple of 5 and 7 = 35
print("Total:", sum_of_multiples(x, y, 7) - sum_of_multiples(x, y, lcm))
(Of course in the above you could just write 35 instead of lcm. I show the calculation in case you want to apply this using other numbers.)
You are getting that exception because sum expects an object that can be iterated through or in other words can return an iterator, such as a list, or tuple.
A proper way would have been to utilize the iterator object returned by the range function to get the cumulative value of all the numbers between x and y which are factors for 7 but not factors of 5.
x = int(input("Pick one small number: "))
y = int(input("And a bigger number: "))
if x > y:
print ("Doesn't work. ")
elif x < y:
print(sum([i for i in range(x, y) if i%7 == 0 and i%5 != 0]))

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

Sum of even integers from a to b in Python

This is my code:
def sum_even(a, b):
count = 0
for i in range(a, b, 1):
if(i % 2 == 0):
count += [i]
return count
An example I put was print(sum_even(3,7)) and the output is 0. I cannot figure out what is wrong.
Your indentation is off, it should be:
def sum_even(a, b):
count = 0
for i in range(a, b, 1):
if(i % 2 == 0):
count += i
return count
so that return count doesn't get scoped to your for loop (in which case it would return on the 1st iteration, causing it to return 0)
(And change [i] to i)
NOTE: another problem - you should be careful about using range:
>>> range(3,7)
[3, 4, 5, 6]
so if you were to do calls to:
sum_even(3,7)
sum_even(3,8)
right now, they would both output 10, which is incorrect for sum of even integers between 3 and 8, inclusive.
What you really want is probably this instead:
def sum_even(a, b):
return sum(i for i in range(a, b + 1) if i % 2 == 0)
Move the return statement out of the scope of the for loop (otherwise you will return on the first loop iteration).
Change count += [i] to count += i.
Also (not sure if you knew this), range(a, b, 1) will contain all the numbers from a to b - 1 (not b). Moreover, you don't need the 1 argument: range(a,b) will have the same effect. So to contain all the numbers from a to b you should use range(a, b+1).
Probably the quickest way to add all the even numbers from a to b is
sum(i for i in xrange(a, b + 1) if not i % 2)
You can make it far simpler than that, by properly using the step argument to the range function.
def sum_even(a, b):
return sum(range(a + a%2, b + 1, 2))
You don't need the loop; you can use simple algebra:
def sum_even(a, b):
if (a % 2 == 1):
a += 1
if (b % 2 == 1):
b -= 1
return a * (0.5 - 0.25 * a) + b * (0.25 * b + 0.5)
Edit:
As NPE pointed out, my original solution above uses floating-point maths. I wasn't too concerned, since the overhead of floating-point maths is negligible compared with the removal of the looping (e.g. if calling sum_even(10, 10000)). Furthermore, the calculations use (negative) powers of two, so shouldn't be subject by rounding errors.
Anyhow, with the simple trick of multiplying everything by 4 and then dividing again at the end we can use integers throughout, which is preferable.
def sum_even(a, b):
if (a % 2 == 1):
a += 1
if (b % 2 == 1):
b -= 1
return (a * (2 - a) + b * (2 + b)) // 4
I'd like you see how your loops work if b is close to 2^32 ;-)
As Matthew said there is no loop needed but he does not explain why.
The problem is just simple arithmetic sequence wiki. Sum of all items in such sequence is:
(a+b)
Sn = ------- * n
2
where 'a' is a first item, 'b' is last and 'n' is number if items.
If we make 'a' and b' even numbers we can easily solve given problem.
So making 'a' and 'b' even is just:
if ((a & 1)==1):
a = a + 1
if ((b & 1)==1):
b = b - 1
Now think how many items do we have between two even numbers - it is:
b-a
n = --- + 1
2
Put it into equation and you get:
a+b b-a
Sn = ----- * ( ------ + 1)
2 2
so your code looks like:
def sum_even(a,b):
if ((a & 1)==1):
a = a + 1
if ((b & 1)==1):
b = b - 1
return ((a+b)/2) * (1+((b-a)/2))
Of course you may add some code to prevent a be equal or bigger than b etc.
Indentation matters in Python. The code you write returns after the first item processed.
This might be a simple way of doing it using the range function.
the third number in range is a step number, i.e, 0, 2, 4, 6...100
sum = 0
for even_number in range(0,102,2):
sum += even_number
print (sum)
def sum_even(a,b):
count = 0
for i in range(a, b):
if(i % 2 == 0):
count += i
return count
Two mistakes here :
add i instead of [i]
you return the value directly at the first iteration. Move the return count out of the for loop
The sum of all the even numbers between the start and end number (inclusive).
def addEvenNumbers(start,end):
total = 0
if end%2==0:
for x in range(start,end):
if x%2==0:
total+=x
return total+end
else:
for x in range(start,end):
if x%2==0:
total+=x
return total
print addEvenNumbers(4,12)
little bit more fancy with advanced python feature.
def sum(a,b):
return a + b
def evensum(a,b):
a = reduce(sum,[x for x in range(a,b) if x %2 ==0])
return a
SUM of even numbers including min and max numbers:
def sum_evens(minimum, maximum):
sum=0
for i in range(minimum, maximum+1):
if i%2==0:
sum = sum +i
i= i+1
return sum
print(sum_evens(2, 6))
OUTPUT is : 12
sum_evens(2, 6) -> 12 (2 + 4 + 6 = 12)
List based approach,
Use b+1 if you want to include last value.
def sum_even(a, b):
even = [x for x in range (a, b) if x%2 ==0 ]
return sum(even)
print(sum_even(3,6))
4
[Program finished]
This will add up all your even values between 1 and 10 and output the answer which is stored in the variable x
x = 0
for i in range (1,10):
if i %2 == 0:
x = x+1
print(x)

Categories