Нахождение симметрий в квадратах

14

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

Используя различные печатные символы ASCII для каждого квадрата (исключая пробел, который используется для пустоты), ваша программа / функция должна напечатать любое отдельное расположение квадратов, которое имеет горизонтальную или вертикальную линию отражательной симметрии. Если такой договоренности не существует, то ничего не должно быть напечатано.

Квадраты - это разные символы, поэтому их можно отличить друг от друга. Только форма, созданная объединением всех квадратов, должна быть симметричной. Можно предположить, что список будет содержать не более 94 элементов (так как имеется 94 символа).

Например, если вход был [2, 1, 2, 2, 2], возможный вывод:

DD--
DD--
Z
FFPP
FFPP

Эта форма имеет горизонтальную линию отражательной симметрии; его верхняя и нижняя половины - зеркальные изображения. Вот некоторые другие возможности: (Обратите внимание, что квадраты не должны касаться, и любые символы могут использоваться, если два квадрата не сделаны из одного и того же символа.)

  55
  55
  %%
  %%
@
  HH
  HH
  ((
  ((
       G

     11 33
     11 33

    22   44
    22   44

Линия симметрии также может быть границей между символами, например, для [2, 4]:

!!!!
!!!!  ++
!!!!  ++
!!!!

Некоторые наборы квадратов невозможно расположить симметрично, например [1, 2, 3]:

AAA BB C
AAA BB         (these can't be vertically or horizontally symmetric => no output)
AAA

И помните, что общая форма может быть симметричной, даже если квадратные границы не являются. Например, допустимый вывод для [2, 1, 1, 1, 1, 4]:

AA----
AA----
BC----
DE----

Точно так же действительный вывод для [1, 1, 2, 3, 5]:

44444
44444
44444
44444
44444
33301
33322
33322

Примечания

  • Список ввода всегда будет иметь от 1 до 94 элементов.
  • Принять ввод любым разумным способом: стандартный ввод, командная строка, текстовый файл, функция arg. Он может быть слегка отформатирован в соответствии с вашими потребностями, например {1, 2, 3, 4}или [1 2 3 4].
  • Вывод на стандартный вывод или аналогичный. Любое количество начальных / конечных пробелов или новых строк хорошо, если полученная форма имеет линию симметрии.
  • Диагональная линия симметрии не считается (иначе это было бы очень легко). Кроме того, это должна быть отражательная симметрия, а не вращательная или переходная.
  • Я, честно говоря, не уверен, насколько сложна в вычислительном отношении эта задача. Вы можете опубликовать частичные ответы, которые решают некоторое подмножество проблемы (особенно если вы хотите показать особенно умный алгоритм). Они не имеют права на победу.
    • Например, вы можете предположить, что входные данные всегда имеют хотя бы одно симметричное расположение (поэтому списки вроде [1, 2, 3]никогда не вводятся).
    • Или, например, вы можете рассмотреть только те варианты, в которых квадратные границы, а также общая форма симметричны. В этом случае не [1, 1, 2, 3, 5]будет никакого выхода.
    • Если вы хотите сойти с ума, вы можете распространить эту идею на прямоугольники или даже полиомино .

счет

Ваша оценка - это размер вашей программы в байтах . Самый низкий балл побеждает. Tiebreaker идет ответ опубликован первым.

Кальвин Хобби
источник
2
Бонусные баллы за решение [2, 4, 6, 7, 8, 9, 11, 15, 16, 17, 18, 19, 24, 25, 27, 29, 33, 35, 37, 42, 50, 112], хотя, поскольку вопрос дает гораздо больше свободы, возможно, есть и другие решения.
Sp3000

Ответы:

4

Python 2, 460 452 437 байт

exec"""def f(L):
 if[]==L:
  X{2}[map(" ".__lt__,q)for q in G]);Z{2}zip(*X));C=Z==Z[::-1]or X==X[::-1]
  if C:print"\\n".join(map("".join,G))
  return C
 x=L[-1];T=S-x+1;R=range(x)
 for n in range(T*T):
  i=n%T;j=n/T
  if all({1}=" "{0}):
{0}:{1}chr(32+len(L))
   r=f(L[:-1])
{0}:{1}" "
   if r:return r""".format("   for a,b in[(a,b)for a in R for b in R]","G[i+a][j+b]=","=filter(sum,")
L=input()
S=sum(L)
G=[S*[" "]for _ in[0]*S]
f(L)

Пока только в гольфе, но есть кое-что для начала. Я попытался использовать execдля строк 10 и 12, но по некоторым причинам это не позволило мне.

Введите список Lчерез STDIN, например [2, 1, 2, 2, 2]. Программа просто пробует каждую возможность размещения квадратов в sum(L) x sum(L)сетке.

Пример вывода (пустые строки удалены для компактности):

[2, 1, 2, 2, 2]

%%       
%%       
$$       
$$       
"        
##       
##       
!!       
!!      

[2, 4]

""""  
""""  
""""  
""""  
 !!   
 !!   

[2, 1, 1, 1]

$!!  
#!!  
 "   

[1, 1, 2, 3, 5]

%%%%%       
%%%%%       
%%%%%       
%%%%%       
%%%%%       
$$$##       
$$$##       
$$$"!       

[1, 4, 1, 8]

$$$$$$$$      
$$$$$$$$      
$$$$$$$$      
$$$$$$$$      
$$$$$$$$      
$$$$$$$$      
$$$$$$$$      
$$$$$$$$      
# """" !      
  """"        
  """"        
  """"        

[8, 1, 4, 1]

$   !!!!!!!!  
    !!!!!!!!  
####!!!!!!!!  
####!!!!!!!!  
####!!!!!!!!  
####!!!!!!!!  
    !!!!!!!!  
"   !!!!!!!!  

(The algorithm starts placing from the last square first, prioritising left then up)

Чуть менее запутанная версия (452 ​​байта):

def f(L):
 if[]==L:
  X=filter(sum,[map(" ".__lt__,q)for q in G]);Z=filter(sum,zip(*X));C=Z==Z[::-1]or X==X[::-1]
  if C:print"\n".join(map("".join,G))
  return C
 x=L[-1];T=S-x+1;R=range(x);V=[(a,b)for a in R for b in R]
 for n in range(T*T):
  i=n%T;j=n/T
  if all(G[i+a][j+b]<"!"for a,b in V):
   for a,b in V:G[i+a][j+b]=chr(32+len(L))
   r=f(L[:-1])
   for a,b in V:G[i+a][j+b]=" "
   if r:return r
L=input()
S=sum(L)
G=[S*[" "]for _ in[0]*S]
f(L)
Sp3000
источник
@ Calvin'sHobbies Я только что понял, что забыл обрезать пустые строки и столбцы (что означало бы, что конфигурация должна быть симметричной относительно платы ). [1, 1, 2, 3, 5]сейчас работает нормально.
Sp3000
Ах. Я думал, что грубая сила просто навсегда.
Увлечения Кельвина
@ Calvin'sHobbies Это подходит для больших плат, но наложение дополнительных ограничений только усугубляет ситуацию: P
Sp3000
Я думаю, что вы можете сохранить некоторые символы, используя трюк с отступом .
Увлечения Кельвина