正方形の対称性を見つける


14

正の整数のリストを受け取るプログラムまたは関数を作成します。これらの整数はそれぞれ、2D平面上の正方形の辺の長さを表します。各正方形は、平面内の任意の整数座標に移動できますが、回転することはできず、他の正方形と重なることはできません。

空白ごとに異なる印刷可能なASCII文字を使用して(空に使用されるスペースを除く)、プログラム/関数は、反射対称の水平線または垂直線を持つ正方形の単一配列を印刷する必要があります。そのような配置が存在しない場合は、何も印刷しないでください。

四角は区別できるように異なる文字です。すべての正方形の結合によって作成された形状のみが対称である必要があります。リストには94を超える要素は含まれないと想定できます(94文字があるため)。

たとえば、入力がの[2, 1, 2, 2, 2]場合、可能な出力は次のとおりです。

DD--
DD--
Z
FFPP
FFPP

この形状には、反射対称の水平線があります。その上半分と下半分は鏡像です。他にもいくつかの可能性があります:(正方形に触れる必要はなく、同じ文字で2つの正方形が作られていない限り、任意の文字を使用できます。)

  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個の要素があります。
  • 標準入力、コマンドライン、テキストファイル、関数引数など、合理的な方法で入力を行います。{1, 2, 3, 4}またはなど、ニーズに合わせてわずかにフォーマットできます[1 2 3 4]
  • stdoutなどへの出力。結果の形状に対称線がある限り、任意の量の先頭/末尾のスペースまたは改行は問題ありません。
  • 対称の対角線はカウントされません(そうでなければ、これは非常に簡単です)。また、回転対称または遷移対称ではなく、反射対称でなければなりません。
  • このタスクが計算上どれほど難しいかは正直わかりません。問題の一部のサブセットを解決する部分的な回答を投稿できます(特に巧妙なアルゴリズムを披露したい場合)。これらは勝つ資格がありません。
    • たとえば、入力には常に少なくとも1つの対称配列があると仮定することができます(したがって、リスト[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)

今のところ軽度のゴルフのみですが、ここから始めましょう。exec10行目と12行目に使用してみましたが、何らかの理由でそれができませんでした。

LSTDIN経由でリストを入力します(例:)[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)

@ Calvin'sHobbies空の行と列を削除するのを忘れたことに気付きました(これは、ボードに対しても構成が対称でなければならないことを意味していました)。[1, 1, 2, 3, 5]今は正常に動作します。
Sp3000

あ。総当たり攻撃は永遠に続いていると思いました。
カルバンの趣味

@ Calvin'sHobbiesこれは、より大きなボードには使用できますが、追加の制約を設定すると、さらに悪化します
。P– Sp3000

インデントトリックを使用していくつかの文字を保存できると思います。
カルビンの趣味
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.