Simplify Python iterations - python

Everytime I try to solve some math problem such as finding a specific product of certain number of factors I do this in Python
for x in xrange(1,10):
for y in xrange(1,10):
for z in xrange(1,10):
product = x * y * z
if product == 36:
print "factors : {0},{1},{2}".format(x,y,z)
It is very straightforward and gets the job done fast in this example, but I was wondering if you guys know an easier or simpler way to write this. Any ideas on how to do this without using that many for iterations or repeating almost the same code over and over. These is obviously for 3 factors, but the more factors I add the longer and more repetitive the code keeps getting. Any ideas on how to simplify code for this simple type of problem?
thanks

Itertool's cartesian product simulates the effect of multiple nested for loops.
import itertools
for x, y, z in itertools.product(range(1,10), range(1,10), range(1,10)):
product = x * y * z
if product == 36:
print "factors : {0},{1},{2}".format(x,y,z)
Result:
factors : 1,4,9
factors : 1,6,6
factors : 1,9,4
(...etc)
If the range is always the same for each of x,y, and z, you can specify it just once:
for x, y, z in itertools.product(range(1,10), repeat=3):
If you're sick of typing a zillion asterisks for the product = line, you can use reduce to multiply together an arbitrary number of arguments:
for factors in itertools.product(range(1,3), repeat=10):
product = reduce(lambda x, y: x*y, factors)
Once your format string becomes unwieldy, you can depend on join to string together factors:
if product == 512:
#use `map` to turn the factors into strings, first
print "factors: " + ",".join(map(str, factors))

Avoid duplicates by having y start at x. Calculate z instead of running another loop.
for x in xrange(1,10):
for y in xrange(x,10):
z, r = divmod(36, x*y)
if r == 0:
print "factors : {0},{1},{2}".format(x,y,z)
For more factors, I would use a recursive function.

Related

How to print the value of number during a "x" number of loops?

basically, Im trying to use a while loop to make an arithmetic sequence of numbers the code i made being rather simple:
x=2
while True:
x=x+3
print(x)
but a problem with this code of course is that there is no way i can find the value of x during a certain number of loops and rather this code prints every possible value in the sequence.
Does anyone know how i can make the code in a way that i can choose to print the value of x after a certain number of loops?
The easiest for a known nuber of iterations is a for-loop:
x = 2
iterations = 5
for _ in range(iterations):
x = x + 3
print(x)
This of course can be shortened in this particular example:
x = x + 3 * iterations

Python While Loop Square

I am a beginner at Python and I'm trying to use a while loop to sum up all of the squared n values in a given n value range.
Code:
def problem2(n):
x = 0
y = 0
while x < n:
y = (n**2)+y
x+=1
return y
For some reason, this equation returns the input number cubed.
Can someone explain why this happens and how to fix it?
You need to perform the ** on x, the value that is being incremented:
def problem2(n):
x = 0
count = 0
while x < n:
count += pow(x, 2)
x += 1
return count
You keep squaring the same number n, instead of the one being incremented x.
def sum_of_squares(n):
sum = 0
for x in range(0, n):
sum += x*x
return sum
You also don't really need the while loop, avoiding having to manually keep track of which variable is the counting variable and which one is the result variable (which is what you are confusing, as explained e.g. by #Ajax1234 in their answer).
It is a lot more Pythonic to use the built-in function sum, a generator expression and range:
def problem2(n):
return sum(x**2 for x in range(n))
This would be a lot more readable and better (unless of course you are being forced to use while).
Looks good. You're almost there.
It makes it the cube root because you add y to (n**2) everytime. Because you code runs until x !< n it runs n times. That means that you add n**2 to n**2*n.
That means that it gives 1(n**2)*(n-1)(n**2) which equals n(n**2) = n**3
Hope this was clear enough.

Python program Query

This is a question from John Guttag's book Introduction to Computation and Programming Using Python
Write a program that prints out the greatest odd number out of three numbers and an alternate error message if none of the numbers are odd.
This is my program. Is it correct? Does it cover all possibilities? I tried thinking it this way - exhaust all possibilities for the 3 statements - x is the largest, y is the largest and z is the largest - one by one. Is it the correct approach? Anyway, this is my program.
if ((x>y and x>z) or (x>y and x<z and z%2==0) or (x>z and x<y and
y%2==0) or (x<z and x<y and y%2==0 and z%2==0)) and x%2!=0:
print(x)
elif (y>z and y%2!=0) or (y<z and z%2==0)
print(y)
elif z%2!=0:
print(z)
else:
print('None of the numbers are odd')
Three simple steps:
Filter the list
Check if empty
Get max
filtered_list = filter(lambda x:x%2!=0, [x, y, z])
if filtered_list:
print max(filtered_list)
else:
print "No Odd number given"
It's almost correct
You are very close but you've forgotten a condition for when x is not printed and y and z are both even. Try the example of (4,2,6) for (x,y,z). Your exhaustive reasoning makes sense, but it is hard to program like this. I want to walk through your current logic then show how your code can be simplified, but your approach is clear using only if-else and indentation.
Your logic
In your logic you check all possibilities where you would ever print x which is if any following are true so long as x is odd:
x is the largest of x, y, and z
x is bigger than y when z is even
x is bigger than z when y is even
y and z are even
Then in the first elif you test whether to print y and make the correct decision to no longer check x at all since the first if handled all the cases where you would want to print x.
This is where your mistake is, however, since you should keep the same logical structure as your if statement for x:
elif ((y>z) or (y<z and z%2==0)) and y%2!=0:
You do the same for z in the last elif and then use else if all are even.
Simplifying your logic
We can simplify the first if statement where you check for x. One small note is that it is better to check that x is odd before doing all the or checks, since if x is even the computer doesn't have to look at all the or logic (short-circuiting):
if x%2 != 0 and ((x>y and x>z) or (x>y and x<z and z%2==0) or (x>z and x<y and
y%2==0) or (x<z and x<y and y%2==0 and z%2==0)):
Next the or logic can be simplified to:
if x%2 != 0 and ((x>=y and x>=z) or (x>=y and z%2==0) or (x>=z and
y%2==0) or (y%2==0 and z%2==0)):
All the simplifications came from the idea that if y or z is even we don't need to compare it to x since we'd want to print x regardless. I've also changed the > to >= or you would have had errors if some of the variables had the same values.
With the same reasoning we can simplify the first elif to:
elif ((y>=z) or (z%2==0)) and y%2!=0:
Bonus
If we know x, y, and z are not negative you can do this little trick. Try to work it out, leave a comment if you have questions or figure out how to make it work with negatives.
x = x*(x%2)
y = y*(y%2)
z = z*(z%2)
if x+y+z == 0:
print('None of the numbers are odd')
elif x >= y and x >= z:
print(x)
elif y >= x and y >= z:
print(y)
elif z >= x and z >= y:
print(z)
This is the Efficient code for finding whether the given number is odd or not.
Here I used '&' (and bitwise operator) which do bitwise and with one .
let the number 5(00000101)
when we do 5 & 1 then it will do (00000101) & (00000001) = (00000001).
This will happen with all other odd numbers.
ip = []
ip = map(int,raw_input().split())
odds = filter(lambda x : x & 1 != 0 , ip)
if len(odds) > 0 :
print (max(odds))
else :
print ("None of the numbers are odd")

Python: divide elements of a list based on a condition

I am trying to find the LCM of first 20 natural numbers (Project Euler question 5). For that, my algorithm is:
have numbers 1 to 20 in a list
Divide only those elements of the list that are divisible by i where i is in the range (2-20).
Whatever numbers are left in the list, multiply them and that will be the lcm.
This is the naivest algorithm which we actually used to calculate lcm in school for the first time.
Now, I donot know how to divide the elements of the list based on the condition.
I have tried:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for x in a:
if(x%2==0):
x=x/2
This does not seem to work.
I also tried:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
a1=[if(x%2==0): x/2 for x in a]
the above with both with and without ":" after the if condition. This does not work. I have the following questions:
a. Why isn't the first loop working correctly?
b. Can someone tell me how I can do this?
c. Will my algorithm work correctly?
a. Why isn't the first loop working correctly?
For the same reason as:
Foreach in Python not working as expected
b. Can someone tell me how I can do this?
You can do either:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for i, x in enumerate(a):
if x%2==0:
a[i]=x/2
Or:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
a1=[x/2 if x%2==0 else x for x in a]
c. Will my algorithm work correctly?
I don't think so. You'll end up dividing everyone by itself and the result will always be 1.
But there are other questions here in SO that have simple answers, like:
find least common multiple of numbers 1-20
a) Why is this loop not working correctly?
As #jose-ricardo-bustos-m indicates, the x is not a reference, is a local copy to each element of the array a, and cannot modify the array in the for loop. You can use, instead:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for i,x in enumerate(a): #used to provide a value, and an index
if(x%2==0):
a[i]=x/2
b) Can someone tell me how I can do this?
You can try to use the ternary if operator and list comprehension:
a = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
b = [x/2 if x%2==0 else x for x in a]
c) Will my algorithm work correctly
You have to keep track of the numbers you have already used, and you might need to divide by the same number more than once. But if you do that, and keep dividing by the same number _until the resulting list is equal to the previous one, and then move to the next, you can later multiply all numbers used, times the remainder of the list (but if you go to the max number in the list, the remaining list will contain just 1's).
def f(l,n): # divides items in a which are divisible by n, or leaves them
return [x/n if x%n==0 else x for x in l]
lcm = 1
a=[2,3,4,5,6,7]
# we go from the smallest to the largest number in your list
for i in range(2,max(a)+1):
repeat_next_time = True
while repeat_next_time:
b = f(a,i)
if a != b:
print('Using %s as a factor' % i)
a = b
lcm *= i
# print(a) # to get the status of the a list
else:
repeat_next_time = False
# finally, for numbers which might have not been divided yet,
# multiply the lcm by all of the remaining items
lcm *= reduce(lambda x,y: x*y, a)
It works even if there are common divisors, or repeated numbers in the list. Try, for instance, with a = [2,2,2], or a = [2,3,6], or a = [8,7,4,7].
a) the variable x takes the value of the list a , but not modified, it is not a reference of list, the following code does what you want:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for i in range(len(a)):
if(a[i]%2==0):
a[i]=a[i]/2
b) y C)
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
def f(x):
if(x%2==0):
return x/2
return x
a1=[f(x) for x in a]
Whatever numbers are left in the list, multiply them and that will be the lcm.
reduce(lambda x, y: x*y, a1)

Multiplying without the multiplication operator in python

How do I write a python script that multiplies x * y without using the multiplication operator? I know that basically you should have:
def multi():
x = raw_input('x is: ')
y = raw_input('y is: ')
z = #(x + x) y times
return z
multi()
You can use reduce which does x*y in the way you describe:
x = raw_input('x is: ')
y = raw_input('y is: ')
reduce(lambda a, b: a+b, [x]*y)
This will calculate ((x+x)+x)... y times.
EDIT to explain what reduce does:
The 1st argument is a function taking exactly 2 arguments, describing what to do at each iteration.
lambda x,y: x+y is just a function taking 2 arguments and adding them together. As if you wrote:
def my_operation(x, y):
return x + y
The 2nd argument is the input data, for example [1, 4, 2, 8, 9].
reduce will iterate over your input data, starting with 1 and 4. This is passed to your function which will return 5. Then 5 and 2 are passed to your function,...
So the calculation will be ((((1+4)+2)+8)+9)
So if your input list is [x, x, x..., x] of length y (i.e. [x]*y), you will get the result you want, calculated in the way you described.
x.__mul__(y)
operator.mul(x, y)
With sum and range or xrange:
z = sum(x for _ in xrange(y))
It can of course work the other way around, and effectively does x+x y times as you requested.
This works essentialy the same as doing:
z = 0
for _ in range(y):
z += x
For Python 3.x you can use this code to solve the same problem.
Knowing that 5*5 is == 5+5+5+5+5....with that idea in mind...
a = int(input("Intro a number: "))
b = int(input("Intro a second number: "))
for i in range(1,a):
b = b+a
print(b)
How do I write a python script that multiplies x * y without using the multiplication operator? you can use this code to solve the same problem
a = int(input("Intro a number: "))
b = int(input("Intro a second number: "))
c=b
for i in range(1,a):
b = b+c
print(b)

Categories

Resources