So, our teacher gave us an assignment to find three integers a, b c. They are in all between 0 and 450 using Python.
a = c + 11 if b is even
a = 2c-129 if b is odd
b = ac mod 2377
c = (∑(b-7k) from k = 0 too a-1) +142 (Edited. I wrote it wrong. Was -149)
I tired my code that looks like this: (Still a newbie. I guess a lot of my code is wrong)
for a, b, c in range(0, 450):
if b % 2 == 0:
a = c + 11
else:
a = 2 * c - 129
b = (a * c) % 2377
c = sum(b - 7 * k for k in range(0, a - 1))
but I get the error:
for a, b, c in range(0, 450):
TypeError: 'int' object is not iterable
What am I doing wrong and how can I make it check every number between 0 and 450?
The answers by Nick T and Eric hopefully helped you solve your issue with iterating over values of a, b, and c. I would like to also point out that the way you're approaching this problem isn't going to work. What's the point of iterating over various values of a if you're going to re-assign a to something anyway at each iteration of the loop? And likewise for b and c. A better approach involves checking that any given triple (a, b, c) satisfies the conditions given in the assignment. For example:
from itertools import product, tee
def test(a, b, c):
flags = {'a': False,
'b': False,
'c': False}
if (b % 2 == 0 and a == c+11) or (b % 2 == 1 and a == 2*c-129):
flags['a'] = True
if b == (a * c) % 2377:
flags['b'] = True
if c == sum(b - 7*k for k in range(a-1)) - 149:
flags['c'] = True
return all(flags.values()) # True if zero flags are False
def run_tests():
# iterate over all combinations of a=0..450, b=0..450, c=0..450
for a, b, c in product(*tee(range(451), 3)):
if test(a, b, c):
return (a, b, c)
print(run_tests())
NOTE: This is a slow solution. One that does fewer loops, like in glglgl's answer, or Duncan's comment, is obviously favorable. This is really more for illustrative purposes than anything.
import itertools
for b, c in itertools.product(*[range(450)]*2):
if b % 2 == 0:
a = c + 11
else:
a = 2 * c - 129
derived_b = (a * c) % 2377
derived_c = sum(b - 7 * k for k in range(0, a - 1))
if derived_b == b and derived_c == c:
print a, b, c
You need to nest the loops to brute-force it like you are attempting:
for a in range(451): # range(450) excludes 450
for b in range(451):
for c in range(451):
...
It's very obviously O(n3), but if you want a quick and dirty answer, I guess it'll work—only 91 million loops, worst case.
The stuff with [0, 450] is just as a hint.
In fact, your variables are coupled together. You can immediately eliminate at least one loop directly:
for b in range(0, 451):
for c in range(0, 451):
if b % 2: # odd
a = 2 * c - 129
else:
a = c + 11
if b != (a * c) % 2377: continue # test failed
if c != sum(b - 7 * k for k in range(a)): continue # test failed as well
print a, b, c
should do the job.
I won't post full code (after all, it is homework), but you can eliminate two of the outer loops. This is easiest if you iterate over c.
You code should then look something like:
for c in range(451):
# calculate a assuming b is even
# calculate b
# if b is even and a and b are in range:
# calculate what c should be and compare against what it is
# calculate a assuming b is odd
# calculate b
# if b is odd and a and b are in range:
# calculate what c should be and compare against what it is
Extra credit for eliminating the duplication of the code to calculate c
a = c + 11 if b is even
a = 2c-129 if b is odd
b = ac mod 2377
c = (∑(b-7k) from k = 0 to a-1) +142
This gives you a strong relation between all 3 numbers
Given a value a, there are 2 values c (a-11 or (a+129)/2), which in turn give 2 values for b (ac mod 2377 for both values of c, conditioned on the oddity of the result for b), which in turn gets applied in the formula for validating c.
The overall complexity for this is o(n^2) because of the formula to compute c.
Here is an implementation example:
for a in xrange(451):
c_even = a - 11
b = (a*c_even) % 2377
if b % 2 == 0:
c = sum(b - 7 * k for k in range(a)) + 142
if c == c_even:
print (a, b, c)
break
c_odd = (a+129)/2
b = (a*c_odd) % 2377
if b % 2 == 1:
c = sum(b - 7 * k for k in range(a)) + 142
if c == c_odd:
print (a, b, c)
break
Related
What is wrong here?
The loop conditions should be fulfilled but the program is not entering the loop.
a=100
b=55
c = min(a,b)
while (a % c !=0 // b % c != 0):
c = c - 1
gcd = c
print(gcd)
EDIT: I'm dumb.
// is the floor division operator. You need to use or for the logical OR function. Here is a simple article on basic Python operators.
a=100
b=55
c = min(a,b)
while (a % c !=0) or (b % c != 0):
c = c - 1
gcd = c
print(gcd) # prints 5
Not strictly what you're asking about, but the far more efficient way to compute the gcd is with the Euclidean algorithm. Also, gcd = c does not need to be inside the while loop.
Here's some alternative code.
a = 100
b = 55
while b != 0:
a, b = b, a % b
gcd = a
print(gcd)
I would like to know why this code is giving me two different solution:
a = 0
b = 1
solution = 0
while b <= 4000000:
if b % 2 == 0:
solution += b
a, b = b, a + b
print(solution)
in this case the solution is 4613732. However when I try this code:
a = 0
b = 1
solution = 0
while b <= 4000000:
if b % 2 == 0:
solution += b
a = b
b = a + b
print(solution)
the solution is 4194302
Any suggestions?
The difference explained
Because you write:
a = b
b = a + b
In your second approach. That means that after the first line, a has the value of b. And the second line will produce b = a + b = b + b so two times b. In other words, the second one will actually walk through the powers of two.
That is not happening in the first approach, since you write:
a, b = b, a + b
As a result you first construct a tuple (b,a+b) (with a and b the old values). Next you unpack that tuple into a and b again. But you first evaluated a + b with the old values. That is the essential difference.
More efficient approach
You want to sum up the even Fibonacci numbers. You can however to this more efficiently. If you do an analysis on the Fibonacci sequence, you will find out that it is structured:
o o e o o e o o e ...
with o being an odd number, and e being an even number. So you can simply work with hops of three, like:
a = 1
b = 2
solution = 0
while b <= 4000000:
solution += b
a,b = a+2*b,2*a+3*b
print(solution)
Here we thus save on iterations and on checks whether b is even: we simply know that it is always even.
When using timeit (with Python 3.5.3 and GCC 6.3.0 on linux), we obtain the following results:
original 3.4839362499988056
optimized 1.5940769709995948 45.755%
So the average runtime of the optimized program is about half of the original one.
Simply because, all expressions at the right side of the assignment operator gets evaluated first.
So let's say you have the code below:
a = 5
b = 7
a, b = b, a + b
You expect a to be assigned with the value 7 and then b to be assigned with the value 14, the sum of a and b using the new value of a.
In fact, on the right side of the = operator, b is evaluated to 7 and a+b is evaluated to 12
a, b = 7, 12
I was doing Problem 9 in Project Euler when I ran into a problem. My program was taking way to long too run. More than half an hour. Here is my code.
def Problem9():
a = 1
b = 1
c = 1
x = []
while(a + b + c != 1000):
a = a + 1
for i in range(0,1000):
c = 1000 - (a + b)
if a < b < c:
if (a*a) + (b*b) == (c*c):
x.append(a*b*c)
print(a*b*c)
b = b + 1
print(x)
Problem9()
This basically is supposed to find out all the Pythagorean triplets which add up to one thousand(link to problem so that you can understand it better: https://projecteuler.net/problem=9) Is there a problem in my code which I can fix or is my code fundamentally wrong?
Since you know that the three numbers must add up to 1000, and a < b < c, you take advantage of that fact to loop much more efficiently (and cleanly).
def Problem9():
for a in range(1000):
for b in range(a,1000):
if a**2 + b**2 == (1000 - a - b)**2:
return a*b*(1000 - a - b)
Here, you loop over a from 1 to 1,000. Since b must be greater than a, you then looper over b from a until 1,000. Then, since you know that 1000 = a + b + c, then c = 1000 - a - b, and you can test you Pythagorean condition without any more looping.
A Pythagorean triplet is a set of three natural numbers, a < b < c, for > which a2 + b2 = c2.
There exists exactly one Pythagorean triplet for which a + b + c = 1000.
This will work
def pythagorean_tiplet():
a = 1
while(a < 1000):
b = a + 1 # note this, b is starting from a + 1, since b starting from 0 is useless and will only add to the running time.
while (b < 1000):
result = a**2 + b**2
c = math.sqrt(result)
if (( a + b + c) == 1000 and (a < b < c)): #test for conditions
return a * b * c
b += 1
a += 1
print(pythagorean_tiplet())
This
algorithm is definitely unsuitable for perimeters s > 1 000 000.
There is a faster algorithm that can be used to solve it. you can search for parametrisation of Pythagorean triplets
You've the system
(*1) a + b + c = 1000
(*2) a² + b² = c²
If
a + b + c = 1000
then
a + b = 1000 - c
(a + b)² = (1000 - c)²
a² + 2ab + b² = 1000² - 2000c + c²
( a² + b² ) + 2ab = 1000² - 2000c + c²
but, by the (*2), ( a² + b² ) = c², and then
c² + 2ab = 1000² - 2000c + c²
2ab = 1000² - 2000c
2000c = 1000² - 2ab
then
c = 500 - ab/(1000)
So, now, you've the new system:
(*3) a + b + 500 - ab/(1000) = 1000
(*4) c = 500 - ab/(1000)
Besides, a, b, and c are whole numbers, and a<b<c;
if a>332, a must be, at least, 333, and then,
b should be, at least, 334, and then, c should be, at least, 335; 333 + 334 + 335 = 1002.
With more math, you can do this even easier.
def p():
for a in range(1,333):
for b in range(a+1,(1000-a)/2):
if ( 1000*a + 1000*b + 500000 - a*b == 1000000 ):
c=500-((a*b)/1000)
print (a,b,c);print a*b*c
return
p()
Result:
time python Special_Pythagorean_triplet.py
(200, 375, 425)
31875000
real 0m0.041s user 0m0.036s sys 0m0.000s
In the if statement:
if ( 1000*a + 1000*b + 500000 - a*b == 1000000 )
you could use:
if ( a + b + 500 - (a*b)/1000 == 1000 )
but, in this case, only whole numbers matters:
with the first, you get around division and its rounding problems.
A better way is use itertools
https://docs.python.org/3.4/library/itertools.html
from itertools import product
def ff1():
for r in product(range(1,1000),repeat=3):
a,b,c=r
if a+b+c==1000:
if a<b<c:
if a**2+b**2==c**2:
print(a,b,c)
print(a*b*c)
ff1()
This code is really awkward. The while condition itself it's somehow wrong, you would stop with the first 3 numbers that sum 1000, then exit. Another wrong thing is that B doesn't reset. You can do similar to how Ibukun suggested, but it is not the best way to do for this direct approach. You DON'T need to check if they sum 1000. It's way simpler:
Iterate A from 3 to 997
Iterate B from A+1 to 999-A
Do C = 1000 - A - B (that's how you don't need to check the sum, you kinda already did that)
Check if they are triplet, when they are, you are done!
There are other great approaches you can check out once you enter the right answer, they are way more interesting
def g(n):
"""Return the value of G(n), computed recursively.
>>> g(1)
1
>>> g(2)
2
>>> g(3)
3
>>> g(4)
10
>>> g(5)
22
"""
if n<=3:
return n
else:
return g(n-1)+2*g(n-2)+3*g(n-3)
How do I convert this to an iterative function? Until now, I didn't realize that writing a recursive function is sometimes easier than writing an iterative one. The reason why it's so hard I think is because I don't know what operation the function is doing. In the recursive one, it's not obvious what's going on.
I want to write an iterative definition, and I know I need to use a while loop, but each time I try to write one either I add additional parameters to g_iter(n) (when there should only be one), or I make a recursive call. Can someone at least start me off on the right path? You don't have to give me a complete solution.
FYI: We have not learned of the all too common "stack" I'm seeing on all these pages. I would prefer to stay away from this.
def g_iter(n):
"""Return the value of G(n), computed iteratively.
>>> g_iter(1)
1
>>> g_iter(2)
2
>>> g_iter(3)
3
>>> g_iter(4)
10
>>> g_iter(5)
22
"""
"*** YOUR CODE HERE ***"
def g(n):
if n <= 3:
return n
a, b, c = 1, 2, 3
for i in range(n - 3):
a, b, c = b, c, c + 2 * b + 3 * a
return c
UPDATE response to comment, without using for loop.
def g(n):
if n <= 3:
return n
a, b, c = 1, 2, 3
while n > 3:
a, b, c = b, c, c + 2 * b + 3 * a
n -= 1
return c
I can't seem to get my function to work. When I type in 3 for a, 2 for b, and 3.61 for c. That works. However, when I try those values in a different order (Ex: 3.61 for a, 3 for b and 2 for c) It returns as false. I can't figure out what the problem is. Thanks in advance!
a = input("Enter a ")
b = input("Enter b ")
c = input("Enter c ")
def isright_angled():
if abs((a**2+b**2)-(c**2)) < 0.1 or abs((c**2-a**2)-(b**2)) < 0.1 or abs((c**2-b**2)-(a**2)) < 0.1:
return True
else:
return False
print isright_angled()
The hypotenuse, if the triangle is right-angled, will be the largest of a, b and c. You can use that to avoid duplicating the test 3 times (this is the "don't repeat yourself" principle). A second thing to avoid is that if something: return True else: return False. It's usually better expressed as simply return something. Thirdly, functions can take arguments rather than relying on global variables: this makes things easier to understand and there's then less chance of functions interfering with each other. I find a * a easier to understand than a ** 2 but that's personal taste. Putting all that together:
def is_approximately_right_angled(a, b, c):
a, b, c = sorted([a, b, c])
return abs(a * a + b * b - c * c) < 0.1
a = input('enter a ')
b = input('enter b ')
c = input('enter c ')
print is_approximately_right_angled(a, b, c)
If it's not working, you can speed up your development by adding some checks. If you were writing a big program you can write unit tests, but here just some asserts in the module will avoid you having to type a, b, c in each time to test.
I'd add something like this (before the a = input... line):
assert is_approximately_right_angled(3, 4, 5)
assert is_approximately_right_angled(3, 5, 4)
assert is_approximately_right_angled(3, 2, 3.61)
assert not is_approximately_right_angled(3, 5, 5)
With these lines in place, you can have some confidence in the code before you get to type numbers in. When you find cases where the code doesn't work you can add them as additional checks.
a = int(input("Enter the side length" ))
b = int(input("Enter the side length" ))
c = int(input("Enter the side length" ))
def is_right_triangle(a,b,c):
'''
is_right_triangle(a,b,c) -> bool
returns True if a,b,c is a right triangle with hypotenuse c
'''
a, b, c = sorted([a, b, c])
return a*a + b*b == c*c
print(is_right_triangle(a,b,c))
for more accuracy you can use
return abs(a * a + b * b - c * c) < 0.001