デューラーの魔方陣を作成する


14

チャレンジ

デューラーの有名な魔方陣の配列または文字列表現を出力します。

ここに画像の説明を入力してください

あれは、

16  3  2 13
 5 10 11  8
 9  6  7 12
 4 15 14  1

おそらく悪用される可能性があるこの正方形のいくつかのプロパティは次のとおりです。

  • から1までの各整数を161回だけ含む
  • 各列または行の合計、および2つの対角線の合計は同じです。これは、魔方陣の定義プロパティです。合計は、正方形の魔法の定数です。
  • さらに、この特定の正方形では、4つの象限のそれぞれの合計も魔法の定数に等しく、中央の4つの正方形の合計とコーナーの4つの正方形の合計も同様です。

ルール

魔方陣を生成するBultinsは許可されていません(Matlab magicやMathematica などMagicSquare)。他の組み込み機能を使用できます。

コードはプログラムでも関数でもかまいません。

入力はありません。

数値は10進数でなければなりません。出力形式は通常どおり柔軟です。いくつかの可能性は次のとおりです。

  • ネストされた配列(関数出力、またはその文字列表現、セパレーターの有無にかかわらず、あらゆる種類の一致する括弧):

    [[16, 3, 2, 13], [5, 10, 11, 8], [9, 6, 7, 12], [4, 15, 14, 1]]
    
  • 2D配列:

    {16, 3, 2, 13; 5, 10, 11, 8; 9, 6, 7, 12; 4, 15, 14, 1}
    
  • 4つの文字列の配列、または4行で構成される文字列。数字は右揃えにすることができます

    16  3  2 13
     5 10 11  8
     9  6  7 12
     4 15 14  1
    

    または左揃え

    16 3  2  13
    5  10 11  8
    9  6  7  12
    4  15 14  1
    
  • 次のような、行と列の2つの異なるセパレーターを含む文字列

    16,3,2,13|5,10,11,8|9,6,7,12|4,15,14,1
    

出力形式では、行と列を明確に区別する必要があります。たとえば、フラット配列、またはすべての数字がスペースで区切られた文字列を出力することはできません。

コードゴルフ。最短勝。



4
興味深いことに、数字5、8、9、12は(1から始まる)位置にあり、6、7、10、11は垂直に、2、3、14、15は水平に、1、4、13および16は180°回転しています。しかし、それが誰にも役立つとは思わない。
ニール

2
おそらく有用な観察:各数値から1をデクリメントする場合、配列[15]で始まり、それぞれ13、3、8、および15でXORされた各アイテムと逆に繰り返し連結することにより、正方形を生成できます。
-ETHproductions

6
これは、ゴルフ以外の言語では圧縮がかなり難しいようです。大きな魔方陣はもっと良くできたと思う。
-xnor

1
私は、正方形の各回転または反射が同じ特性を持つことをかなり確信しています。
デニス

回答:


7

ゼリー、15 バイト

“¡6ṡƘ[²Ḳi<’ḃ⁴s4

TryItOnline!

かなり退屈です、ごめんなさい:

準備:正方形を取り、行ごとに読み、全単射の基数16から変換し、それを基数250に変換し、それらの「数字」のコードページインデックスを検索しました(¡6ṡƘ[²Ḳi<)。

次に、Jellyはインデックスを読み取って基数250を作成し、全単射の基数16(ḃ⁴)に変換し、サイズ4(s4)のチャンクに分割します。


別の方向を出力できる場合、14で逆さまにすることができます。

“#⁷ƙ¤ṆWȷỤ’ḃ⁴s4

テスト


理論上、16!整数に十分なメモリがある場合、次のようにすると14の正しい方向が得られます。

⁴Œ!“ŒCġŀḌ;’ịs4

これは、[1,16]のすべての順列を作成し、ベース250表現⁴Œ!使用してインデックス19800593106060(1ベース)の値を選択し、ŒCġŀḌ;で長さ4のチャンクに分割しs4ます。


それ以来、私は4個の新しい原子(追加したŒ?Œ¿œ?、及びœ¿そのような状況に対処するためにゼリーに)を。
モナドŒ?は整数(または整数の反復可能要素)を取り、実行中の自然数の可能な限り短い順列を返します。これは、それらの数のすべての順列の辞書式にソートされたリストの特定のインデックスを持ちます。
...順列リストを作成せずにそうします。
そのため、以下は12で機能します(明らかに競合しません):

“ŒCġŀḌ;’Œ?s4

試してごらん!


これは、Jelly forkで短くする必要があります(今まで忘れていましたが、申し訳ありません)。
デニス

ああ?あなたはどのように思いますか?
ジョナサンアラン

8

Pyth、18バイト

c4.PC"H#ût"_S16

コードを実行します。

c4.PC"H#ût"_S16

    C"H#ût"       Convert the packed string to the number 1122196781940
  .P       _S16   Take that-numbered permutation of the reversed range [16,15,...,1]
c4                Chop into piece of length 4

出力が16から始まるため、範囲を逆にすることは順列インデックスを下げることを意味していましたが、壊れただけだと思います。

これは、テーブルをベース17に直接変換し、次に20バイトの文字列(link)に変換するという、より退屈な戦略を打ち負かします。

c4jC"úz(ás¸H"17 

7

ゼリー16 15 バイト

4Œ!.ịm0µZḂÞ’×4+

オンラインでお試しください!

バックグラウンド

正方形の数字から1を減算し、それらを4で割ると(商と剰余の計算)、パターンが明らかになります。

quotients and remainders    quotients    remainders

   3 3  0 2  0 1  3 0        3 0 0 3      3 2 1 0
   1 0  2 1  2 2  1 3        1 2 2 1      0 1 2 3
   2 0  1 1  1 2  2 3        2 1 1 2      0 1 2 3
   0 3  3 2  3 1  0 0        0 3 3 0      3 2 1 0

剰余マトリックスは明らかなパターンに従い、生成が簡単です。商行列は、剰余行列を転置し、中央の行を交換することにより取得できます。

使い方

4Œ!.ịm0µZḂÞ’×4+  Main link. No arguments.

4Œ!              Compute the array of all permutations of [1, 2, 3, 4], in
                 lexicographical order.
   .ị            Take the permutations at the indices adjacent to 0.5, i.e., the
                 ones at indices 0 ([4, 3, 2, 1]) and 1 ([1, 2, 3, 4]).
     m0          Concatenate the resulting [[4, 3, 2, 1], [1, 2, 3, 4]] with a
                 reversed copy, yielding the matrix
                 M := [[4, 3, 2, 1], [1, 2, 3, 4], [1, 2, 3, 4], [4, 3, 2, 1]].
       µ         Begin a new, monadic chain. Argument: M
        Z        Zip/transpose M, yielding the matrix
                 [[4, 1, 1, 4], [3, 2, 2, 3], [2, 3, 3, 2], [1, 4, 4, 1]].
         ḂÞ      Sort the rows by the lexicographical order of their parities,
                 yielding [[4, 1, 1, 4], [2, 3, 3, 2], [3, 2, 2, 3], [1, 4, 4, 1]].
           ’     Subtract 1 to yield the matrix of quotients, i.e.,
                 [[3, 0, 0, 3], [1, 2, 2, 1], [2, 1, 1, 2], [0, 3, 3, 0]].
            ×4+  Multiply the quotient by 4 and add the result to M (remainders).

5

J、37 27バイト

マイルのおかげで10バイト節約できました!

4 4$1+19800593106059 A.i.16

退屈が少なくなりました!これは、かかる19800593106059リストの順列i.16です、15 2 1 12 4 9 10 7 8 5 6 11 3 14 13 0。次に、それは増分され、次に4by 4リストにシェーピングされます。

空白なしの代替バージョン:

_4]\1+19800593106059&A.i.16

後世のための出力:

   _4]\1+19800593106059&A.i.16
16  3  2 13
 5 10 11  8
 9  6  7 12
 4 15 14  1
   4 4$1+19800593106059 A.i.16
16  3  2 13
 5 10 11  8
 9  6  7 12
 4 15 14  1

私が考える_4]\1+19800593106059&A.i.16作品が、それはおそらく短くすることができ
マイル

@miles oo、のいい使い方A.。どのようにしてその数を特定しましたか?
コナーオブライエン

モナディックA.は、ゼロインデックスの順列の順列インデックスを検索します
マイル

@マイルハァッ。その機能についてもう少し学ぶ必要があると思います。
コナーオブライエン


4

ルビー、49バイト(単純なソリューションよりも短い!)

このチャレンジのスニペットを、評価されたものよりも短い主流言語で書くには、かなりの試行が必要でした!通常のルールではp、出力にa を追加してプログラムを作成しました。

p [15,4,8,3].map{|i|[1+i,1+i^=13,1+i^=3,1+i^=13]}

配列の配列(の文字列表現)を出力します。異なるフォーマットの文字列を出力するwatのRubyソリューションよりも長いですが、単純なリテラル配列を返す単純なプログラムよりも1バイト短くなっています。

p [[16,3,2,13],[5,10,11,8],[9,6,7,12],[4,15,14,1]] #naive solution, 50 bytes
p [15,4,8,3].map{|i|[1+i,1+i^=13,1+i^=3,1+i^=13]}  #submission, 49 bytes

説明:数字0..15(38バイト!)

これが私が始めた場所であり、はるかに簡単です。0..15の正方形を2進数に変換すると、各セルの列の下部に値がXORされ、行の右側に値が含まれることに注意してください。

15 2  1  12            1111 0010 0001 1100
4  9  10 7             0100 1001 1010 0111
8  5  6  11            1000 0101 0110 1011
3  14 13 0             0011 1110 1101 0000

これから、以下のコードを導き出します。ただし、最後の列ではなく最初の列を使用することで、図のように1バイトを節約します。

p [12,7,11,0].map{|i|[i^3,i^14,i^13,i]}            #0..15 square, 39 bytes         
p [15,4,8,3].map{|i|[i,i^13,i^14,i^3]}             #0..15 square, 38 bytes

必要な1..16バージョンはより困難でした。最終的には、0..15の正方形の各セルに1を追加することだと思いました。しかし、バイトを消費する多くの括弧を必要とした^よりも優先順位が低い+ので。最後に、私はを使用するというアイデアを思いつきました^=。の新しい値は、1が追加される前にi拡張割り当てによって計算される^=ため、計算は正しい順序で実行されます。


素晴らしい特性評価!Pythonでの簡単な実現は、ハードコードの上に6文字あります:for a in 12,7,11,0:print[(a^b)+1for b in 3,14,13,0]。で0〜15ができれば勝ちですfor a in 12,7,11,0:print[a^3,a^14,a^13,a]
-xnor

3

JavaScript(ES6)、43バイト

_=>`16,3,2,13
5,10,11,8
9,6,7,12
4,15,14,1`

改行、コンマで区切られます。もっと短い方法があるとは思わない...


ええ、これはおそらく最短です。
コナーオブライエン



2

DASH、24バイト

<|>4tc"................"

ピリオドをそれぞれ文字コード16、3、2、13、5、10、11、8、9、6、7、12、4、15、14、および1の文字に置き換えます。

説明

文字を4ずつ文字コードとチャンクの配列に変換するだけです。


2

実際には、22バイト

4"►♥☻♪♣◙♂◘○♠•♀♦☼♫☺"♂┘╪

オンラインでお試しください!

説明:

4"►♥☻♪♣◙♂◘○♠•♀♦☼♫☺"♂┘╪
 "►♥☻♪♣◙♂◘○♠•♀♦☼♫☺"     push a string containing the numbers in the magic square, encoded as CP437 characters
                   ♂┘   convert to ordinals
4                    ╪  chunk into length-4 slices

2

Groovy、57バイト/ 46バイト

"F21C49A7856B3ED0".collect{Eval.me("0x$it")+1}​.collate(4)​

それぞれを16進数として解析し、1を追加して4ずつ照合し、2D配列にします。

[[16, 3, 2, 13], [5, 10, 11, 8], [9, 6, 7, 12], [4, 15, 14, 1]]

より短いが、より遅い:

print '16,3,2,13|5,10,11,8|9,6,7,12|4,15,14,1'

2

JavascriptをES6、66 65 55バイト

はい、最短ではありません。はい、削減できます。

_=>`f21c
49a7
856b
3ed0`.replace(/./g,_=>'0x'+_-~0+' ')

今のところ、それは完璧ではありません。しかし、何かです!


おかげ@Neil 5-8バイトを救うことができるの提案、及びそのインスピレーション@ETHproductions 10のバイトを節約する提案!

これにより、回答は43バイトのソリューションよりも12バイトだけ長くなります


1
あなたは使用することができますgの代わりに、0parseInt(c,17)私はあなたに4つのバイトを節約すると思うこれは、代わりに、またはあなたが使用することができます+ 0x${c}、|| 16、私はあなたに5つのバイトを節約すると思うこれ、あなたはその後、すべての桁から1を減算し、後で戻ってそれを追加することができますこれでもう1バイト節約できます。
ニール

1
@Neilの提案に基づいて、合計で少なくとも10バイトを節約できます。
ETHproductions

@Neilアイデアをありがとう。base17を使用すると、実際に数バイト節約できます。本当に考えていないことです。
イスマエルミゲル

@ETHproductions提案ありがとうございます!私はまだそれがどのように機能するかを理解しようとしています。しかし、私はそこに着くと思います。今、あなたを倒すために13バイトを短くするだけです。しかし、あなたの答えはJavascriptで可能な限り短いようです
イスマエルミゲル

1

PowerShell v2 +、40バイト

'16,3,2,13
5,10,11,8
9,6,7,12
4,15,14,1'

パイプライン上に残された複数行のリテラル文字列。暗黙的な出力Write-Outputは、プログラムの完了時に発生します。素敵で退屈。


構築バージョン、77バイト

'f21c59a7856b3dc0'-split'(....)'-ne''|%{([char[]]$_|%{"0x$_+1"|iex})-join','}

文字列を取得し、-split4要素ごとにそれをループし、それぞれを16進数に変更して0x$_追加します1、にパイプをしiex(にInvoke-Expression似てeval)、その後、セパレータとして-join文字列に結果を,。暗黙的な印刷を使用して、4つの文字列をパイプラインに出力します。


1

Ruby、60バイト-最初の試行

%w(f21c 49a7 856b 3ed0).map{|i|i.chars.map{|i|i.to_i(16)+1}}

Ruby、45バイト-安い

puts '16,3,2,13|5,10,11,8|9,6,7,12|4,15,14,1'


1

05AB1E、15バイト

16Lœ•iPNÍš¯•è4ä

説明

16L              # range [1 ... 16]
   œ             # compute all permutations of the range
    •iPNÍš¯•è    # take the permutation at index 19800593106059
             4ä  # split the permutation into 4 parts

順列のインデックスは、次の式を使用して見つかりました。

a*15! + b*14! + c*13!+ ... + o*1! + p*0!

変数が、ターゲットリスト内の各番号の現在のインデックスの番号よりも小さい後続の要素の数で置き換えられる場所
[16, 3, 2, 13, 5, 10, 11, 8, 9, 6, 7, 12, 4, 15, 14, 1]

求められている順列は
a=15, b=2, c=1, d=10, e=2, f=6, g=6, h=4, i=4, j=2, k=2, l=2, m=1, n=2 o=1, p=0

これにより、次の式が得られます。 15*15!+2*14!+1*13!+10*12!+2*11!+6*10!+6*9!+4*8!+4*7!+2*6!+2*5!+2*4!+1*3!+2*2!+1*1!+0*0!

に等しい19800593106059


1

Matlab、38 35バイト

匿名関数:

@()['pcbm';'ejkh';'ifgl';'dnoa']-96

直接印刷(38バイト):

disp(['pcbm';'ejkh';'ifgl';'dnoa']-96)

Matlabでは、整数の配列を生成する最良の方法は文字列です。


:匿名関数を使用すると、数バイト救う@()['pcbm';'ejkh';'ifgl';'dnoa']-96
ルイスMendo

@LuisMendo値を返すことも受け入れられることに気づかなかった、ありがとう!
パジョン

1

Scala、52バイト

()=>Seq(15,4,8,3)map(x=>Seq(x,x^13,x^14,x^3)map(1+))

ゴルフをしていない:

()=>
  Seq(15, 4, 8, 3)
  .map(x=>
    Seq(x, x^13, x^14, x^3)
    .map(1+)
  )

Level River Stのルビーの答えに触発されました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.