Firstly, your check function is incorrect. From this post, we see that the conditions required are that the sum of each pair of sides is greater than the other side. As @david explained:
Let's say that a, b, c is the sides of the triangle. Therefore, it
must be satisfy this criteria:
- a + b > c
- a + c > b
- b + c > a
You are only checking to see if the sum of the two smaller sides is greater than the largest. Furthermore, your function would fail for cases where the largest side is duplicated. For example, the values 1, 4, 4
form a valid triangle but your function check(1, 4, 4)
returns False
.
That being said, there is very little you can do to avoid checking all combinations of 3 values.
from itertools import combinations
[(x, y, z) for (x, y, z) in combinations(test, 3)
if ((x+y) > z) and ((x+z) > y) and ((y+z) > x)]
#[(2, 5, 4), (2, 3, 4), (5, 3, 4)]
You could make a marginal speed improvement by sorting the list. This helps because the code can short-circuit because the first condition will fail (and you don't have to check the other two).
For example, these are the sorted combinations of 3 sides from your example list:
>>> test = [2,789,5,3,3237,4]
>>> list(combinations(sorted(test), 3))
[(2, 3, 4),
(2, 3, 5),
(2, 3, 789),
(2, 3, 3237),
(2, 4, 5),
(2, 4, 789),
(2, 4, 3237),
(2, 5, 789),
(2, 5, 3237),
(2, 789, 3237),
(3, 4, 5),
(3, 4, 789),
(3, 4, 3237),
(3, 5, 789),
(3, 5, 3237),
(3, 789, 3237),
(4, 5, 789),
(4, 5, 3237),
(4, 789, 3237),
(5, 789, 3237)]
In the third example, x = 2
, y = 3
, and z = 789
. The first condition (x+y) > z
will fail and you won't have to check the other two. I've included some timing results to show that sorting is slightly faster.
Update
If you wanted to avoid duplicates, you can use a set comprehension:
{(x, y, z) for (x, y, z) in combinations(sorted(test), 3) if
((x+y) > z) and ((x+z) > y) and ((y+z) > x)}
Timing Results
# make list of random numbers
import numpy as np
N = 100
test = [np.random.randint(0,5000) for i in range(N)]
# without sorting
%%timeit
[(x, y, z) for (x, y, z) in combinations(test, 3)
if ((x+y) > z) and ((x+z) > y) and ((y+z) > x)]
#10 loops, best of 3: 76.1 ms per loop
# with sorting
%%timeit
[(x, y, z) for (x, y, z) in combinations(sorted(test), 3) if
((x+y) > z) and ((x+z) > y) and ((y+z) > x)]
#10 loops, best of 3: 65.1 ms per loop