Ссылка на несколько списков, пока не будут получены правильные комбинации - PullRequest
0 голосов
/ 20 апреля 2019

ИЗМЕНЕНО, чтобы ОБНОВИТЬ МОЙ КОД И ПОЛНОСТЬЮ ОТВЕТИТЬ НА @ МОХАММЕД

Изображение, если хотите, куб.Каждое лицо этого куба имеет группу из 4 чисел.Каждое число в кубе встречается только один раз.

До сих пор мне с некоторой помощью удалось написать программу, которая фильтрует эти 24 числа в список, где каждое лицо из 4 чисел составляет 50, нет.пара на лице всего 25, но каждое число и его прямая противоположность (физически) всего 25.

Проблема, с которой я сейчас столкнулся, - это углы.У меня есть правило, которое я хочу применить к ним.Все 3 числа, которые встречались в каждом углу, должны составлять 37 или 38. Есть и другие правила, но сейчас давайте просто придерживаться этого.

Теперь, как у кубика, все числа, противоположные всем, одинаковы,Это означает, что для всех намерений у каждой группы была противоположность, и поэтому она никогда не может быть смежной с ней.

Так что моя программа выплюнула свою первую группу из 6 лиц, которые соответствуют моим критериям.Как мне теперь проработать углы?

Я понял, что мне НУЖНО работать только с 3 из 6 граней, как с каждым числом в паре с противоположным общим 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 в качестве константы, с которой все остальные соединяются, чтобы сделать его немного проще, я думаю.

У меня есть2 вопроса, во-первых, при условии, что наше первое совпадение появляется только в последней комбинации групп. Как лучше всего написать код?

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 выбрана первым битом правила, как я могу убедиться, что последующий запрос будет работать только в том случае, если это правда (или это имеет смысл?)

Это мой полный код ... EDITED

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

Таким образом, 8 миллионов попаданий для углов 1 и 8, только 200 000 для 1 и 8, 2 и 7 и только 5000 для 1 и 8, 2 и 7, AND 3 и 6 - но ничего, кроме 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|
  +----------------------+

================================================================================

ОТВЕТ на @ код Мохаммеда

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).

Я изменил порядок проверок, чтобы сначала выполнить проверки с наименьшим количеством аргументов.

Но яне понимая вывод, кажется, что он просто печатает все комбинации из 24 чисел от 1 до n без применения фильтров.

Изменение 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 угловых комбинаций.

Все, что мне нужно сделать сейчас, это как-то проверить одно на другое. Проблема в том, что позиция каждой стороны или угла подвижна.

Ответы [ 2 ]

1 голос
/ 20 апреля 2019

Я подошел к вашей проблеме по-другому, но вы можете адаптировать ее аспекты для собственного использования. Надеюсь, что это квалифицируется как ответ здесь, поскольку должно решить проблему, но я не знаю, как найти куб, отвечающий вашим условиям, кроме как грубой силой. Если у вас уже есть кандидаты, вы можете немного изменить код, чтобы он работал только с ними.

В целом код работает как сито. Я решил использовать filter() для выполнения тяжелых работ вместо вложенных для петель. Преимущества этого подхода состоят в том, что с помощью кода легче рассуждать, вы можете создать новое правило, написав функцию фильтра, и вы можете легко переупорядочить фильтры позже, чтобы повысить производительность.

Чтобы код имел смысл, вам нужно обратиться к этой карте. Каждая комбинация кандидатов представляет собой кортеж с 24 элементами, поэтому индексы изменяются от 0 до 23. A = 0, B = 1, C = 2, ..., X = 23. Я дважды проверил, что все функции фильтра используйте правильные индексы, но вы можете перепроверить.

Редактировать: я исправил функцию пар с вашими исправлениями и изменил комбинации на перестановки. Поскольку каждое число отображается в определенное место на кубе, порядок имеет значение. Вот почему комбинации (диапазон (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 создает итератор кортежей из 24 целых чисел от 1 до 24 во всех возможных порядках. Это означает, что он будет действовать как список возможных кубов-кандидатов, но создает каждый кортеж только по запросу, а не заранее. Это ограничивает использование памяти. Каждая комбинация похожа на (n1, n2, n3, ... n24). Каждый член этого кортежа соответствует одному из чисел в вашем кубе.
  2. Цепной фильтр работает как сито. Он начинается с самого внутреннего фильтра и выходит из него. Каждый внутренний фильтр передает только те перестановки, которые удовлетворяют всем условиям функции фильтрации.
  3. То, что all() делает, возвращает True, если все сравнения в скобках True. Выражение в скобках называется генератором выражение .
  4. cubes содержит цепочечный итератор, который проверяет условия в порядке, который вы видите в списке. Вы можете ускорить производительность, если вы уверены, какие из них исключают большинство кубов-кандидатов. Чем больше кандидатов вы выберете в начале цепочки, тем меньше времени будет потрачено на них.
  5. Цикл for - это первый запуск любого проверочного кода, потому что когда цикл запрашивает cubes элемент, cubes должен запросить filter(check_pairs, ...), который должен запросить filter(check_sides, ...) всех спуск. Итак, check_sides - это самый глубокий уровень, то есть это действительно первое сравнение 1039 *, которое выполняется.
  6. Каждый раз, когда cubes выплевывает кортеж со значениями, которые удовлетворяют всем условиям, указанным функциями фильтра, цикл for выводит его на печать.

Наконец, если вы отслеживаете, сколько комбинаций вы уже пробовали, и программа дает сбой, или вам нужно сделать паузу, проверьте здесь для примера того, как перейти к n-му элементу итерируемого, в данном случае combinations().

0 голосов
/ 23 апреля 2019

Добавление этого в качестве ответа, в отличие от повторного редактирования вопроса, просто для ясности.

Итак, используя мой угловой и боковой код, я провел сравнение списков по двум спискам, которые я создал, по углам и сторонам.

Код теперь работает. Это грязно, но работает (я думаю)

Спасибо за вашу помощь.

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))                                              
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...