我正在编写一个Python程序,它返回列表中可以创建三角形的组合数。
示例:
--> test([1,1,3])
0 #you cant make a triangle out of 1,1,3 (the only combination in this list)
--> test([2,789,5,3,3237,4])
3 #you can make a triangle out of [2,5,4],[5,3,4] and [2,4,3]
我只设法编写一个函数来检查你是否可以在3个给定边中创建一个三角形:
def check(a,b,c):
n = max((a,b,c))
x = 0
y = 0
for i in [a,b,c]:
if i != n:
if x == 0:
x = i
elif y == 0:
y = i
return (x+y)>n
答案 0 :(得分:0)
使用函数来检查是否有任何三个边可以在评论中给出三角形check
非常容易:
from itertools import combinations
def test(x):
return sum(check(*comb) for comb in combinations(x, 3))
这使用itertools.combinations
提供所有可能的组合的事实,此处输入的长度为3
,以及bool为True == 1
和False == 0
的整数,所以我们可以将它们相加以获得True
元素的数量。
您的check
功能也可能更明确:
def check(a, b, c):
a, b, c = sorted([a, b, c])
return a + b > c
答案 1 :(得分:0)
首先,您的检查功能不正确。从this post,我们看到所需的条件是每对边的总和大于另一边。正如@david explained:
假设a,b,c是三角形的边。因此,它 必须满足这个标准:
- a + b> ç
- a + c> B'/ LI>
- b + c>一个
醇>
您只是检查两个较小边的总和是否大于最大值。此外,对于最大边重复的情况,您的功能将失败。例如,值1, 4, 4
形成有效三角形,但您的函数check(1, 4, 4)
返回False
。
话虽如此,你几乎无法避免检查3个值的所有组合。
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)]
您可以通过对列表进行排序来提高边际速度。这有帮助,因为代码可能会短路,因为第一个条件会失败(而且你不必检查另外两个)。
例如,这些是示例列表中3个边的排序组合:
>>> 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)]
在第三个示例中,x = 2
,y = 3
和z = 789
。第一个条件(x+y) > z
将失败,您不必检查其他两个条件。我已经包含了一些时序结果,以显示排序稍微更快。
更新
如果您想避免重复,可以使用集合理解:
{(x, y, z) for (x, y, z) in combinations(sorted(test), 3) if
((x+y) > z) and ((x+z) > y) and ((y+z) > x)}
时间安排
# 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