引用多个列表直到获得正确的组合
Referencing multiple lists until correct combinations achieved
编辑以更新我的代码并对 @MOHAMMED
给予完整回应
图片,如果你愿意的话,一个立方体。该立方体的每个面都有一组 4 个数字。立方体上的每个数字只出现一次。
到目前为止,在此处的一些帮助下,我已经设法编写了一个程序,将这 24 个数字过滤到一个列表中,其中 4 个数字的每个面总计 50,没有一对面总计 25,但每个数字它正好相反(物理上)总共 25.
我现在的问题是边角。我有一条规则要应用到他们身上。每个角相交的 3 个数字的总和必须是 37 或 38。还有一些其他规则,但现在让我们坚持下去。
现在,就像骰子一样,相反的数字总和相同。这意味着,对于所有意图,我的每个组都有一个对立面,因此,它永远不会与之相邻。
所以我的程序吐出了第一组符合我的标准的 6 张面孔。我现在如何算出角落?
我意识到我只需要处理 6 个面孔中的 3 个面孔,因为每个数字都与总数 25 的对面配对,一旦一个角符合规则,它的对面也应该这样做。
我已经针对这个问题简化了我的代码。
group1 = list(['A','B','E','F'])
group2 = list(['A','D','E','G'])
group3 = list(['A','B','C','D'])
group4 = list(['E','F','G','H'])
group5 = list(['B','C','F','H'])
group6 = list(['C','D','G','H'])
for a in group1:
for b in group2:
for c in group3:
for corner1 in itertools.combinations((a,b,c),3):
if (a == b == c):
print (corner1)
给予
('A','A','A')
假设没有匹配,那么在1,2,3之后还有另外两个可能的分组组合;那些是 1,3,5 和 1,4,5。
我认为使用 1 作为所有其他配对的常量可以使其更简单。
我有两个问题,首先,假设我们的第一个匹配项只出现在最后一组组合中,那么编写代码的最佳方式是什么?
for a in group1:
for b in group2:
for c in group3:
for d in group4:
for e in group5:
for f in group6:
for corner1 in itertools.combinations((a,b,c),3):
else:
for corner1 in itertools.combinations((a,b,d),3):
else:
for corner1 in itertools.combinations((a,d,e),3):
或:
for a in group1:
for b in group2:
for c in group3:
for corner1 in itertools.combinations((a,b,c),3):
else for a in group1:
for b in group2:
for c in group4:
for corner1 in itertools.combinations((a,b,d),3):
else for a in group1:
for b in group2:
for c in group3:
for corner1 in itertools.combinations((a,d,e),3):
即使这些代码中的任何一个都可行(我对这两个代码都有疑问,因为我是新手),然后我需要从与同一组的进一步匹配中删除这些数字并保留顺序的组。
例如,如果规则的第一位选择组合 1、2、4,我如何确保后续查询仅在该条件为真时才有效(这有意义吗?)
这是我到目前为止的完整代码.... 已编辑
n = 0
cnr1 = 0
cnr2 = 0
cnr3 = 0
cnr4 = 0
faces_all = list(range(1,25))
for x in itertools.combinations((faces_all[1:24]),3):
if faces_all[0] + sum(x) == 50:
side1 = (faces_all[0], x[0], x[1], x[2])
for pair in itertools.combinations(side1, 2):
if sum(pair) == 25:
break
else:
side6 = (25-side1[0], 25-side1[1], 25-side1[2], 25-side1[3])
faces_remaining = list(set(faces_all) - set(side1) - set(side6))
for y in itertools.combinations(faces_remaining,4):
if sum(y) == 50:
side2 = y
for pair in itertools.combinations(side2,2):
if sum(pair) == 25:
break
else:
side5 = (25-side2[0], 25-side2[1], 25-side2[2], 25-side2[3])
faces_last = list(set(faces_remaining) - set(side2) - set(side5))
for z in itertools.combinations(faces_last,4):
if sum(z) == 50:
side3 = z
for pair in itertools.combinations(side3,2):
if sum(pair) == 25:
break
else:
side4 = (25-side3[0], 25-side3[1], 25-side3[2], 25-side3[3])
for a in side2:
for b in side3:
for c in side4:
for d in side5:
for top in itertools.permutations(side1,4):
for corner1 in itertools.combinations((top[0],a,b),3):
if (sum(corner1) == 37 or sum(corner1) == 38):
corner8 = (25-top[0],25-a,25-b)
cnr1 += 1
print ("1&8",cnr1,"2&7",cnr2,"3&6",cnr3)
for corner2 in itertools.combinations((top[1],b,d),3):
#if (b not in corner1 and sum(corner1) + sum(corner2) == 75):
if sum(corner1) + sum(corner2) == 75:
corner7 = (25-top[1],25-b,25-d)
cnr2 += 1
print ("1&8",cnr1,"2&7",cnr2,"3&6",cnr3)
for corner3 in itertools.combinations((top[2],d,c),3):
#if (d not in corner1 and sum(corner3) == sum(corner1)):
if sum(corner3) == sum(corner1):
corner6 = (25-top[2],25-d,25-c)
cnr3 += 1
print ("1&8",cnr1,"2&7",cnr2,"3&6",cnr3)
for corner4 in itertools.combinations((top[2],c,a),3):
#if (c not in corner3 and a not in corner1 and sum(corner4) + sum(corner1) == 75):
if sum(corner4) + sum(corner1) == 75:
corner5 = (25-top[2],25-c,25-a)
print ("1&8",cnr1,"2&7",cnr2,"3&6",cnr3)
print (n)
print ("sides:", side1, side2, side3, side4, side5, side6)
print ("corners:", corner1, corner2, corner3, corner4, corner5, corner6)
输出(从开始到代码停止无误)是:
1&8 1 2&7 0 3&6 0
...
1&8 8109504 2&7 213792 3&6 5558
所以角 1&8 有 800 万次命中,1&8 和 2&7 只有 200,000 次,1&8、2&7 和 3&6 只有 5,000 次——但没有包括 4&5)。
这表明我无法实现(这是可能的),或者我的代码有问题。
尝试图表使其更清晰:
A____________B
|\A B:\
|A\ :B\
| \ : \
| \D______:__C\C
| D|D : C|
E|E | F:F |
\```|````````. |
\ | . |
\H| .|
\|H_________G|G
H G
+-----+
| E F |
| A B |
+-----+-----+-----+-----+
| E A | A B | B F | F E |
| H G | D C | C G | G H |
+-----+-----+-----+-----+
| D c |
| H G |
+-----+
+----------------------+
|Ee fF|
| +--+----------+--+ |
| |37|e 50 f|38| |
| +--+--+ +--+--+ |`
| |E |38|a b|37| F| |
| | +--+----+--+ | |
| | Aa|A B|bB | |
| | 50 | 50 | 50 | |
| | Dd|D C|cC | |
| | +--+----+--+ | |
| |H |37|d c|38| G| |
| +--+--+ 50 +--+--+ |
| |38|h g|37| |
| +--+----------+--+ |
|Hh gG|
+----------------------+
====================================== ===================================
响应 @Mohammed's 代码
from itertools import combinations
# Filter functions
# ------------
## All sides add to 50
def check_sides(lst):
sides = [lst[0] + lst[1] + lst[2] + lst[3],
lst[4] + lst[5] + lst[12] + lst[13],
lst[6] + lst[7] + lst[14] + lst[15],
lst[8] + lst[9] + lst[16] + lst[17],
lst[10] + lst[11] + lst[18] + lst[19],
lst[20] + lst[21] + lst[22] + lst[23]]
return all(side == 50 for side in sides)
# All corners are 37 or 38
def check_corners(lst):
print(".")
corners = [lst[5] + lst[6] + lst[2],
lst[3] + lst[7] + lst[8],
lst[13] + lst[14] + lst[20],
lst[21] + lst[15] + lst[16],
lst[12] + lst[22] + lst[19],
lst[23] + lst[17] + lst[6],
lst[1] + lst[9] + lst[10],
lst[0] + lst[4] + lst[11]]
return all(36 < corner < 39 for corner in corners)
# All opposites add to 25
def check_opposites(lst):
print(lst)
opposites = [lst[0] + lst[22],
lst[2] + lst[20],
lst[1] + lst[23],
lst[3] + lst[21],
lst[5] + lst[8],
lst[4] + lst[9],
lst[12] + lst[17],
lst[13] + lst[16],
lst[7] + lst[10],
lst[6] + lst[11],
lst[15] + lst[18],
lst[14] + lst[19]]
return all(pair == 25 for pair in opposites)
# No pairs on a side add to 25
def check_pairs(lst):
pairs = [lst[0] + lst[1], lst[2] + lst[3],
lst[0] + lst[2], lst[1] + lst[3],
lst[0] + lst[3], lst[1] + lst[2],
lst[4] + lst[5], lst[12] + lst[13],
lst[4] + lst[12], lst[5] + lst[13],
lst[4] + lst[13], lst[5] + lst[12],
lst[6] + lst[7], lst[14] + lst[15],
lst[6] + lst[14], lst[7] + lst[15],
lst[6] + lst[15], lst[7] + lst[14],
lst[8] + lst[9], lst[16] + lst[17],
lst[8] + lst[16], lst[9] + lst[17],
lst[8] + lst[17], lst[9] + lst[16],
lst[10] + lst[11], lst[18] + lst[19],
lst[10] + lst[18], lst[11] + lst[19],
lst[10] + lst[19], lst[11] + lst[18],
lst[20] + lst[21], lst[22] + lst[23],
lst[20] + lst[22], lst[21] + lst[23],
lst[20] + lst[23], lst[21] + lst[22]]
return all(pair != 25 for pair in pairs)
# Everything else
# ---------------
def nFilter(filters, iterable):
for f in filters:
iterable = filter(f, iterable)
return iterable
candidates = combinations(range(1,50), 24)
#cubes = nFilter([check_sides, check_corners, check_opposites, check_pairs], candidates)
cubes = nFilter([check_sides],candidates)
for cube in cubes:
print(cube)
我在每张脸上添加了缺失的 "pairs"(对于 4 个数字,有 6 种可能的组合对(AB、AC、AD、BC、BD、CD)。
我重新安排了检查的顺序,首先执行参数最少的检查。
但我不理解输出,它似乎只是在不应用过滤器的情况下打印从 1 到 n 的 24 个数字的所有组合。
将 combinations(range(1,50)
更改为 combinations(range(1,26)
会产生以下输出,并将其更改为 combinations(range(1,25)
(这样只会使用我想使用的数字 (1-24) 只会产生下面第一行输出。
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
====================================== ===================================
添加更多代码:
我有以下 2 个充满丑陋 if 语句的程序,但希望它们能正常工作。
所以我有
face_combinations = 0
faces_all = list(range(1,25))
for side in combinations((faces_all[1:24]),3):
if faces_all[0] + sum(side) == 50:
if faces_all[0] + side[0] != 25:
if faces_all[0] + side[1] != 25:
if faces_all[0] + side[2] != 25:
if side[0] + side[1] != 25:
if side[0] + side[2] != 25:
if side[1] + side[2] != 25:
side1 = (faces_all[0], side[0], side[1], side[2])
side6 = (25-side1[0], 25-side1[1], 25-side1[2], 25-side1[3])
faces_remaining = list(set(faces_all) - set(side1) - set(side6))
for side in combinations(faces_remaining[1:16],4):
if faces_remaining[0] + sum(side) == 50:
if faces_remaining[0] + side[0] != 25:
if faces_remaining[0] + side[1] != 25:
if faces_remaining[0] + side[2] != 25:
if side[0] + side[1] != 25:
if side[0] + side[2] != 25:
if side[1] + side[2] != 25:
side2 = (faces_remaining[0], side[0], side[1], side[2])
side5 = (25-side2[0], 25-side2[1], 25-side2[2], 25-side2[3])
faces_last = list(set(faces_remaining) - set(side2) - set(side5))
for side in combinations(faces_last[1:8],4):
if faces_last[0] + sum(side) == 50:
if faces_last[0] + side[0] != 25:
if faces_last[0] + side[1] != 25:
if faces_last[0] + side[2] != 25:
if side[0] + side[1] != 25:
if side[0] + side[2] != 25:
if side[1] + side[2] != 25:
side3 = (faces_last[0], side[0], side[1], side[2])
side4 = (25-side2[0], 25-side2[1], 25-side2[2], 25-side2[3])
face_combinations += 1
print (face_combinations, side1, side2, side3, side4, side5, side6)
产生:
2 (1, 4, 22, 23) (5, 6, 9, 12) (7, 8, 10, 11) (20, 19, 16, 13) (20, 19, 16, 13) (24, 21, 3, 2)
3 (1, 4, 22, 23) (5, 6, 9, 13) (7, 8, 10, 11) (20, 19, 16, 12) (20, 19, 16, 12) (24, 21, 3, 2)
4 (1, 4, 22, 23) (5, 6, 9, 14) (7, 8, 10, 12) (20, 19, 16, 11) (20, 19, 16, 11) (24, 21, 3, 2)
5 (1, 4, 22, 23) (5, 6, 11, 12) (7, 8, 9, 10) (20, 19, 14, 13) (20, 19, 14, 13) (24, 21, 3, 2)
6 (1, 4, 22, 23) (5, 6, 11, 13) (7, 8, 9, 10) (20, 19, 14, 12) (20, 19, 14, 12) (24, 21, 3, 2)
7 (1, 4, 22, 23) (5, 7, 8, 11) (6, 9, 10, 12) (20, 18, 17, 14) (20, 18, 17, 14) (24, 21, 3, 2)
8 (1, 4, 22, 23) (5, 7, 8, 12) (6, 9, 10, 11) (20, 18, 17, 13) (20, 18, 17, 13) (24, 21, 3, 2)
9 (1, 4, 22, 23) (5, 7, 8, 13) (6, 9, 10, 11) (20, 18, 17, 12) (20, 18, 17, 12) (24, 21, 3, 2)
10 (1, 4, 22, 23) (5, 7, 8, 14) (6, 9, 10, 12) (20, 18, 17, 11) (20, 18, 17, 11) (24, 21, 3, 2)
...
691 (1, 15, 16, 18) (2, 3, 5, 19) (4, 8, 11, 13) (23, 22, 20, 6) (23, 22, 20, 6) (24, 10, 9, 7)
692 (1, 15, 16, 18) (2, 4, 8, 13) (3, 5, 6, 14) (23, 21, 17, 12) (23, 21, 17, 12) (24, 10, 9, 7)
693 (1, 15, 16, 18) (2, 4, 11, 12) (3, 5, 6, 17) (23, 21, 14, 13) (23, 21, 14, 13) (24, 10, 9, 7)
694 (1, 15, 16, 18) (2, 4, 11, 13) (3, 5, 6, 17) (23, 21, 14, 12) (23, 21, 14, 12) (24, 10, 9, 7)
695 (1, 15, 16, 18) (2, 4, 13, 14) (3, 5, 6, 17) (23, 21, 12, 11) (23, 21, 12, 11) (24, 10, 9, 7)
696 (1, 15, 16, 18) (2, 5, 6, 14) (3, 4, 8, 13) (23, 20, 19, 11) (23, 20, 19, 11) (24, 10, 9, 7)
697 (1, 15, 16, 18) (2, 6, 11, 12) (3, 4, 5, 17) (23, 19, 14, 13) (23, 19, 14, 13) (24, 10, 9, 7)
还有这个:
numbers_all = list(range(1,25))
corner_combinations = 0
for corner in combinations((numbers_all[1:24]), 2):
if 36 < numbers_all[0] + sum(corner) < 39:
corner1 = (numbers_all[0], corner[0], corner[1])
if corner1[0] + corner1[1] != 25:
if corner1[0] + corner1[2] != 25:
if corner1[1] + corner1[2] != 25:
corner8 = (25 - corner1[0], 25 - corner1[1], 25 - corner1[2])
numbers_remaining = list(set(numbers_all) - set(corner1) - set(corner8))
for corner in combinations((numbers_remaining[1:18]), 2):
if 36 < numbers_remaining[0] + sum(corner) < 39:
corner2 = (numbers_remaining[0], corner[0], corner[1])
if sum(corner1) + sum(corner2) ==75:
if corner2[0] + corner2[1] != 25:
if corner2[0] + corner2[2] != 25:
if corner2[1] + corner2[2] != 25:
corner7 = (25 - corner2[0], 25 - corner2[1], 25 - corner2[2])
numbers_remaining2 = list(set(numbers_remaining) - set(corner2) - set(corner7))
for corner in combinations((numbers_remaining2[1:12]), 2):
if 36 < numbers_remaining2[0] + sum(corner) < 39:
corner3 = (numbers_remaining2[0], corner[0], corner[1])
if sum(corner3) == sum(corner1):
if corner3[0] + corner3[1] != 25:
if corner3[0] + corner3[2] != 25:
if corner3[1] + corner3[2] != 25:
corner6 = (25 - corner3[0], 25 - corner3[1], 25 - corner3[2])
numbers_remaining3 = list(set(numbers_remaining2) - set(corner3) - set(corner6))
for corner in combinations((numbers_remaining3[1:6]), 2):
if 36 < numbers_remaining3[0] + sum(corner) < 39:
corner4 = (numbers_remaining3[0], corner[0], corner[1])
if sum(corner1) + sum(corner4) ==75:
if corner4[0] + corner4[1] != 25:
if corner4[0] + corner4[1] != 25:
if corner4[1] + corner4[2] != 25:
corner5 = (25 - corner4[0], 25 - corner4[1], 25 - corner4[2])
corner_combinations += 1
print (corner_combinations, corner1, corner2, corner3, corner4, corner5, corner6, corner7, corner8)
产生这个:
2 (1, 14, 22) (2, 16, 20) (4, 15, 18) (6, 13, 19) (19, 12, 6) (21, 10, 7) (23, 9, 5) (24, 11, 3)
3 (1, 14, 22) (2, 17, 19) (4, 13, 20) (7, 15, 16) (18, 10, 9) (21, 12, 5) (23, 8, 6) (24, 11, 3)
4 (1, 14, 22) (2, 17, 19) (4, 15, 18) (5, 13, 20) (20, 12, 5) (21, 10, 7) (23, 8, 6) (24, 11, 3)
5 (1, 14, 23) (3, 15, 19) (4, 16, 18) (5, 12, 20) (20, 13, 5) (21, 9, 7) (22, 10, 6) (24, 11, 2)
6 (1, 14, 23) (3, 16, 18) (4, 15, 19) (5, 12, 20) (20, 13, 5) (21, 10, 6) (22, 9, 7) (24, 11, 2)
7 (1, 15, 21) (2, 17, 19) (3, 14, 20) (7, 13, 18) (18, 12, 7) (22, 11, 5) (23, 8, 6) (24, 10, 4)
8 (1, 15, 21) (2, 17, 19) (3, 16, 18) (5, 13, 20) (20, 12, 5) (22, 9, 7) (23, 8, 6) (24, 10, 4)
9 (1, 15, 22) (2, 14, 21) (5, 16, 17) (6, 12, 19) (19, 13, 6) (20, 9, 8) (23, 11, 4) (24, 10, 3)
10 (1, 15, 22) (2, 14, 21) (5, 16, 17) (6, 13, 18) (19, 12, 7) (20, 9, 8) (23, 11, 4) (24, 10, 3)
11 (1, 15, 22) (2, 16, 19) (4, 14, 20) (7, 12, 18) (18, 13, 7) (21, 11, 5) (23, 9, 6) (24, 10, 3)
12 (1, 15, 22) (2, 16, 19) (4, 14, 20) (7, 13, 17) (18, 12, 8) (21, 11, 5) (23, 9, 6) (24, 10, 3)
13 (1, 15, 22) (2, 17, 18) (4, 14, 20) (6, 12, 19) (19, 13, 6) (21, 11, 5) (23, 8, 7) (24, 10, 3)
14 (1, 16, 20) (2, 14, 22) (4, 15, 18) (6, 13, 19) (19, 12, 6) (21, 10, 7) (23, 11, 3) (24, 9, 5)
15 (1, 16, 21) (2, 13, 22) (5, 15, 18) (6, 14, 17) (19, 11, 8) (20, 10, 7) (23, 12, 3) (24, 9, 4)
16 (1, 16, 21) (2, 15, 20) (3, 17, 18) (6, 12, 19) (19, 13, 6) (22, 8, 7) (23, 10, 5) (24, 9, 4)
17 (1, 16, 21) (2, 17, 18) (3, 15, 20) (6, 12, 19) (19, 13, 6) (22, 10, 5) (23, 8, 7) (24, 9, 4)
18 (1, 17, 19) (2, 14, 22) (4, 13, 20) (7, 15, 16) (18, 10, 9) (21, 12, 5) (23, 11, 3) (24, 8, 6)
19 (1, 17, 19) (2, 14, 22) (4, 15, 18) (5, 13, 20) (20, 12, 5) (21, 10, 7) (23, 11, 3) (24, 8, 6)
20 (1, 17, 19) (2, 15, 21) (3, 14, 20) (7, 13, 18) (18, 12, 7) (22, 11, 5) (23, 10, 4) (24, 8, 6)
21 (1, 17, 19) (2, 15, 21) (3, 16, 18) (5, 13, 20) (20, 12, 5) (22, 9, 7) (23, 10, 4) (24, 8, 6)
22 (1, 17, 20) (2, 13, 22) (4, 15, 19) (7, 14, 16) (18, 11, 9) (21, 10, 6) (23, 12, 3) (24, 8, 5)
23 (1, 17, 20) (2, 14, 21) (3, 16, 19) (7, 12, 18) (18, 13, 7) (22, 9, 6) (23, 11, 4) (24, 8, 5)
24 (1, 17, 20) (2, 16, 19) (3, 14, 21) (7, 12, 18) (18, 13, 7) (22, 11, 4) (23, 9, 6) (24, 8, 5)
25 (1, 18, 19) (2, 14, 21) (3, 15, 20) (8, 12, 17) (17, 13, 8) (22, 10, 5) (23, 11, 4) (24, 7, 6)
26 (1, 18, 19) (2, 14, 21) (3, 15, 20) (8, 13, 16) (17, 12, 9) (22, 10, 5) (23, 11, 4) (24, 7, 6)
27 (1, 18, 19) (2, 15, 20) (3, 14, 21) (8, 12, 17) (17, 13, 8) (22, 11, 4) (23, 10, 5) (24, 7, 6)
28 (1, 18, 19) (2, 15, 20) (3, 14, 21) (8, 13, 16) (17, 12, 9) (22, 11, 4) (23, 10, 5) (24, 7, 6)
所以有 697 个边组合,但只有 28 个角组合。
我现在需要做的就是以某种方式将一个与另一个进行比较。问题是每个边或角的位置都是可移动的。
我以不同的方式解决了您的问题,但您可以调整它的各个方面以供您自己使用。希望这可以作为这里的答案,因为它 应该 解决问题,但我不知道如何找到满足您条件的多维数据集,除非通过蛮力。如果您已经有一些候选人,您可以稍微修改代码以仅处理这些候选人。
总的来说,代码就像筛子一样工作。我选择使用 filter()
来完成繁重的工作,而不是嵌套的 for 循环。这种方法的优点是更容易通过代码进行推理,可以通过编写过滤器函数来创建新规则,并且以后可以轻松地重新排序过滤器以提高性能。
为了使代码有意义,您需要参考这张地图。每个候选组合都是一个包含 24 个元素的元组,因此索引从 0 到 23。A = 0,B = 1,C = 2,...,X = 23。我已经仔细检查了所有过滤器函数使用正确的索引,但您可能需要仔细检查。
编辑:我已经根据您的修正更正了对函数,并将组合更改为排列。由于每个数字都映射到立方体上的特定位置,因此顺序很重要。这就是为什么 combinations(range(1,25), 24) 只产生一个组合。只有一组无序的 24 个数字包含数字 1 到 24。这次我也手动创建了过滤器链,因为链接功能似乎不适用于这种情况。
+-----+
| A B |
| C D |
+-----+-----+-----+-----+
| E F | G H | I J | K L |
| M N | O P | Q R | S T |
+-----+-----+-----+-----+
| U V |
| W X |
+-----+
from itertools import permutations
# Filter functions
# ------------
# All corners are 37 or 38
def check_corners(lst):
print(".")
corners = [lst[5] + lst[6] + lst[2],
lst[3] + lst[7] + lst[8],
lst[13] + lst[14] + lst[20],
lst[21] + lst[15] + lst[16],
lst[12] + lst[22] + lst[19],
lst[23] + lst[17] + lst[6],
lst[1] + lst[9] + lst[10],
lst[0] + lst[4] + lst[11]]
return all(36 < corner < 39 for corner in corners)
# All sides add to 50
def check_sides(lst):
sides = [lst[0] + lst[1] + lst[2] + lst[3],
lst[4] + lst[5] + lst[12] + lst[13],
lst[6] + lst[7] + lst[14] + lst[15],
lst[8] + lst[9] + lst[16] + lst[17],
lst[10] + lst[11] + lst[18] + lst[19],
lst[20] + lst[21] + lst[22] + lst[23]]
return all(side == 50 for side in sides)
# All opposites add to 25
def check_opposites(lst):
print(lst)
opposites = [lst[0] + lst[22],
lst[2] + lst[20],
lst[1] + lst[23],
lst[3] + lst[21],
lst[5] + lst[8],
lst[4] + lst[9],
lst[12] + lst[17],
lst[13] + lst[16],
lst[7] + lst[10],
lst[6] + lst[11],
lst[15] + lst[18],
lst[14] + lst[19]]
return all(pair == 25 for pair in opposites)
# No pairs on a side add to 25
def check_pairs(lst):
pairs = [lst[0] + lst[1], lst[2] + lst[3],
lst[0] + lst[2], lst[1] + lst[3],
lst[0] + lst[3], lst[1] + lst[2],
lst[4] + lst[5], lst[12] + lst[13],
lst[4] + lst[12], lst[5] + lst[13],
lst[4] + lst[13], lst[5] + lst[12],
lst[6] + lst[7], lst[14] + lst[15],
lst[6] + lst[14], lst[7] + lst[15],
lst[6] + lst[15], lst[7] + lst[14],
lst[8] + lst[9], lst[16] + lst[17],
lst[8] + lst[16], lst[9] + lst[17],
lst[8] + lst[17], lst[9] + lst[16],
lst[10] + lst[11], lst[18] + lst[19],
lst[10] + lst[18], lst[11] + lst[19],
lst[10] + lst[19], lst[11] + lst[18],
lst[20] + lst[21], lst[22] + lst[23],
lst[20] + lst[22], lst[21] + lst[23],
lst[20] + lst[23], lst[21] + lst[22]]
return all(pair != 25 for pair in pairs)
candidates = permutations(range(1,25), 24)
cubes = filter(check_pairs,
filter(check_corners,
filter(check_corners,
filter(check_sides, candidates))))
for cube in cubes:
print(cube)
此代码的作用:
permutations
以所有可能的顺序生成从 1 到 24 的 24 个整数元组的迭代器。这意味着它将像一个可能的候选立方体列表一样,但只在被询问时而不是事先创建每个元组。这限制了内存使用。每个组合就像 (n1, n2, n3, ... n24)。这个元组的每个成员对应于你的多维数据集上的一个数字。
- 链式过滤器就像筛子一样工作。它从最里面的过滤器开始,然后开始工作。每个内部过滤器仅传递满足过滤函数所有条件的排列。
- 如果括号内的所有比较都是
True
,all()
所做的就是returnTrue
。括号内的表达式称为 generator expression.
cubes
包含一个链式迭代器,它按照您在列表中看到的顺序检查条件。如果您确定哪些消除了最多的候选立方体,则可以提高性能。您在链的开头淘汰的候选人越多,在他们身上浪费的时间就越少。
for
循环是第一次任何检查代码是 运行,因为当循环向 cubes
询问某个项目时,cubes
必须询问filter(check_pairs, ...)
这还得一路问filter(check_sides, ...)
。因此,check_sides
是最深层次,这意味着实际执行的是 第一次 比较。
- 每次
cubes
吐出一个元组,其值满足过滤函数指定的所有条件,for循环将其打印出来。
最后,如果您跟踪已经尝试了多少组合并且程序崩溃或您必须暂停,请查看 here 以获取如何跳至可迭代项的第 n 项的示例,在这种情况下是 combinations()
。
为了清楚起见,将其添加为答案而不是再次编辑问题。
因此,使用我的边角代码,我 运行 对我创建的 2 个列表(边角和边)进行了列表比较。
代码现在似乎可以工作了。它很乱,但它有效(我认为)
感谢您的帮助。
from itertools import combinations
# program to distribute 24 numbers across the 6 sides of a cube
# there will be 4 numbers to a side
# and 3 numbers at each corner where 3 sides meet
# every number and its physical opposite must sum to 25.
# this means only the 1st 4 corners and 3 sides have to be worked out.
# as the opposites will automatically obey the rules.
# no pairs of numbers in a corner or on a side may equal 25
# the sum of a side must equal 50
# the sum of a corner must equal 37 or 38
# the sum of 2 corners connected by an edge must equal 75
# corners opposite each other on a side must be equal
corner_combinations = 0 # a simple counter
side_combinations = 0 # a simple counter
side_numbers_all = list(range(1,25)) # list of all numbers from 1 to 24
corner_numbers_all = list(range(1,25)) # list of all numbers from 1 to 24
# find the first corner
for corner_a in combinations((corner_numbers_all[1:24]), 2): # find combinations of 2 numbers from 2 to 23 (not using 1 or 24 as 1 is the first constant, and 24 is its direct opposite)
if 36 < corner_numbers_all[0] + sum(corner_a) < 39: # check if the corner using 1 (the constant mentiined above) and the pair of numbers from the combination sum to 37 or 38
corner1 = (corner_numbers_all[0], corner_a[0], corner_a[1]) # create a new corner list with the constant and the combination
if 25 not in (corner1[0] + corner1[1], corner1[0] + corner1[2], corner1[1] + corner1[2]): # check that all possible pairings in the new list do not sum to 25
corner8 = (25 - corner1[0], 25 - corner1[1], 25 - corner1[2]) # create a new corner list that is the opposite of the current list.
corner_numbers_remaining = list(set(corner_numbers_all) - set(corner1) - set(corner8)) # create a new list of numbers from the 1st list minus the 2 corner lists just created
# find the second corner, rules as above
for corner_b in combinations((corner_numbers_remaining[1:18]), 2):
if 36 < corner_numbers_remaining[0] + sum(corner_b) < 39:
corner2 = (corner_numbers_remaining[0], corner_b[0], corner_b[1])
if sum(corner1) + sum(corner2) == 75: # checks to see if the sum of the first and second corners is 75
if 25 not in (corner2[0] + corner2[1], corner2[0] + corner2[2], corner2[1] + corner2[2]):
corner7 = (25 - corner2[0], 25 - corner2[1], 25 - corner2[2])
corner_numbers_remaining2 = list(set(corner_numbers_remaining) - set(corner2) - set(corner7))
# find third corner, as abive
for corner_c in combinations((corner_numbers_remaining2[1:12]), 2):
if 36 < corner_numbers_remaining2[0] + sum(corner_c) < 39:
corner3 = (corner_numbers_remaining2[0], corner_c[0], corner_c[1])
if sum(corner3) == sum(corner1): # check to see if the sum of the first corner is the same as the sum of the third corner
if (corner3[0] + corner3[1] and corner3[0] + corner3[2] and corner3[1] + corner3[2]) != 25:
corner6 = (25 - corner3[0], 25 - corner3[1], 25 - corner3[2])
corner_numbers_remaining3 = list(set(corner_numbers_remaining2) - set(corner3) - set(corner6))
# find fourth corner, as per second corner
for corner_d in combinations((corner_numbers_remaining3[1:6]), 2):
if 36 < corner_numbers_remaining3[0] + sum(corner_d) < 39:
corner4 = (corner_numbers_remaining3[0], corner_d[0], corner_d[1])
if sum(corner1) + sum(corner4) ==75:
if (corner4[0] + corner4[1] and corner4[0] + corner4[1] and corner4[1] + corner4[2]) != 25:
corner5 = (25 - corner4[0], 25 - corner4[1], 25 - corner4[2])
corner_combinations += 1 # count how many combinations of corners meet the criteria.
# find first side, as per first corner
for side_a in combinations((side_numbers_all[1:24]),3): # 3 number combination this time, still dropping 1 and 24
if side_numbers_all[0] + sum(side_a) == 50: # check constant and combination sum to 50
if 25 not in (side_numbers_all[0] + side_a[0], side_numbers_all[0] + side_a[1], side_numbers_all[0] + side_a[2], side_a[0] + side_a[1], side_a[0] + side_a[2], side_a[1] + side_a[2]): # check no pairs of numbers sum to 25
side1 = (side_numbers_all[0], side_a[0], side_a[1], side_a[2]) # createvfirst side list
if len(set(side1).intersection(corner1)) <= 1 and len(set(side1).intersection(corner2)) <= 1 and len(set(side1).intersection(corner3)) <= 1 and len(set(side1).intersection(corner4)) <= 1 and len(set(side1).intersection(corner5)) <= 1 and len(set(side1).intersection(corner6)) <= 1 and len(set(side1).intersection(corner7)) <= 1 and len(set(side1).intersection(corner8)) <= 1: # check first side against all corners. Each number in side may only exist in one corner.
side6 = (25-side1[0], 25-side1[1], 25-side1[2], 25-side1[3]) # create the opposite side
# find second side as above
side_numbers_remaining = list(set(side_numbers_all) - set(side1) - set(side6))
for side_b in combinations(side_numbers_remaining[1:16],3):
if side_numbers_remaining[0] + sum(side_b) == 50:
if 25 not in (side_numbers_remaining[0] + side_b[0], side_numbers_remaining[0] + side_b[1], side_numbers_remaining[0] + side_b[2], side_b[0] + side_b[1], side_b[0] + side_b[2], side_b[1] + side_b[2]):
side2 = (side_numbers_remaining[0], side_b[0], side_b[1], side_b[2])
if len(set(side2).intersection(corner1)) <= 1 and len(set(side2).intersection(corner2)) <= 1 and len(set(side2).intersection(corner3)) <= 1 and len(set(side2).intersection(corner4)) <= 1 and len(set(side2).intersection(corner5)) <= 1 and len(set(side2).intersection(corner6)) <= 1 and len(set(side2).intersection(corner7)) <= 1 and len(set(side2).intersection(corner8)) <= 1:
side5 = (25-side2[0], 25-side2[1], 25-side2[2], 25-side2[3])
side_numbers_remaining2 = list(set(side_numbers_remaining) - set(side2) - set(side5))
for side_c in combinations(side_numbers_remaining2[1:8],3):
if side_numbers_remaining2[0] + sum(side_c) == 50:
if 25 not in (side_numbers_remaining2[0] + side_c[0], side_numbers_remaining2[0] + side_c[1], side_numbers_remaining2[0] + side_c[2], side_c[0] + side_c[1], side_c[0] + side_c[2], side_c[1] + side_c[2]):
side3 = (side_numbers_remaining2[0], side_c[0], side_c[1], side_c[2])
if len(set(side3).intersection(corner1)) <= 1 and len(set(side3).intersection(corner2)) <= 1 and len(set(side3).intersection(corner3)) <= 1 and len(set(side3).intersection(corner4)) <= 1 and len(set(side3).intersection(corner5)) <= 1 and len(set(side3).intersection(corner6)) <= 1 and len(set(side3).intersection(corner7)) <= 1 and len(set(side3).intersection(corner8)) <= 1:
side4 = (25-side3[0], 25-side3[1], 25-side3[2], 25-side3[3])
side_combinations += 1 # count how many sides combinations meet the criteria
# print result
print ("corner combinations:", corner_combinations)
print (corner1,"=", sum(corner1), corner2,"=", sum(corner2), corner3,"=", sum(corner3), corner4,"=", sum(corner4), corner5,"=", sum(corner5), corner6,"=", sum(corner6), corner7,"=", sum(corner7), corner8,"=", sum(corner8))
print ("side combinations:", side_combinations)
print (side1,"=", sum(side1), side2,"=", sum(side2), side3,"=", sum(side3), side4,"=", sum(side4), side5,"=", sum(side5), side6,"=", sum(side6))
我刚刚重新开始这个项目 - 在我恢复我的 SOF 帐户之前,我已经忘记了以上所有内容。
我认为,我同时创建的是一种破解此问题的蛮力尝试。该代码大约需要 5-10 分钟才能完成并产生一个组合。
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 21:26:53) [MSC v.1916 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>>
====================== RESTART: C:\Users\escri\face1.py ======================
1: [1, 12, 16, 21][18, 10, 3, 19][11, 17, 20, 2][23, 5, 8, 14][6, 22, 15, 7][4, 9, 13, 24]
There are 1 combinations
>>>
代码如下:
r = range(2, 23) # +-------------+-------------+-------------+
n = 0 # | C6:2--------| F2:0 F2:1 |--------C5:2 |
# | | F6:1 | C6:1 C5:1 | F6:0 | |
f1 = [1,0,0,0] # | | | | | |
f2 = [0,0,0,0] # | | | F2:3 F2:2 | | |
f3 = [0,0,0,0] # | | | C1:1 C2:1 | | |
f4 = [0,0,0,0] # +-------------+-------------+-------------+
f5 = [0,0,0,0] # | F3:0 F3:1 | F1:0 F1:1 | F4:0 F4:1 |
f6 = [0,0,0,24] # | C6:0 C1:2 | C1:0 C2:0 | C2:2 C5:0 |
# | | | |
c1 = [1,0,0] # | F3:3 F3:2 | F1:3 F1:2 | F4:3 F4:2 |
c2 = [0,0,0] # | C7:0 C4:2 | C4:0 C3:0 | C3:2 C8:0 |
c3 = [0,0,0] # +-------------+-------------+-------------+
c4 = [0,0,0] # | | | F5:2 F5:3 | | |
c5 = [0,0,0] # | | | C4:1 C3:1 | | |
c6 = [0,0,0] # | | | | | |
c7 = [0,0,0] # | | F6:2 | F5:1 F5:0 | F6:3 | |
c8 = [0,0,24] # | C7:2--------| C7:1 C8:1 |--------C8:2 |
# +-------------+-------------+-------------+
for xa in r:
f1[1] = xa
f6[2] = 25 - xa
for ya in r:
if ya != xa and ya + xa != 25:
f1[2] = ya
f6[1] = 25 - ya
for za in r:
if za != xa and za + xa != 25 and za != ya and za + ya != 25:
f1[3] = za
f6[0] = 25 - za
if sum(f1) == 50:
c2[0] = f1[1]
c7[2] = f6[2]
c3[0] = f1[2]
c6[2] = f6[1]
c4[0] = f1[3]
c5[2] = f6[0]
for wb in r:
if wb not in f1 and wb not in f6:
f2[0] = wb
f5[3] = 25 - wb
for xb in r:
if xb not in f1 and xb not in f6 and xb != wb and xb + wb != 25:
f2[1] = xb
f5[2] = 25 - xb
for yb in r:
if yb not in f1 and yb not in f6 and yb != wb and yb + wb !=25 and yb != xb and yb + xb != 25:
f2[2] = yb
f5[1] = 25 - yb
for zb in r:
if zb not in f1 and zb not in f6 and zb != wb and zb + wb !=25 and zb != xb and zb + xb != 25 and zb != yb and zb + yb != 25:
f2[3] = zb
f5[0] = 25 - zb
if sum(f2) == 50:
c6[1] = f2[0]
c3[1] = f5[3]
c5[1] = f2[1]
c4[1] = f5[2]
c2[1] = f2[2]
c7[1] = f5[1]
c1[1] = f2[3]
c8[1] = f5[0]
for wc in r:
if wc not in f1 and wc not in f2 and wc not in f5 and wc not in f6:
f3[0] = wc
f4[3] = 25 - wc
for xc in r:
if xc not in f1 and xc not in f2 and xc not in f5 and xc not in f6 and xc != wc and xc + wc != 25:
f3[1] = xc
f4[2] = 25 - xc
for yc in r:
if yc not in f1 and yc not in f2 and yc not in f5 and yc not in f6 and yc != wc and yc + wc != 25 and yc != xc and yc + xc != 25:
f3[2] = yc
f4[1] = 25 - yc
for zc in r:
if zc not in f1 and zc not in f2 and zc not in f5 and zc not in f6 and zc != wc and zc + wc != 25 and zc != xc and zc + xc != 25 and zc != yc and zc + yc != 25:
f3[3] = zc
f4[0] = 25 - zc
if sum(f3) == 50:
c6[0] = f3[0]
c3[2] = f4[3]
c1[2] = f3[1]
c8[0] = f4[2]
c7[0] = f3[2]
c5[0] = f4[1]
c4[2] = f3[3]
c2[2] = f4[0]
if sum(c1) == 37 or sum(c1) == 38:
if sum(c1) + sum(c2) == 75 and sum(c1) + sum(c4) == 75 and sum(c1) == sum(c3) and sum(c1) + sum(c8) == 75:
n += 1
print(f"{n}: {f1}{f2}{f3}{f4}{f5}{f6}")
print(f"There are {n} combinations")
编辑以更新我的代码并对 @MOHAMMED
给予完整回应图片,如果你愿意的话,一个立方体。该立方体的每个面都有一组 4 个数字。立方体上的每个数字只出现一次。
到目前为止,在此处的一些帮助下,我已经设法编写了一个程序,将这 24 个数字过滤到一个列表中,其中 4 个数字的每个面总计 50,没有一对面总计 25,但每个数字它正好相反(物理上)总共 25.
我现在的问题是边角。我有一条规则要应用到他们身上。每个角相交的 3 个数字的总和必须是 37 或 38。还有一些其他规则,但现在让我们坚持下去。
现在,就像骰子一样,相反的数字总和相同。这意味着,对于所有意图,我的每个组都有一个对立面,因此,它永远不会与之相邻。
所以我的程序吐出了第一组符合我的标准的 6 张面孔。我现在如何算出角落?
我意识到我只需要处理 6 个面孔中的 3 个面孔,因为每个数字都与总数 25 的对面配对,一旦一个角符合规则,它的对面也应该这样做。
我已经针对这个问题简化了我的代码。
group1 = list(['A','B','E','F'])
group2 = list(['A','D','E','G'])
group3 = list(['A','B','C','D'])
group4 = list(['E','F','G','H'])
group5 = list(['B','C','F','H'])
group6 = list(['C','D','G','H'])
for a in group1:
for b in group2:
for c in group3:
for corner1 in itertools.combinations((a,b,c),3):
if (a == b == c):
print (corner1)
给予
('A','A','A')
假设没有匹配,那么在1,2,3之后还有另外两个可能的分组组合;那些是 1,3,5 和 1,4,5。
我认为使用 1 作为所有其他配对的常量可以使其更简单。
我有两个问题,首先,假设我们的第一个匹配项只出现在最后一组组合中,那么编写代码的最佳方式是什么?
for a in group1:
for b in group2:
for c in group3:
for d in group4:
for e in group5:
for f in group6:
for corner1 in itertools.combinations((a,b,c),3):
else:
for corner1 in itertools.combinations((a,b,d),3):
else:
for corner1 in itertools.combinations((a,d,e),3):
或:
for a in group1:
for b in group2:
for c in group3:
for corner1 in itertools.combinations((a,b,c),3):
else for a in group1:
for b in group2:
for c in group4:
for corner1 in itertools.combinations((a,b,d),3):
else for a in group1:
for b in group2:
for c in group3:
for corner1 in itertools.combinations((a,d,e),3):
即使这些代码中的任何一个都可行(我对这两个代码都有疑问,因为我是新手),然后我需要从与同一组的进一步匹配中删除这些数字并保留顺序的组。
例如,如果规则的第一位选择组合 1、2、4,我如何确保后续查询仅在该条件为真时才有效(这有意义吗?)
这是我到目前为止的完整代码.... 已编辑
n = 0
cnr1 = 0
cnr2 = 0
cnr3 = 0
cnr4 = 0
faces_all = list(range(1,25))
for x in itertools.combinations((faces_all[1:24]),3):
if faces_all[0] + sum(x) == 50:
side1 = (faces_all[0], x[0], x[1], x[2])
for pair in itertools.combinations(side1, 2):
if sum(pair) == 25:
break
else:
side6 = (25-side1[0], 25-side1[1], 25-side1[2], 25-side1[3])
faces_remaining = list(set(faces_all) - set(side1) - set(side6))
for y in itertools.combinations(faces_remaining,4):
if sum(y) == 50:
side2 = y
for pair in itertools.combinations(side2,2):
if sum(pair) == 25:
break
else:
side5 = (25-side2[0], 25-side2[1], 25-side2[2], 25-side2[3])
faces_last = list(set(faces_remaining) - set(side2) - set(side5))
for z in itertools.combinations(faces_last,4):
if sum(z) == 50:
side3 = z
for pair in itertools.combinations(side3,2):
if sum(pair) == 25:
break
else:
side4 = (25-side3[0], 25-side3[1], 25-side3[2], 25-side3[3])
for a in side2:
for b in side3:
for c in side4:
for d in side5:
for top in itertools.permutations(side1,4):
for corner1 in itertools.combinations((top[0],a,b),3):
if (sum(corner1) == 37 or sum(corner1) == 38):
corner8 = (25-top[0],25-a,25-b)
cnr1 += 1
print ("1&8",cnr1,"2&7",cnr2,"3&6",cnr3)
for corner2 in itertools.combinations((top[1],b,d),3):
#if (b not in corner1 and sum(corner1) + sum(corner2) == 75):
if sum(corner1) + sum(corner2) == 75:
corner7 = (25-top[1],25-b,25-d)
cnr2 += 1
print ("1&8",cnr1,"2&7",cnr2,"3&6",cnr3)
for corner3 in itertools.combinations((top[2],d,c),3):
#if (d not in corner1 and sum(corner3) == sum(corner1)):
if sum(corner3) == sum(corner1):
corner6 = (25-top[2],25-d,25-c)
cnr3 += 1
print ("1&8",cnr1,"2&7",cnr2,"3&6",cnr3)
for corner4 in itertools.combinations((top[2],c,a),3):
#if (c not in corner3 and a not in corner1 and sum(corner4) + sum(corner1) == 75):
if sum(corner4) + sum(corner1) == 75:
corner5 = (25-top[2],25-c,25-a)
print ("1&8",cnr1,"2&7",cnr2,"3&6",cnr3)
print (n)
print ("sides:", side1, side2, side3, side4, side5, side6)
print ("corners:", corner1, corner2, corner3, corner4, corner5, corner6)
输出(从开始到代码停止无误)是:
1&8 1 2&7 0 3&6 0
...
1&8 8109504 2&7 213792 3&6 5558
所以角 1&8 有 800 万次命中,1&8 和 2&7 只有 200,000 次,1&8、2&7 和 3&6 只有 5,000 次——但没有包括 4&5)。
这表明我无法实现(这是可能的),或者我的代码有问题。
尝试图表使其更清晰:
A____________B
|\A B:\
|A\ :B\
| \ : \
| \D______:__C\C
| D|D : C|
E|E | F:F |
\```|````````. |
\ | . |
\H| .|
\|H_________G|G
H G
+-----+
| E F |
| A B |
+-----+-----+-----+-----+
| E A | A B | B F | F E |
| H G | D C | C G | G H |
+-----+-----+-----+-----+
| D c |
| H G |
+-----+
+----------------------+
|Ee fF|
| +--+----------+--+ |
| |37|e 50 f|38| |
| +--+--+ +--+--+ |`
| |E |38|a b|37| F| |
| | +--+----+--+ | |
| | Aa|A B|bB | |
| | 50 | 50 | 50 | |
| | Dd|D C|cC | |
| | +--+----+--+ | |
| |H |37|d c|38| G| |
| +--+--+ 50 +--+--+ |
| |38|h g|37| |
| +--+----------+--+ |
|Hh gG|
+----------------------+
====================================== ===================================
响应 @Mohammed's 代码
from itertools import combinations
# Filter functions
# ------------
## All sides add to 50
def check_sides(lst):
sides = [lst[0] + lst[1] + lst[2] + lst[3],
lst[4] + lst[5] + lst[12] + lst[13],
lst[6] + lst[7] + lst[14] + lst[15],
lst[8] + lst[9] + lst[16] + lst[17],
lst[10] + lst[11] + lst[18] + lst[19],
lst[20] + lst[21] + lst[22] + lst[23]]
return all(side == 50 for side in sides)
# All corners are 37 or 38
def check_corners(lst):
print(".")
corners = [lst[5] + lst[6] + lst[2],
lst[3] + lst[7] + lst[8],
lst[13] + lst[14] + lst[20],
lst[21] + lst[15] + lst[16],
lst[12] + lst[22] + lst[19],
lst[23] + lst[17] + lst[6],
lst[1] + lst[9] + lst[10],
lst[0] + lst[4] + lst[11]]
return all(36 < corner < 39 for corner in corners)
# All opposites add to 25
def check_opposites(lst):
print(lst)
opposites = [lst[0] + lst[22],
lst[2] + lst[20],
lst[1] + lst[23],
lst[3] + lst[21],
lst[5] + lst[8],
lst[4] + lst[9],
lst[12] + lst[17],
lst[13] + lst[16],
lst[7] + lst[10],
lst[6] + lst[11],
lst[15] + lst[18],
lst[14] + lst[19]]
return all(pair == 25 for pair in opposites)
# No pairs on a side add to 25
def check_pairs(lst):
pairs = [lst[0] + lst[1], lst[2] + lst[3],
lst[0] + lst[2], lst[1] + lst[3],
lst[0] + lst[3], lst[1] + lst[2],
lst[4] + lst[5], lst[12] + lst[13],
lst[4] + lst[12], lst[5] + lst[13],
lst[4] + lst[13], lst[5] + lst[12],
lst[6] + lst[7], lst[14] + lst[15],
lst[6] + lst[14], lst[7] + lst[15],
lst[6] + lst[15], lst[7] + lst[14],
lst[8] + lst[9], lst[16] + lst[17],
lst[8] + lst[16], lst[9] + lst[17],
lst[8] + lst[17], lst[9] + lst[16],
lst[10] + lst[11], lst[18] + lst[19],
lst[10] + lst[18], lst[11] + lst[19],
lst[10] + lst[19], lst[11] + lst[18],
lst[20] + lst[21], lst[22] + lst[23],
lst[20] + lst[22], lst[21] + lst[23],
lst[20] + lst[23], lst[21] + lst[22]]
return all(pair != 25 for pair in pairs)
# Everything else
# ---------------
def nFilter(filters, iterable):
for f in filters:
iterable = filter(f, iterable)
return iterable
candidates = combinations(range(1,50), 24)
#cubes = nFilter([check_sides, check_corners, check_opposites, check_pairs], candidates)
cubes = nFilter([check_sides],candidates)
for cube in cubes:
print(cube)
我在每张脸上添加了缺失的 "pairs"(对于 4 个数字,有 6 种可能的组合对(AB、AC、AD、BC、BD、CD)。
我重新安排了检查的顺序,首先执行参数最少的检查。
但我不理解输出,它似乎只是在不应用过滤器的情况下打印从 1 到 n 的 24 个数字的所有组合。
将 combinations(range(1,50)
更改为 combinations(range(1,26)
会产生以下输出,并将其更改为 combinations(range(1,25)
(这样只会使用我想使用的数字 (1-24) 只会产生下面第一行输出。
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
====================================== ===================================
添加更多代码:
我有以下 2 个充满丑陋 if 语句的程序,但希望它们能正常工作。
所以我有
face_combinations = 0
faces_all = list(range(1,25))
for side in combinations((faces_all[1:24]),3):
if faces_all[0] + sum(side) == 50:
if faces_all[0] + side[0] != 25:
if faces_all[0] + side[1] != 25:
if faces_all[0] + side[2] != 25:
if side[0] + side[1] != 25:
if side[0] + side[2] != 25:
if side[1] + side[2] != 25:
side1 = (faces_all[0], side[0], side[1], side[2])
side6 = (25-side1[0], 25-side1[1], 25-side1[2], 25-side1[3])
faces_remaining = list(set(faces_all) - set(side1) - set(side6))
for side in combinations(faces_remaining[1:16],4):
if faces_remaining[0] + sum(side) == 50:
if faces_remaining[0] + side[0] != 25:
if faces_remaining[0] + side[1] != 25:
if faces_remaining[0] + side[2] != 25:
if side[0] + side[1] != 25:
if side[0] + side[2] != 25:
if side[1] + side[2] != 25:
side2 = (faces_remaining[0], side[0], side[1], side[2])
side5 = (25-side2[0], 25-side2[1], 25-side2[2], 25-side2[3])
faces_last = list(set(faces_remaining) - set(side2) - set(side5))
for side in combinations(faces_last[1:8],4):
if faces_last[0] + sum(side) == 50:
if faces_last[0] + side[0] != 25:
if faces_last[0] + side[1] != 25:
if faces_last[0] + side[2] != 25:
if side[0] + side[1] != 25:
if side[0] + side[2] != 25:
if side[1] + side[2] != 25:
side3 = (faces_last[0], side[0], side[1], side[2])
side4 = (25-side2[0], 25-side2[1], 25-side2[2], 25-side2[3])
face_combinations += 1
print (face_combinations, side1, side2, side3, side4, side5, side6)
产生:
2 (1, 4, 22, 23) (5, 6, 9, 12) (7, 8, 10, 11) (20, 19, 16, 13) (20, 19, 16, 13) (24, 21, 3, 2)
3 (1, 4, 22, 23) (5, 6, 9, 13) (7, 8, 10, 11) (20, 19, 16, 12) (20, 19, 16, 12) (24, 21, 3, 2)
4 (1, 4, 22, 23) (5, 6, 9, 14) (7, 8, 10, 12) (20, 19, 16, 11) (20, 19, 16, 11) (24, 21, 3, 2)
5 (1, 4, 22, 23) (5, 6, 11, 12) (7, 8, 9, 10) (20, 19, 14, 13) (20, 19, 14, 13) (24, 21, 3, 2)
6 (1, 4, 22, 23) (5, 6, 11, 13) (7, 8, 9, 10) (20, 19, 14, 12) (20, 19, 14, 12) (24, 21, 3, 2)
7 (1, 4, 22, 23) (5, 7, 8, 11) (6, 9, 10, 12) (20, 18, 17, 14) (20, 18, 17, 14) (24, 21, 3, 2)
8 (1, 4, 22, 23) (5, 7, 8, 12) (6, 9, 10, 11) (20, 18, 17, 13) (20, 18, 17, 13) (24, 21, 3, 2)
9 (1, 4, 22, 23) (5, 7, 8, 13) (6, 9, 10, 11) (20, 18, 17, 12) (20, 18, 17, 12) (24, 21, 3, 2)
10 (1, 4, 22, 23) (5, 7, 8, 14) (6, 9, 10, 12) (20, 18, 17, 11) (20, 18, 17, 11) (24, 21, 3, 2)
...
691 (1, 15, 16, 18) (2, 3, 5, 19) (4, 8, 11, 13) (23, 22, 20, 6) (23, 22, 20, 6) (24, 10, 9, 7)
692 (1, 15, 16, 18) (2, 4, 8, 13) (3, 5, 6, 14) (23, 21, 17, 12) (23, 21, 17, 12) (24, 10, 9, 7)
693 (1, 15, 16, 18) (2, 4, 11, 12) (3, 5, 6, 17) (23, 21, 14, 13) (23, 21, 14, 13) (24, 10, 9, 7)
694 (1, 15, 16, 18) (2, 4, 11, 13) (3, 5, 6, 17) (23, 21, 14, 12) (23, 21, 14, 12) (24, 10, 9, 7)
695 (1, 15, 16, 18) (2, 4, 13, 14) (3, 5, 6, 17) (23, 21, 12, 11) (23, 21, 12, 11) (24, 10, 9, 7)
696 (1, 15, 16, 18) (2, 5, 6, 14) (3, 4, 8, 13) (23, 20, 19, 11) (23, 20, 19, 11) (24, 10, 9, 7)
697 (1, 15, 16, 18) (2, 6, 11, 12) (3, 4, 5, 17) (23, 19, 14, 13) (23, 19, 14, 13) (24, 10, 9, 7)
还有这个:
numbers_all = list(range(1,25))
corner_combinations = 0
for corner in combinations((numbers_all[1:24]), 2):
if 36 < numbers_all[0] + sum(corner) < 39:
corner1 = (numbers_all[0], corner[0], corner[1])
if corner1[0] + corner1[1] != 25:
if corner1[0] + corner1[2] != 25:
if corner1[1] + corner1[2] != 25:
corner8 = (25 - corner1[0], 25 - corner1[1], 25 - corner1[2])
numbers_remaining = list(set(numbers_all) - set(corner1) - set(corner8))
for corner in combinations((numbers_remaining[1:18]), 2):
if 36 < numbers_remaining[0] + sum(corner) < 39:
corner2 = (numbers_remaining[0], corner[0], corner[1])
if sum(corner1) + sum(corner2) ==75:
if corner2[0] + corner2[1] != 25:
if corner2[0] + corner2[2] != 25:
if corner2[1] + corner2[2] != 25:
corner7 = (25 - corner2[0], 25 - corner2[1], 25 - corner2[2])
numbers_remaining2 = list(set(numbers_remaining) - set(corner2) - set(corner7))
for corner in combinations((numbers_remaining2[1:12]), 2):
if 36 < numbers_remaining2[0] + sum(corner) < 39:
corner3 = (numbers_remaining2[0], corner[0], corner[1])
if sum(corner3) == sum(corner1):
if corner3[0] + corner3[1] != 25:
if corner3[0] + corner3[2] != 25:
if corner3[1] + corner3[2] != 25:
corner6 = (25 - corner3[0], 25 - corner3[1], 25 - corner3[2])
numbers_remaining3 = list(set(numbers_remaining2) - set(corner3) - set(corner6))
for corner in combinations((numbers_remaining3[1:6]), 2):
if 36 < numbers_remaining3[0] + sum(corner) < 39:
corner4 = (numbers_remaining3[0], corner[0], corner[1])
if sum(corner1) + sum(corner4) ==75:
if corner4[0] + corner4[1] != 25:
if corner4[0] + corner4[1] != 25:
if corner4[1] + corner4[2] != 25:
corner5 = (25 - corner4[0], 25 - corner4[1], 25 - corner4[2])
corner_combinations += 1
print (corner_combinations, corner1, corner2, corner3, corner4, corner5, corner6, corner7, corner8)
产生这个:
2 (1, 14, 22) (2, 16, 20) (4, 15, 18) (6, 13, 19) (19, 12, 6) (21, 10, 7) (23, 9, 5) (24, 11, 3)
3 (1, 14, 22) (2, 17, 19) (4, 13, 20) (7, 15, 16) (18, 10, 9) (21, 12, 5) (23, 8, 6) (24, 11, 3)
4 (1, 14, 22) (2, 17, 19) (4, 15, 18) (5, 13, 20) (20, 12, 5) (21, 10, 7) (23, 8, 6) (24, 11, 3)
5 (1, 14, 23) (3, 15, 19) (4, 16, 18) (5, 12, 20) (20, 13, 5) (21, 9, 7) (22, 10, 6) (24, 11, 2)
6 (1, 14, 23) (3, 16, 18) (4, 15, 19) (5, 12, 20) (20, 13, 5) (21, 10, 6) (22, 9, 7) (24, 11, 2)
7 (1, 15, 21) (2, 17, 19) (3, 14, 20) (7, 13, 18) (18, 12, 7) (22, 11, 5) (23, 8, 6) (24, 10, 4)
8 (1, 15, 21) (2, 17, 19) (3, 16, 18) (5, 13, 20) (20, 12, 5) (22, 9, 7) (23, 8, 6) (24, 10, 4)
9 (1, 15, 22) (2, 14, 21) (5, 16, 17) (6, 12, 19) (19, 13, 6) (20, 9, 8) (23, 11, 4) (24, 10, 3)
10 (1, 15, 22) (2, 14, 21) (5, 16, 17) (6, 13, 18) (19, 12, 7) (20, 9, 8) (23, 11, 4) (24, 10, 3)
11 (1, 15, 22) (2, 16, 19) (4, 14, 20) (7, 12, 18) (18, 13, 7) (21, 11, 5) (23, 9, 6) (24, 10, 3)
12 (1, 15, 22) (2, 16, 19) (4, 14, 20) (7, 13, 17) (18, 12, 8) (21, 11, 5) (23, 9, 6) (24, 10, 3)
13 (1, 15, 22) (2, 17, 18) (4, 14, 20) (6, 12, 19) (19, 13, 6) (21, 11, 5) (23, 8, 7) (24, 10, 3)
14 (1, 16, 20) (2, 14, 22) (4, 15, 18) (6, 13, 19) (19, 12, 6) (21, 10, 7) (23, 11, 3) (24, 9, 5)
15 (1, 16, 21) (2, 13, 22) (5, 15, 18) (6, 14, 17) (19, 11, 8) (20, 10, 7) (23, 12, 3) (24, 9, 4)
16 (1, 16, 21) (2, 15, 20) (3, 17, 18) (6, 12, 19) (19, 13, 6) (22, 8, 7) (23, 10, 5) (24, 9, 4)
17 (1, 16, 21) (2, 17, 18) (3, 15, 20) (6, 12, 19) (19, 13, 6) (22, 10, 5) (23, 8, 7) (24, 9, 4)
18 (1, 17, 19) (2, 14, 22) (4, 13, 20) (7, 15, 16) (18, 10, 9) (21, 12, 5) (23, 11, 3) (24, 8, 6)
19 (1, 17, 19) (2, 14, 22) (4, 15, 18) (5, 13, 20) (20, 12, 5) (21, 10, 7) (23, 11, 3) (24, 8, 6)
20 (1, 17, 19) (2, 15, 21) (3, 14, 20) (7, 13, 18) (18, 12, 7) (22, 11, 5) (23, 10, 4) (24, 8, 6)
21 (1, 17, 19) (2, 15, 21) (3, 16, 18) (5, 13, 20) (20, 12, 5) (22, 9, 7) (23, 10, 4) (24, 8, 6)
22 (1, 17, 20) (2, 13, 22) (4, 15, 19) (7, 14, 16) (18, 11, 9) (21, 10, 6) (23, 12, 3) (24, 8, 5)
23 (1, 17, 20) (2, 14, 21) (3, 16, 19) (7, 12, 18) (18, 13, 7) (22, 9, 6) (23, 11, 4) (24, 8, 5)
24 (1, 17, 20) (2, 16, 19) (3, 14, 21) (7, 12, 18) (18, 13, 7) (22, 11, 4) (23, 9, 6) (24, 8, 5)
25 (1, 18, 19) (2, 14, 21) (3, 15, 20) (8, 12, 17) (17, 13, 8) (22, 10, 5) (23, 11, 4) (24, 7, 6)
26 (1, 18, 19) (2, 14, 21) (3, 15, 20) (8, 13, 16) (17, 12, 9) (22, 10, 5) (23, 11, 4) (24, 7, 6)
27 (1, 18, 19) (2, 15, 20) (3, 14, 21) (8, 12, 17) (17, 13, 8) (22, 11, 4) (23, 10, 5) (24, 7, 6)
28 (1, 18, 19) (2, 15, 20) (3, 14, 21) (8, 13, 16) (17, 12, 9) (22, 11, 4) (23, 10, 5) (24, 7, 6)
所以有 697 个边组合,但只有 28 个角组合。
我现在需要做的就是以某种方式将一个与另一个进行比较。问题是每个边或角的位置都是可移动的。
我以不同的方式解决了您的问题,但您可以调整它的各个方面以供您自己使用。希望这可以作为这里的答案,因为它 应该 解决问题,但我不知道如何找到满足您条件的多维数据集,除非通过蛮力。如果您已经有一些候选人,您可以稍微修改代码以仅处理这些候选人。
总的来说,代码就像筛子一样工作。我选择使用 filter()
来完成繁重的工作,而不是嵌套的 for 循环。这种方法的优点是更容易通过代码进行推理,可以通过编写过滤器函数来创建新规则,并且以后可以轻松地重新排序过滤器以提高性能。
为了使代码有意义,您需要参考这张地图。每个候选组合都是一个包含 24 个元素的元组,因此索引从 0 到 23。A = 0,B = 1,C = 2,...,X = 23。我已经仔细检查了所有过滤器函数使用正确的索引,但您可能需要仔细检查。
编辑:我已经根据您的修正更正了对函数,并将组合更改为排列。由于每个数字都映射到立方体上的特定位置,因此顺序很重要。这就是为什么 combinations(range(1,25), 24) 只产生一个组合。只有一组无序的 24 个数字包含数字 1 到 24。这次我也手动创建了过滤器链,因为链接功能似乎不适用于这种情况。
+-----+
| A B |
| C D |
+-----+-----+-----+-----+
| E F | G H | I J | K L |
| M N | O P | Q R | S T |
+-----+-----+-----+-----+
| U V |
| W X |
+-----+
from itertools import permutations
# Filter functions
# ------------
# All corners are 37 or 38
def check_corners(lst):
print(".")
corners = [lst[5] + lst[6] + lst[2],
lst[3] + lst[7] + lst[8],
lst[13] + lst[14] + lst[20],
lst[21] + lst[15] + lst[16],
lst[12] + lst[22] + lst[19],
lst[23] + lst[17] + lst[6],
lst[1] + lst[9] + lst[10],
lst[0] + lst[4] + lst[11]]
return all(36 < corner < 39 for corner in corners)
# All sides add to 50
def check_sides(lst):
sides = [lst[0] + lst[1] + lst[2] + lst[3],
lst[4] + lst[5] + lst[12] + lst[13],
lst[6] + lst[7] + lst[14] + lst[15],
lst[8] + lst[9] + lst[16] + lst[17],
lst[10] + lst[11] + lst[18] + lst[19],
lst[20] + lst[21] + lst[22] + lst[23]]
return all(side == 50 for side in sides)
# All opposites add to 25
def check_opposites(lst):
print(lst)
opposites = [lst[0] + lst[22],
lst[2] + lst[20],
lst[1] + lst[23],
lst[3] + lst[21],
lst[5] + lst[8],
lst[4] + lst[9],
lst[12] + lst[17],
lst[13] + lst[16],
lst[7] + lst[10],
lst[6] + lst[11],
lst[15] + lst[18],
lst[14] + lst[19]]
return all(pair == 25 for pair in opposites)
# No pairs on a side add to 25
def check_pairs(lst):
pairs = [lst[0] + lst[1], lst[2] + lst[3],
lst[0] + lst[2], lst[1] + lst[3],
lst[0] + lst[3], lst[1] + lst[2],
lst[4] + lst[5], lst[12] + lst[13],
lst[4] + lst[12], lst[5] + lst[13],
lst[4] + lst[13], lst[5] + lst[12],
lst[6] + lst[7], lst[14] + lst[15],
lst[6] + lst[14], lst[7] + lst[15],
lst[6] + lst[15], lst[7] + lst[14],
lst[8] + lst[9], lst[16] + lst[17],
lst[8] + lst[16], lst[9] + lst[17],
lst[8] + lst[17], lst[9] + lst[16],
lst[10] + lst[11], lst[18] + lst[19],
lst[10] + lst[18], lst[11] + lst[19],
lst[10] + lst[19], lst[11] + lst[18],
lst[20] + lst[21], lst[22] + lst[23],
lst[20] + lst[22], lst[21] + lst[23],
lst[20] + lst[23], lst[21] + lst[22]]
return all(pair != 25 for pair in pairs)
candidates = permutations(range(1,25), 24)
cubes = filter(check_pairs,
filter(check_corners,
filter(check_corners,
filter(check_sides, candidates))))
for cube in cubes:
print(cube)
此代码的作用:
permutations
以所有可能的顺序生成从 1 到 24 的 24 个整数元组的迭代器。这意味着它将像一个可能的候选立方体列表一样,但只在被询问时而不是事先创建每个元组。这限制了内存使用。每个组合就像 (n1, n2, n3, ... n24)。这个元组的每个成员对应于你的多维数据集上的一个数字。- 链式过滤器就像筛子一样工作。它从最里面的过滤器开始,然后开始工作。每个内部过滤器仅传递满足过滤函数所有条件的排列。
- 如果括号内的所有比较都是
True
,all()
所做的就是returnTrue
。括号内的表达式称为 generator expression. cubes
包含一个链式迭代器,它按照您在列表中看到的顺序检查条件。如果您确定哪些消除了最多的候选立方体,则可以提高性能。您在链的开头淘汰的候选人越多,在他们身上浪费的时间就越少。for
循环是第一次任何检查代码是 运行,因为当循环向cubes
询问某个项目时,cubes
必须询问filter(check_pairs, ...)
这还得一路问filter(check_sides, ...)
。因此,check_sides
是最深层次,这意味着实际执行的是 第一次 比较。- 每次
cubes
吐出一个元组,其值满足过滤函数指定的所有条件,for循环将其打印出来。
最后,如果您跟踪已经尝试了多少组合并且程序崩溃或您必须暂停,请查看 here 以获取如何跳至可迭代项的第 n 项的示例,在这种情况下是 combinations()
。
为了清楚起见,将其添加为答案而不是再次编辑问题。
因此,使用我的边角代码,我 运行 对我创建的 2 个列表(边角和边)进行了列表比较。
代码现在似乎可以工作了。它很乱,但它有效(我认为)
感谢您的帮助。
from itertools import combinations
# program to distribute 24 numbers across the 6 sides of a cube
# there will be 4 numbers to a side
# and 3 numbers at each corner where 3 sides meet
# every number and its physical opposite must sum to 25.
# this means only the 1st 4 corners and 3 sides have to be worked out.
# as the opposites will automatically obey the rules.
# no pairs of numbers in a corner or on a side may equal 25
# the sum of a side must equal 50
# the sum of a corner must equal 37 or 38
# the sum of 2 corners connected by an edge must equal 75
# corners opposite each other on a side must be equal
corner_combinations = 0 # a simple counter
side_combinations = 0 # a simple counter
side_numbers_all = list(range(1,25)) # list of all numbers from 1 to 24
corner_numbers_all = list(range(1,25)) # list of all numbers from 1 to 24
# find the first corner
for corner_a in combinations((corner_numbers_all[1:24]), 2): # find combinations of 2 numbers from 2 to 23 (not using 1 or 24 as 1 is the first constant, and 24 is its direct opposite)
if 36 < corner_numbers_all[0] + sum(corner_a) < 39: # check if the corner using 1 (the constant mentiined above) and the pair of numbers from the combination sum to 37 or 38
corner1 = (corner_numbers_all[0], corner_a[0], corner_a[1]) # create a new corner list with the constant and the combination
if 25 not in (corner1[0] + corner1[1], corner1[0] + corner1[2], corner1[1] + corner1[2]): # check that all possible pairings in the new list do not sum to 25
corner8 = (25 - corner1[0], 25 - corner1[1], 25 - corner1[2]) # create a new corner list that is the opposite of the current list.
corner_numbers_remaining = list(set(corner_numbers_all) - set(corner1) - set(corner8)) # create a new list of numbers from the 1st list minus the 2 corner lists just created
# find the second corner, rules as above
for corner_b in combinations((corner_numbers_remaining[1:18]), 2):
if 36 < corner_numbers_remaining[0] + sum(corner_b) < 39:
corner2 = (corner_numbers_remaining[0], corner_b[0], corner_b[1])
if sum(corner1) + sum(corner2) == 75: # checks to see if the sum of the first and second corners is 75
if 25 not in (corner2[0] + corner2[1], corner2[0] + corner2[2], corner2[1] + corner2[2]):
corner7 = (25 - corner2[0], 25 - corner2[1], 25 - corner2[2])
corner_numbers_remaining2 = list(set(corner_numbers_remaining) - set(corner2) - set(corner7))
# find third corner, as abive
for corner_c in combinations((corner_numbers_remaining2[1:12]), 2):
if 36 < corner_numbers_remaining2[0] + sum(corner_c) < 39:
corner3 = (corner_numbers_remaining2[0], corner_c[0], corner_c[1])
if sum(corner3) == sum(corner1): # check to see if the sum of the first corner is the same as the sum of the third corner
if (corner3[0] + corner3[1] and corner3[0] + corner3[2] and corner3[1] + corner3[2]) != 25:
corner6 = (25 - corner3[0], 25 - corner3[1], 25 - corner3[2])
corner_numbers_remaining3 = list(set(corner_numbers_remaining2) - set(corner3) - set(corner6))
# find fourth corner, as per second corner
for corner_d in combinations((corner_numbers_remaining3[1:6]), 2):
if 36 < corner_numbers_remaining3[0] + sum(corner_d) < 39:
corner4 = (corner_numbers_remaining3[0], corner_d[0], corner_d[1])
if sum(corner1) + sum(corner4) ==75:
if (corner4[0] + corner4[1] and corner4[0] + corner4[1] and corner4[1] + corner4[2]) != 25:
corner5 = (25 - corner4[0], 25 - corner4[1], 25 - corner4[2])
corner_combinations += 1 # count how many combinations of corners meet the criteria.
# find first side, as per first corner
for side_a in combinations((side_numbers_all[1:24]),3): # 3 number combination this time, still dropping 1 and 24
if side_numbers_all[0] + sum(side_a) == 50: # check constant and combination sum to 50
if 25 not in (side_numbers_all[0] + side_a[0], side_numbers_all[0] + side_a[1], side_numbers_all[0] + side_a[2], side_a[0] + side_a[1], side_a[0] + side_a[2], side_a[1] + side_a[2]): # check no pairs of numbers sum to 25
side1 = (side_numbers_all[0], side_a[0], side_a[1], side_a[2]) # createvfirst side list
if len(set(side1).intersection(corner1)) <= 1 and len(set(side1).intersection(corner2)) <= 1 and len(set(side1).intersection(corner3)) <= 1 and len(set(side1).intersection(corner4)) <= 1 and len(set(side1).intersection(corner5)) <= 1 and len(set(side1).intersection(corner6)) <= 1 and len(set(side1).intersection(corner7)) <= 1 and len(set(side1).intersection(corner8)) <= 1: # check first side against all corners. Each number in side may only exist in one corner.
side6 = (25-side1[0], 25-side1[1], 25-side1[2], 25-side1[3]) # create the opposite side
# find second side as above
side_numbers_remaining = list(set(side_numbers_all) - set(side1) - set(side6))
for side_b in combinations(side_numbers_remaining[1:16],3):
if side_numbers_remaining[0] + sum(side_b) == 50:
if 25 not in (side_numbers_remaining[0] + side_b[0], side_numbers_remaining[0] + side_b[1], side_numbers_remaining[0] + side_b[2], side_b[0] + side_b[1], side_b[0] + side_b[2], side_b[1] + side_b[2]):
side2 = (side_numbers_remaining[0], side_b[0], side_b[1], side_b[2])
if len(set(side2).intersection(corner1)) <= 1 and len(set(side2).intersection(corner2)) <= 1 and len(set(side2).intersection(corner3)) <= 1 and len(set(side2).intersection(corner4)) <= 1 and len(set(side2).intersection(corner5)) <= 1 and len(set(side2).intersection(corner6)) <= 1 and len(set(side2).intersection(corner7)) <= 1 and len(set(side2).intersection(corner8)) <= 1:
side5 = (25-side2[0], 25-side2[1], 25-side2[2], 25-side2[3])
side_numbers_remaining2 = list(set(side_numbers_remaining) - set(side2) - set(side5))
for side_c in combinations(side_numbers_remaining2[1:8],3):
if side_numbers_remaining2[0] + sum(side_c) == 50:
if 25 not in (side_numbers_remaining2[0] + side_c[0], side_numbers_remaining2[0] + side_c[1], side_numbers_remaining2[0] + side_c[2], side_c[0] + side_c[1], side_c[0] + side_c[2], side_c[1] + side_c[2]):
side3 = (side_numbers_remaining2[0], side_c[0], side_c[1], side_c[2])
if len(set(side3).intersection(corner1)) <= 1 and len(set(side3).intersection(corner2)) <= 1 and len(set(side3).intersection(corner3)) <= 1 and len(set(side3).intersection(corner4)) <= 1 and len(set(side3).intersection(corner5)) <= 1 and len(set(side3).intersection(corner6)) <= 1 and len(set(side3).intersection(corner7)) <= 1 and len(set(side3).intersection(corner8)) <= 1:
side4 = (25-side3[0], 25-side3[1], 25-side3[2], 25-side3[3])
side_combinations += 1 # count how many sides combinations meet the criteria
# print result
print ("corner combinations:", corner_combinations)
print (corner1,"=", sum(corner1), corner2,"=", sum(corner2), corner3,"=", sum(corner3), corner4,"=", sum(corner4), corner5,"=", sum(corner5), corner6,"=", sum(corner6), corner7,"=", sum(corner7), corner8,"=", sum(corner8))
print ("side combinations:", side_combinations)
print (side1,"=", sum(side1), side2,"=", sum(side2), side3,"=", sum(side3), side4,"=", sum(side4), side5,"=", sum(side5), side6,"=", sum(side6))
我刚刚重新开始这个项目 - 在我恢复我的 SOF 帐户之前,我已经忘记了以上所有内容。
我认为,我同时创建的是一种破解此问题的蛮力尝试。该代码大约需要 5-10 分钟才能完成并产生一个组合。
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 21:26:53) [MSC v.1916 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>>
====================== RESTART: C:\Users\escri\face1.py ======================
1: [1, 12, 16, 21][18, 10, 3, 19][11, 17, 20, 2][23, 5, 8, 14][6, 22, 15, 7][4, 9, 13, 24]
There are 1 combinations
>>>
代码如下:
r = range(2, 23) # +-------------+-------------+-------------+
n = 0 # | C6:2--------| F2:0 F2:1 |--------C5:2 |
# | | F6:1 | C6:1 C5:1 | F6:0 | |
f1 = [1,0,0,0] # | | | | | |
f2 = [0,0,0,0] # | | | F2:3 F2:2 | | |
f3 = [0,0,0,0] # | | | C1:1 C2:1 | | |
f4 = [0,0,0,0] # +-------------+-------------+-------------+
f5 = [0,0,0,0] # | F3:0 F3:1 | F1:0 F1:1 | F4:0 F4:1 |
f6 = [0,0,0,24] # | C6:0 C1:2 | C1:0 C2:0 | C2:2 C5:0 |
# | | | |
c1 = [1,0,0] # | F3:3 F3:2 | F1:3 F1:2 | F4:3 F4:2 |
c2 = [0,0,0] # | C7:0 C4:2 | C4:0 C3:0 | C3:2 C8:0 |
c3 = [0,0,0] # +-------------+-------------+-------------+
c4 = [0,0,0] # | | | F5:2 F5:3 | | |
c5 = [0,0,0] # | | | C4:1 C3:1 | | |
c6 = [0,0,0] # | | | | | |
c7 = [0,0,0] # | | F6:2 | F5:1 F5:0 | F6:3 | |
c8 = [0,0,24] # | C7:2--------| C7:1 C8:1 |--------C8:2 |
# +-------------+-------------+-------------+
for xa in r:
f1[1] = xa
f6[2] = 25 - xa
for ya in r:
if ya != xa and ya + xa != 25:
f1[2] = ya
f6[1] = 25 - ya
for za in r:
if za != xa and za + xa != 25 and za != ya and za + ya != 25:
f1[3] = za
f6[0] = 25 - za
if sum(f1) == 50:
c2[0] = f1[1]
c7[2] = f6[2]
c3[0] = f1[2]
c6[2] = f6[1]
c4[0] = f1[3]
c5[2] = f6[0]
for wb in r:
if wb not in f1 and wb not in f6:
f2[0] = wb
f5[3] = 25 - wb
for xb in r:
if xb not in f1 and xb not in f6 and xb != wb and xb + wb != 25:
f2[1] = xb
f5[2] = 25 - xb
for yb in r:
if yb not in f1 and yb not in f6 and yb != wb and yb + wb !=25 and yb != xb and yb + xb != 25:
f2[2] = yb
f5[1] = 25 - yb
for zb in r:
if zb not in f1 and zb not in f6 and zb != wb and zb + wb !=25 and zb != xb and zb + xb != 25 and zb != yb and zb + yb != 25:
f2[3] = zb
f5[0] = 25 - zb
if sum(f2) == 50:
c6[1] = f2[0]
c3[1] = f5[3]
c5[1] = f2[1]
c4[1] = f5[2]
c2[1] = f2[2]
c7[1] = f5[1]
c1[1] = f2[3]
c8[1] = f5[0]
for wc in r:
if wc not in f1 and wc not in f2 and wc not in f5 and wc not in f6:
f3[0] = wc
f4[3] = 25 - wc
for xc in r:
if xc not in f1 and xc not in f2 and xc not in f5 and xc not in f6 and xc != wc and xc + wc != 25:
f3[1] = xc
f4[2] = 25 - xc
for yc in r:
if yc not in f1 and yc not in f2 and yc not in f5 and yc not in f6 and yc != wc and yc + wc != 25 and yc != xc and yc + xc != 25:
f3[2] = yc
f4[1] = 25 - yc
for zc in r:
if zc not in f1 and zc not in f2 and zc not in f5 and zc not in f6 and zc != wc and zc + wc != 25 and zc != xc and zc + xc != 25 and zc != yc and zc + yc != 25:
f3[3] = zc
f4[0] = 25 - zc
if sum(f3) == 50:
c6[0] = f3[0]
c3[2] = f4[3]
c1[2] = f3[1]
c8[0] = f4[2]
c7[0] = f3[2]
c5[0] = f4[1]
c4[2] = f3[3]
c2[2] = f4[0]
if sum(c1) == 37 or sum(c1) == 38:
if sum(c1) + sum(c2) == 75 and sum(c1) + sum(c4) == 75 and sum(c1) == sum(c3) and sum(c1) + sum(c8) == 75:
n += 1
print(f"{n}: {f1}{f2}{f3}{f4}{f5}{f6}")
print(f"There are {n} combinations")