projecteuler problem 8 - unsure on what is wrong with my code - python

A Pythagorean triplet is a set of three natural numbers, a < b < c,
for which,
a^2 + b^2 = c^2
For example, 3^2 + 4^2 = 9 + 16 = 25 = 5^2.
There exists exactly one Pythagorean triplet for which a + b + c =
1000. Find the product abc.
above is the question. when i run my code it works and runs how i expect it to, but the programme always finishes without finding an answer. any advice on how to improve my code would be appreciated.
for k in range (1,1000):
c = 1000 - k
for i in range (1,c):
b = c - i
c_sqr = c ** 2
b_sqr = b ** 2
a = c - b
a_sqr = a ** 2
if a_sqr + b_sqr == c_sqr:
if a + b + c == 1000:
product = a * b * c
print(f"{product} is the answer")
exit()
else:
print("Pythagorean triplet!")
else:
josephmama = 11
print("not a pythagorean triplet")

In your code c < 1000 and a + b == c are invariants. The sum (a + b + c) == 2 * c requires that the longest side(hypotenuse) of the right triangle to be as long as the sum of the other sides, and there's no such numbers that satisfy it and so the if body never executes.
for a in range(1, 1000):
for b in range(1, 1000):
c = 1000 - (a + b)
if (a ** 2 + b ** 2 == c ** 2):
print(a * b * c)
exit()

a is not always equal to c - b
by deriving b from c and a from c and b you are unnecessarily limiting the options of what b and a could be. Just loop through all combinations of a, b and c, add the constrains you have and you'll eventually get your triplet.
for a in range(1, 1000):
for b in range(1, 1000):
for c in range(1, 1000):
if a+b+c == 1000:
if a**2+b**2 == c**2:
if a < b:
if b < c:
print(f"My Triplet: a: {a}, b: {b}, c:{c}")

Related

How do I write a program to find A,B answer that AAB +BB =BAA in python?

topic:
If A and B are both integers from 1 to 9, try to find out those (A, B) values that can meet the following conditions: AAB+BB=BAA
What I write:
for A in range (1,10):
for B in range(1,10):
if #I have no idea...
print(A,B)
Well, start with the fact that AAB is equal to A * 100 + A * 10 + B.
Apply that to the others, work out the expressions, and test for equality.
For example(1), to test if ABBA + AB is exactly seven greater than BBBB, you could use something like:
abba = A * 1000 + B * 100 + B * 10 + A # or A * 1001 + B * 110
ab = A * 10 + B
bbbb = B * 1000 + B * 100 + B * 10 + B # or B * 1111
if abba + ab == bbbb + 7:
do_something()
(1) Hopefully close enough that you can work it out for your specific question, but not so close that you can just plagiarise :-)
You can use:
from itertools import product
[(A,B,f'{A}{A}{B} + {B}{B} = {B}{A}{A}')
for A,B in product(range(1,10), range(1,10))
if A*100+A*10+B+B*10+B == B*100+A*10+A]
output: [(8, 9, '889 + 99 = 988')]
Using a classical loop:
for A in range(1,10):
for B in range(1,10):
if A*100+A*10+B+B*10+B == B*100+A*10+A:
print(f'A={A}, B={B} -> {A}{A}{B} + {B}{B} = {B}{A}{A}')
output:
A=8, B=9 -> 889 + 99 = 988
You can really simplify this by just casting to strings and back to integers. Since this is a small enough n there won't be any performance concerns.
You could apply math by adding factors of 10 in the appropriate places but to me, this is the most obvious what's going on.
for A in range (1, 10):
for B in range(1, 10):
AAB = int(str(A) + str(A) + str(B))
BB = int(str(B) + str(B))
BAA = int(str(B) + str(A) + str(A))
if AAB + BB == BAA:
print(A, B)
Or with f-strings.
for A in range (1, 10):
for B in range(1, 10):
AAB = int(f'{A}{A}{B}')
BB = int(f'{B}{B}')
BAA = int(f'{B}{A}{A}')
if AAB + BB == BAA:
print(A, B)
At first, lets simplify the expression.
AAB + BB = BAA == 100A + 10A + B + 10B + B = 100B + 10A + A == 99A = 88B == 9A = 8B.
As you can see, we can already suggest the right answer (A should be the value of B multiplier and vise versa).
But if you really need to write some Python code, here you go:
for a in range(1, 10):
for b in range(1, 10):
if a * 9 == b * 8:
print(f'A={a}, B={b}')
Output: A=8, B=9

How this algorithm actually works and thought process behind it?

I came across this question as follows:
There are three integers a, b, c given in input. You have to convert the number a to b by performing the given operations:
Multiply a by c
Decrease a by 2.
Decrease a by 1.
You have to perform the above operations to convert the integer from a to b and find the minimum steps.
Note: You can perform the operations in any order.
I found this solution:
def rec(a,b,c):
if a>=b:
return ((a-b)//2+(a-b)%2)
if b%c==0:
return (1+rec(a,b//c,c))
else:
x=(b//c+1)*c;
return ((x-b)//2+(x-b)%2+rec(a,x,c))
a,b,c=map(int,input().split())
print(rec(a,b,c))
The first condition check is easily understandable that if (a>=b) then we decrement a in steps of 2 until we reach b and if there is a remainder "1" we add it to the steps to compute the final output.
In second and third condition checks it successfully performs the required operation using the concept of recursion, but why recursion is used? Is it possible to do it without recursion? What is the use of x in third condition?
You can add some kind of logging, at each moment there really is only one possible route:
def rec(a, b, c):
if a >= b:
# when a >= b, multiplying doesn't make sense,
# so subtract 2 as many times as needed
# then subtract 1 if the difference was odd
print(f"from {a}, subtract 2 for {(a - b) // 2} steps, subtract 1 for {(a - b) % 2} steps to get {b}" +
f" (this are {((a - b) // 2 + (a - b) % 2)} steps)")
return ((a - b) // 2 + (a - b) % 2)
if b % c == 0:
# we have a < b, we need to multiply at least once to get from b/c to b,
# we still need to go from a to b/c
print(f"first get {b // c}, then multiply by {c} to get {b}" +
f" (this is 1 step)")
return (1 + rec(a, b // c, c))
else:
# we have a < b and b isn't a multiple of c
# we need to get to a multiple of c that is larger then b, let x be this multiple
# we need to multiply at least once to get from x/c to x
# we will need subtractions of 2 and 1 to get from x to b
# we still need to go from a to x
x = (b // c + 1) * c
print(f"first get {x}, then subtract 2 for {(x - b) // 2} steps, subtract 1 for {(x - b) % 2} steps to get {b}" +
f" (this are {((x - b) // 2 + (x - b) % 2)} steps)")
return ((x - b) // 2 + (x - b) % 2 + rec(a, x, c))
a, b, c = map(int, input().split())
print("Total number of steps:", rec(a, b, c))
For example, for 4 29 5:
first get 30, then subtract 2 for 0 steps, subtract 1 for 1 steps to get 29 (this are 1 steps)
first get 6, then multiply by 5 to get 30 (this is 1 step)
first get 10, then subtract 2 for 2 steps, subtract 1 for 0 steps to get 6 (this are 2 steps)
first get 2, then multiply by 5 to get 10 (this is 1 step)
from 4, subtract 2 for 1 steps, subtract 1 for 0 steps to get 2 (this are 1 steps)
Total number of steps: 6
PS: As the function is written with tail recursion, it can easily be transformed to a loop. Instead of giving the variables new values by recursion, the new values can be assigned localy in the loop:
def rec(a, b, c):
result = 0
while a < b:
if b % c == 0:
result += 1
b //= c
else:
x = (b // c + 1) * c
result += (x - b) // 2 + (x - b) % 2
b = x
result += ((a - b) // 2 + (a - b) % 2)
return result
A benefit of the recursive code, is that it is easier to convert to write the output in the correct order:
def rec(a, b, c):
if a >= b:
steps2 = (a - b) // 2
steps1 = (a - b) % 2
if steps1 + steps2 > 0:
print(f"from {a}" +
(f", subtract 2 for {steps2} steps" if steps2 > 0 else "") +
(f", subtract 1" if steps1 > 0 else "") +
f" to get {b}" +
f" ({steps1 + steps2} steps)")
return steps1 + steps2
if b % c == 0:
prev_steps = rec(a, b // c, c)
print(f"from {b // c}, multiply by {c} to get {b}" +
f" (plus 1 step, totaling {1 + prev_steps} steps)")
return 1 + prev_steps
else:
x = (b // c + 1) * c
prev_steps = rec(a, x, c)
steps2 = (x - b) // 2
steps1 = (x - b) % 2
print(f"from {x}" +
(f", subtract 2 for {steps2} steps" if steps2 > 0 else "") +
(f", subtract 1" if steps1 > 0 else "") +
f" to get {b}" +
f" (plus {steps1 + steps2} steps, totaling {steps1 + steps2 + prev_steps} steps)")
return steps1 + steps2 + prev_steps
from 4, subtract 2 for 1 steps to get 2 (1 steps)
from 2, multiply by 5 to get 10 (plus 1 step, totaling 2 steps)
from 10, subtract 2 for 2 steps to get 6 (plus 2 steps, totaling 4 steps)
from 6, multiply by 5 to get 30 (plus 1 step, totaling 5 steps)
from 30, subtract 1 to get 29 (plus 1 steps, totaling 6 steps)

Solving problems in Python

I currently have the following, both of which must hold true:
A B C D + A E F = E F G H and
I C J * E = A B C D
Each letter represents a unique digit from 0 to 9 and both equations must hold true.
I need to write a Python solution which outputs the correct answer, here is my code:
import numpy as np
def solve():
for a in range(0,10):
for b in range(0,10):
for c in range(0,10):
for d in range(0,10):
for e in range(0,10):
for f in range(0,10):
for g in range(0,10):
for h in range(0,10):
for i in range(0,10):
for j in range(0,10):
if len(set([a, b, c, d, e, f, g, h, i, j])) == 10:
icj = 100*i + 10*c + j
e = e
abcd = 1000*a + 100*b + 10*c + d
aef = 100*a + 10*e + f
efgh = 1000*e + 100*f + 10*g + h
if icj * e == abcd and abcd + aef == efgh:
print(icj, e, abcd, aef, efgh)
print(solve())
However, when I run this, not only does it take a while to run, it outputs "None". Any ideas as to where I am going wrong?
You should try for x in range(0, 10) instead of for x in range(0,9) because you were looping from 0 to 8
If you want to loop in a more efficient way, you can use permutations:
from itertools import permutations
for a, b, c, d, e, f, g, h, i, j in permutations(range(0, 10), 10):
print(a, b, c, d, e, f, g, h, i, j)
Result :
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 9 8
...
9 8 7 6 5 4 3 2 0 1
9 8 7 6 5 4 3 2 1 0
Here is the final code :
import numpy as np
from itertools import permutations
def solve():
for a, b, c, d, e, f, g, h, i, j in permutations(range(0, 10), 10):
icj = 100*i + 10*c + j
e = e
abcd = 1000*a + 100*b + 10*c + d
aef = 100*a + 10*e + f
efgh = 1000*e + 100*f + 10*g + h
if icj * e == abcd and abcd + aef == efgh:
print(icj, e, abcd, aef, efgh)
print(a, b, c, d, e, f, g, h, i, j)
solve()
Output :
934 7 6538 672 7210
6 5 3 8 7 2 1 0 9 4
Apart from the typos, if you only test in the very inner loop whether all 10 digits are different, this inner loop is executed 1010 = 10,000,000,000 times. If you test at every pass, you "only" need 10! = 3,628,800 passes to this inner loop.
You still can do better changing the order of variables, so the equation abc * d == hibj can be tested without needing the other 3 variables, and only go deeper when it holds. For these 7 digits, you enter 604,800 times in that loop, and only 45 times you need to go deeper to reach the most inner loop only 270 times.
def solve():
for a in range(0, 10):
for b in range(0, 10):
if a != b:
for c in range(0, 10):
if not c in [a, b]:
for d in range(0, 10):
if not d in [a, b, c]:
for h in range(0, 10):
if not h in [a, b, c, d]:
for i in range(0, 10):
if not i in [a, b, c, d, h]:
for j in range(0, 10):
if not j in [a, b, c, d, h, i]:
abc = 100 * a + 10 * b + c
hibj = 1000 * h + 100 * i + 10 * b + j
if abc * d == hibj:
print(abc, '*', d, '=', hibj)
for e in range(0, 10):
if not e in [a, b, c, d, h, i, j]:
for f in range(0, 10):
if not f in [a, b, c, d, h, i, j, e]:
for g in range(0, 10):
if not g in [a, b, c, d, h, i, j, e, f]:
hde = 100 * h + 10 * d + e
defg = 1000 * d + 100 * e + 10 * f + g
if hibj + hde == defg:
print(abc, d, hibj, hde, defg)
solve()
print('done')
Although it now runs fast enough, still more specific optimizations can be thought of:
Change the order to a,b,c and h,i,j then calculate whether hibj is a multiple of abc. Only in case it is, this defines d which should be between 0 and 9, and different from the rest.
Or, the reverse: generate a,b,c,d and then try all the multiples first whether they fit b and then whether the corresponding h,i,j are different from each other and different from a,b,c,d.
h should be smaller than a, otherwise d will be larger than 9. This makes a at least 1.
Usually in this kind of problems, the first digit of every number is supposed to be non-zero, which can further reduce the number of checks.
An alternative approach, is to use an SMT/SAT solver such as Z3. With such a solver, all the conditions are formulated, and via all kind of heuristics a solution is searched for. Example codes: here and here.
This is how the code could look like:
from z3 import Int, And, Or, Distinct, Solver, sat
D = [Int(f'{c}') for c in "abcdefghij"]
a, b, c, d, e, f, g, h, i, j = D
vals_0_to_9 = [And(Di >= 0, Di <= 9) for Di in D]
all_different = [Distinct(D)]
abc = 100 * a + 10 * b + c
hibj = 1000 * h + 100 * i + 10 * b + j
hde = 100 * h + 10 * d + e
defg = 1000 * d + 100 * e + 10 * f + g
equations = [abc * d == hibj, hibj + hde == defg]
s = Solver()
s.add(vals_0_to_9 + all_different + equations)
while s.check() == sat:
m = s.model()
print(", ".join([f'{Di}={m[Di]}' for Di in D]))
s.add(Or([Di != m[Di] for Di in D]))
This prints out a=9, b=3, c=4, d=7, e=2, f=1, g=0, h=6, i=5, j=8 as unique solution.

How can i get sum of all the numbers that this program prints?

B = 1
A = 3
C = 1
while C < 1000:
B = B + 1
C = A * B
print (C)
This is the code and i want to get the sum of the numbers that it prints
Here is a possibility,
B = 1
A = 3
C = 1
D = 0
while C < 1000:
B = B + 1
C = A * B
D += C
print (C)
# sum of all printed numbers
print(D)
B runs over all the integers from 2 to 334; you only need the sum of all integers from 2 to 334 (which is well known: average * number of elements) and then multiply it by A:
A = 3
B_max = 334 # ~ (1000 // A) + ...
res = A * (B_max + 2) * (B_max - 1) // 2
# 167832
you just need to make sure you get B_max right...
there is no reason for a loop at all if that is all you need to do.
define a list outside while:
dataList = []
then add C in that list:
while C < 1000:
B = B + 1
C = A * B
dataList.append(C)
then find sum:
print(sum(dataList))
for me, your goal is not clear. can you explain it more for me to be able to help you?
PS. your B = B + 1 can be simplified to:
B += 1
You should declare SUM first:
SUM=0
And at the end of while loop after print message, add
SUM = SUM + C
And thats all, simplest possible way.
B = 1
A = 3
C = 1
total = 0
while C < 1000:
B = B + 1
C = A * B
print(C)
total+=C
print("Sum is : ",total)

Python - Make avarage variables without 0

A = 0
B = 10
C = 20
N = [(A, B, C)]
Avarage = (A + B + C) / sum(1 for i in N if i != 0)
Avarage = 30??
Need Avarage = 15.
Any idea?
You need to remove ( and ) from your list N
a = 0
b = 10
c = 20
n = [a, b, c]
list_avg = sum(n) / sum(1 for i in n if i != 0)
Output:
>>> list_avg
15
N is list containing tupple. So sum(1 for i in N if i != 0) returns 1 as there is only 1 element (a tupple) in list N.
Try:
A = 0
B = 10
C = 20
N = [(A, B, C)]
Avarage = (A + B + C) / sum(1 for i in N[0] if i != 0)
print Avarage
15
OR:
A = 0
B = 10
C = 20
N = [A, B, C]
Avarage = (A + B + C) / sum(1 for i in N if i != 0)
print Avarage
15
As stated by depperm, N is a list of one tuple, so you have in your sum only one element (which is different than 0 because it is a tuple and not an int). Otherwise you can use numpy
import numpy as np
average = np.mean([A, B, C])
Make a new list of values without the zeros, then average that:
non_zero = [v for v in (A, B, C) if v != 0]
avg = sum(non_zero)/len(non_zero)

Categories

Resources