Витворіть магічний квадрат Дюрера


14

Змагання

Виведіть масив або рядкове зображення знаменитого магічного квадрата Дюрера :

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

тобто,

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

Деякі властивості цього квадрата, які, можливо, можна експлуатувати, такі:

  • Він містить всі ціле число від 1до 16рівно один раз
  • Сума кожного стовпця чи рядка, а також сума кожної з двох діагоналей однакова. Це визначальна властивість магічного квадрата . Сума - магічна константа квадрата.
  • Крім того, для цього конкретного квадрата сума кожного з чотирьох квадрантів також дорівнює магічній константі, як і сума центральних чотирьох квадратів та сума кута чотирьох квадратів.

Правила

Бультини, які генерують магічні квадрати, не дозволені (наприклад, Matlab's 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

СпробуйтеItOnline!

Досить нудно, вибачте:

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

Потім Jelly зчитує індекси, щоб створити базове число 250, перетворюється на біективну базу 16 ( ḃ⁴) і розбивається на шматки розміром 4 ( s4).


Якщо нам дозволено виводити іншу орієнтацію, перевертання можливе в 14 :

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

Тест


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

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

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


З тих пір я додав чотири нових атомів ( Œ?, Œ¿, œ?і œ¿) в желе для вирішення таких ситуацій.
Монада Œ?приймає ціле число (або ітерабельне цілих чисел) і повертає найкоротшу можливу перестановку запущених натуральних чисел, які мали б даний індекс (або індекси) у списку лексикографічно відсортованого списку всіх перестановок цих чисел.
... і це робиться без створення списків перестановок.
Таким чином, зараз працює 12 (очевидно, що не конкурують):

“ŒCġŀḌ;’Œ?s4

Спробуй!


Це має бути коротше у вашій вилці «Желе» (про яку я досі забув, вибачте).
Денніс

Ой? Як ви думаєте?
Джонатан Аллан

8

Піт, 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роботи можуть, але це може бути скорочено можливо
милі

@miles oo, приємне використання A.. Як ви оштрафували це число?
Conor O'Brien

Монадік A.знаходить перестановку індексу перестановки з нульовою індексованою перестановкою
миль

@miles так. Я думаю, тоді мені слід було б дізнатися трохи більше про ці функції.
Conor O'Brien


4

Ruby, 49 байт (коротше, ніж наївне рішення!)

Було потрібно чимало спроб написати фрагмент для цього виклику основною мовою, яка була коротшою за те, що він оцінював! Відповідно до звичайних правил, я створив програму з неї, додавши pдля виведення її.

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

Він виводить (рядкове подання) масиву масивів. Це довше, ніж рішення Ruby від Wat, яке виводить рядок у різному форматі, але на один байт коротше, ніж наївна програма нижче, що просто повертає буквальний масив.

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`

Відокремлюються новими рядками, потім комами. Сумніваюсь, є якийсь коротший шлях ...


Так, це, мабуть, найкоротше.
Conor O'Brien



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 у двовимірному масиві.

[[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
Спираючись на пропозиції @ Ніла, ви можете зберегти принаймні 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.