Произведите магический квадрат Дюрера


14

Соревнование

Выведите массив или строковое представление знаменитого магического квадрата Дюрера :

введите описание изображения здесь

то есть,

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

Некоторые свойства этого квадрата, которые могут быть использованы, являются:

  • Он содержит каждое целое число от ровно 1до16
  • Сумма каждого столбца или строки, а также сумма каждой из двух диагоналей одинакова. Это определяющее свойство магического квадрата . Сумма является магической константой квадрата.
  • Кроме того, для этого конкретного квадрата сумма каждого из четырех квадрантов также равна магической константе, равно как и сумма центральных четырех квадратов и сумма угловых четырех квадратов.

правила

Бултины, которые генерируют магические квадраты, не допускаются (такие как 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], а затем многократно конкатенировать его с обратным порядком с каждым элементом XOR, равным 13, 3, 8 и 15 соответственно.
ETHproductions

6
Это кажется довольно сложным для сжатия в неигровых языках. Я думаю, что больший магический квадрат был бы лучше.
xnor

1
Я уверен, что каждое вращение или отражение квадрата будет иметь одинаковые свойства.
Деннис

Ответы:


7

Желе , 15 байт

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

TryItOnline!

Довольно скучно, извините

Приготовление: взял квадрат, прочитал его по строкам, преобразовал из биективной базы 16, преобразовал ее в базу 250, посмотрел индексы кодовой страницы для этих «цифр» (¡6ṡƘ[²Ḳi< ).

Затем желе читает индексы, чтобы сделать число 250 оснований, преобразует в биективное основание 16 (ḃ⁴ ) и разбивается на куски размером 4 ( s4).


Если нам разрешено выводить другую ориентацию, в 14 возможен перевернутый вид :

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

Тестовое задание


Теоретически, учитывая достаточно памяти для 16!целых чисел, следующее даст нам правильную ориентацию в 14 :

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

Это создаст все перестановки [1,16] с ⁴Œ!и выберет значение по индексу 19800593106060 (на основе 1) с использованием представления 250 базыŒCġŀḌ; и разделит его на куски длиной 4 с s4.


С тех пор я добавил четыре новых атомов ( Œ?, Œ¿, œ?и œ¿) в желе для решения таких ситуаций.
Монада Œ?берет целое число (или итерацию целых чисел) и возвращает кратчайшую возможную перестановку бегущих натуральных чисел, которые имели бы данный индекс (или индексы) в списке лексикографически отсортированного списка всех перестановок этих чисел.
... и делает это без создания списков перестановок.
Таким образом, следующее будет работать для 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 байтов:

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 . Затем, что увеличивается, а затем формируется в 4по 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работает, но это может быть сделано, возможно, короче
миль

@ миль oO, хорошее использование A.. Как вы нашли этот номер?
Конор О'Брайен

Monadic A.находит индекс перестановки перестановки с нулевым индексом
мили

@ Майлз да Я думаю, что я должен узнать немного больше об этих функциях тогда.
Конор О'Брайен


4

Ruby, 49 байт (короче наивного решения!)

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

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

Он выводит (строковое представление) массив массивов. Это длиннее, чем решение Waty 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 в двоичный файл, мы заметим, что каждая ячейка содержит значение в нижней части своего столбца, XORed со значением в правой части строки:

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 была более сложной. В конце я понял, что способ сделать это - добавить 1 в каждую ячейку квадрата 0..15. Но так как ^имеет более низкий приоритет, чем +мне нужно много скобок, которые съедают байты. Наконец я наткнулся на идею использования ^=. Новое значение 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`

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


Да, это, наверное, самое короткое из возможных.
Конор О'Брайен



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, сопоставить на 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 байтов!

Это делает ответ только на 12 байтов длиннее, чем его решение на 43 байта .


1
Вы можете использовать gвместо 0и parseInt(c,17)вместо этого, что, я думаю, экономит вам 4 байта, или вы можете использовать + 0x${c}|| 16, который, я думаю, экономит вам 5 байтов, и вы можете затем вычесть 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','}

Берет строку, -splitкаждые четыре элемента, зацикливает на них, заменяет каждый на гекс 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}}

Рубин, 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

Матлаб, 38 35 байт

Анонимная функция:

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

Прямая печать (38 байт):

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

В Matlab лучший способ создать массив целых чисел - это строка.


Использование анонимной функции позволило бы сэкономить несколько байтов:@()['pcbm';'ejkh';'ifgl';'dnoa']-96
Луис Мендо

@ LuisMendo Я не заметил, что возвращаемое значение также приемлемо, спасибо!
Pajonk

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.