首页 > 解决方案 > 引用多个列表,直到获得正确的组合

问题描述

编辑以更新我的代码并对@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 AND 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 的代码

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)

我在每张脸上添加了缺失的“对”(对于 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个角组合。

我现在需要做的就是以某种方式检查一个与另一个。问题是每个边或角的位置是可移动的。

标签: pythonpython-3.xpython-3.6flow-control

解决方案


我以不同的方式处理您的问题,但您可以调整它的各个方面以供自己使用。希望这可以作为这里的答案,因为它应该可以解决问题,但是我不知道如何找到满足您条件的立方体,除非通过蛮力。如果您已经有一些候选人,您可以稍微修改代码以仅通过这些候选人。

一般来说,代码就像筛子一样工作。我选择使用filter()to 做繁重的工作而不是嵌套的 for 循环。这种方法的优点是更容易通过代码进行推理,您可以通过编写过滤器函数来创建新规则,并且您可以在以后轻松地重新排序过滤器以提高性能。

为了使代码有意义,您需要查阅此地图。每个候选组合是一个包含 24 个元素的元组,因此索引从 0 到 23。A = 0,B = 1,C = 2,...,X = 23。我仔细检查了所有过滤器功能使用正确的索引,但您可能需要仔细检查。

编辑:我已经用您的修复更正了pairs函数,并将组合更改为排列。由于每个数字都映射到立方体上的特定位置,因此顺序很重要。这就是为什么 combine(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)

这段代码的作用:

  1. permutations以所有可能的顺序生成从 1 到 24 的 24 个整数的元组的迭代器. 这意味着它将像一个可能的候选多维数据集列表一样,但仅在被询问时而不是事先创建每个元组。这限制了内存使用。每个组合就像 (n1, n2, n3, ... n24)。该元组的每个成员对应于您的多维数据集上的一个数字。
  2. 链式过滤器像筛子一样工作。它从最里面的过滤器开始,然后向外工作。每个内部过滤器仅传递满足过滤功能的所有条件的那些排列。
  3. 如果all()括号True内的所有比较都是True. 括号内的表达式称为生成器表达式
  4. cubes包含一个链式迭代器,它按照您在列表中看到的顺序检查条件。如果您确定哪些消除了最多候选立方体,则可以提高性能。您在链开始时淘汰的候选人越多,在他们身上浪费的时间就越少。
  5. for循环是第一次运行任何检查代码,因为当循环要求一个cubes项目时,cubes必须询问filter(check_pairs, ...)哪个必须一直询问filter(check_sides, ...)。所以,check_sides是最深层次,这意味着它是实际执行的第一个比较。
  6. 每次cubes吐出一个元组,其值满足过滤器函数指定的所有条件,for 循环将其打印出来。

最后,如果您跟踪您已经尝试了多少组合并且程序崩溃或者您必须暂停,请在此处查看如何跳到可迭代的第 n 个项目的示例,combinations()在这种情况下。


推荐阅读