I've been trying to solve this:
Find positive integer solutions for a,b,c that 1≤a<b<c≤30 and b/a c/b a/c is a positive integer.
So I worte this, in python:
for i,j,m in range(1,31):
if i<=j and j<=m and j/i m/j i/m>=0:
try:
print(int(j/i m/j i/m))
except TypeError:
continue
However it didn't work.
And the error message:
for i,j,m in range(1,31):
TypeError: cannot unpack non-iterable int object
CodePudding user response:
Iterating over a triplet
range
returns an iterable over single integers. To iterate over triplets, you can either nest three loops, or use itertools
:
# using nested loops
for a in range(1, 29):
for b in range(a 1, 30):
for c in range(b 1, 31):
...
# using itertools
from itertools import combinations
for a,b,c in combinations(range(1,31), 3):
...
Note that in both cases, I wrote the loops to iterate directly over triplets (a,b,c)
satisfying a < b < c
. This is much more efficient than iterating over all triplets (a,b,c)
, then filtering for the condition a < b < c
.
Testing whether b/a c/b a/c
is an integer
When dealing with fractions with different denominators, the first thing to do is usually to put everything to a common denominator. In this case, the sum of three fractions b/a c/b a/c
is equal to fraction (b*b*c c*a*c a*a*b) / (a*b*c)
. Testing whether this fraction is an integer or not is exactly testing whether its numerator is divisible by its denominator. This can be easily achieved with the modulo operator %
.
if (b*b*c c*a*c a*a*b) % (a*b*c) == 0:
...
This is actually better than using floating-point division and testing if the result looks like an integer. Floating-point division results in a binary floating-point number. Not all numbers can be represented exactly in binary floating-point: just like fraction 1/3
cannot be represented exactly in decimal, many numbers cannot be represented exactly in binary. Imagine testing whether 1/3 1/3 1/3
is an integer: if 1/3
is rounded to 0.333
, then we'll get 0.333 0.333 0.333 == 0.999
, which is not an integer. This is an approximation error. If possible, when dealing with integer arithmetic, always use only integers, and never use floating-point division. Protect yourself from floating-point approximations!
Separating algorithm logic from input/output
It is very good practice to separate the parts of code that deal with algorithms and arithmetic, on the one side, from parts of code that deal with printing to screen, reading from and writing to files, etc.
You could append all the found triplets to a list, then return the list:
def get_triplet_list(n):
l = []
for a,b,c in combinations(range(1, n 1), 3):
if (b*b*c c*a*c a*a*b) % (a*b*c) == 0:
l.append((a,b,c))
return l
def main():
l = get_triplet_list(30)
for a,b,c in l:
print(a,b,c)
if __name__ == '__main__':
main()
# 2 9 12
# 3 4 18
# 4 18 24
Or use a list comprehension:
def get_triplet_list(n):
return [(a,b,c) for a,b,c in combinations(range(1, n 1), 3) if (b*b*c c*a*c a*a*b) % (a*b*c) == 0]
def main():
l = get_triplet_list(30)
for a,b,c in l:
print(a,b,c)
if __name__ == '__main__':
main()
Or use a generator function, with keyword yield
instead of return
:
def gen_triplets(n):
for a,b,c in combinations(range(1, n 1), 3):
if (b*b*c c*a*c a*a*b) % (a*b*c) == 0:
yield (a,b,c)
def main():
for a,b,c in gen_triplets(30):
print(a,b,c)
if __name__ == '__main__':
main()
CodePudding user response:
You want to assign 3 variables, range()
only returns a single "list" of values.
I'm not exactly sure what you are trying to do but I suspect you want to try every combination of values for i
, j
and m
. One way to do this is creating nested loops. Each loop will iterate over the values for one variable.
Another solution would be using itertools
and create a list of all combinations which will processed by your function (which would need some little adjustments).
CodePudding user response:
try this : According to problem statement, 1≤a<b<c≤30 and b/a c/b a/c >0
for i in range(1,31):
for j in range(1,31):
for m in range(1,31):
if i<j and j<m and j/i m/j i/m>0:
try:
print(int(j/i m/j i/m))
except TypeError:
continue