产生丢勒的魔方


14

挑战

输出Dürer著名的魔方的数组或字符串表示形式:

enter image description here

那是,

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

该广场的某些属性可能会被利用,它们是:

  • 它包含从1到的每个整数16一次
  • 每列或每行的总和以及两个对角线的每一个的总和是相同的。这是魔方的定义属性。总和是平方的魔术常数
  • 另外,对于这个特定的正方形,四个象限中每个象限的总和也等于魔术常数,中心四个正方形的总和和角点四个正方形的总和也等于魔术常数。

规则

不允许生成魔术方块的Bultin(例如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}
    
  • 四个字符串组成的数组,或由四行组成的字符串。数字可能右对齐

    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
    
  • 具有两个不同的行和列分隔符的字符串,例如

    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 2016年

6
在非高尔夫语言中,这似乎很难压缩。我认为更大的魔术方块会做得更好。
xnor

1
我相当确定正方形的每次旋转或反射都将具有相同的属性。
丹尼斯,

Answers:


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


从那时起,我已经添加四个新的原子(Œ?Œ¿œ?,和œ¿),以果冻到地址这样的情况。
monad Œ?接受一个整数(或整数的可迭代数),并返回运行中的自然数的最短排列,该自然数在按字典顺序排序的所有这些排列的列表中具有给定索引(或多个索引)。
...并且这样做无需创建任何排列列表。
因此,以下内容现在适用于12(显然是非竞争):

“ŒCġŀḌ;’Œ?s4

搏一搏!


这应该在您的Jelly叉子上短一些(对不起,到现在为止我已经忘记了)。
丹尼斯

哦?你怎么想?
乔纳森·艾伦

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。然后,将其递增,然后成形为一个44列表。

备用版本,无空格:

_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.。您是如何找到该号码的?
Conor O'Brien

Monadic A.找到零索引排列的排列索引
英里

@miles呵呵。我想我那时应该更多地了解这些功能。
Conor O'Brien


4

Ruby,49个字节(比朴素的解决方案短!)

花费了很多尝试才能用比其评估结果要短的主流语言来编写此挑战的摘要!按照通常的规则,我通过添加a p使其输出来制作了一个程序。

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

它输出数组的(字符串表示形式)。它比wat的Ruby解决方案要长,后者输出格式不同的字符串,但比下面的简单程序(只返回文字数组)短一个字节。

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平方转换为二进制,则请注意,每个单元格在其列的底部包含的值与该行的右侧的值进行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

从中我们得出下面的代码。但是,通过使用第一列而不是最后一列,我们节省了一个字节,如图所示。

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。但是由于^优先级比+我需要的很多括号要低,所以要吃掉字节。最后,我想到了使用的想法^=。的新值i^=在添加1之前通过扩充分配计算的,因此计算以正确的顺序进行。


很好的表征!在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`

用换行符分隔,然后用逗号分隔。我怀疑还有没有更短的路...


是的,这可能是最短的。
Conor O'Brien

2

sed 39个字节

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

在线尝试!

没有比这更简单的了。而且,不幸的是,我也不认为它会变得更短。


2

果冻,20个字节

“Ѥ£Æ¦½¿®µ©¬€¥ÐÇ¢‘s4

在线尝试!

这只是查找每个字符的Jelly代码点,然后使用分割成长度为4的子数组s4


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

将每个解析为十六进制数字,并将1加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
根据@Neil的建议,您总共可以节省至少10个字节
ETH生产

@Neil非常感谢您的想法。使用base17确实可以节省一些字节。这真的是我没想到的。
伊斯梅尔·米格尔

@ETHproductions非常感谢您的建议!我仍在尝试了解其工作原理。但我想我会到达那里。现在,只需缩短13个字节即可击败您。但是看来您的答案似乎是Java语言中最短的答案
Ismael Miguel

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','}

取字符串,-split每四个元素s,在其上循环,将每个元素更改为十六进制,0x$_然后添加1,管道iex(为的缩写Invoke-Expression,类似于eval),然后-join将结果以字符串,作为分隔符。将四个字符串输出到管道,并进行隐式打印。


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
Luis Mendo

@LuisMendo我没有注意到返回值也是可以接受的,谢谢!
pajonk

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的红宝石答案的启发。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.