Унікальна спіраль множення


13

Цей натхненний останнім викликом таблиці Хобі Кальвіна, що займається таблицею множення .

Напишіть функцію або програму, яка приймає ціле число Nяк вхід і друкує або повертає унікальну спіраль множення N-на-N. Код повинен (теоретично) працювати для N від 0 до 1000 (хоча виведення цього може бути важким). Вихід повинен бути еквівалентний таблиці, отриманій за наступною процедурою:

  1. Заповніть таблицю множення N-на-N. Напр. Для N = 3:

    1 2 3
    2 4 6
    3 6 9
    
  2. Виконайте спіраль за годинниковою стрілкою від лівого верхнього кута, зазначивши цифри, які ви відвідуєте. Коли ви відвідуєте номер, який ви вже відвідали, замініть його на 0.

Деякі приклади можуть зробити це більш зрозумілим:

n = 0:
0

n = 1:
1

n = 2:       //   Spiral order:
1  2         //   1  2
0  4         //   4  3

n = 3:
1  2  3      //   1  2  3
0  4  6      //   8  9  4
0  0  9      //   7  6  5

n = 4:
1  2  3  4   //   1   2   3   4
0  0  6  8   //  12  13  14   5
0  0  9 12   //  11  16  15   6
0  0  0 16   //  10   9   8   7

n = 5:
1   2   3   4   5
0   0   6   8  10
0   0   9  12  15
0   0   0  16  20
0   0   0   0  25

n = 10:
1   2   3   4   5   6   7   8   9  10
0   0   0   0   0  12  14  16  18  20
0   0   0   0  15   0  21  24  27  30
0   0   0   0   0   0  28  32  36  40
0   0   0   0  25   0  35   0  45  50
0   0   0   0   0   0  42  48  54  60
0   0   0   0   0   0  49  56  63  70
0   0   0   0   0   0   0  64  72  80
0   0   0   0   0   0   0   0  81  90
0   0   0   0   0   0   0   0   0 100

Цифри знаходяться так:

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

Будь-який розумний вихідний формат приймається, але він повинен бути матрицею N-by-N, це не може бути просто списком. Формати, такі, як наведено нижче, приймаються, оскільки є N легко розрізнених стовпців 1 на N або N-на-1 рядки:

[[1 2 3][0 4 6][0 0 9]]   <-- OK

[[1 0 0][2 4 0][3 6 9]]   <-- OK

ans =                     <-- OK
    1  2  3
    0  4  6
    0  0  9   

Найкоротший код виграти в байтах.


Я шпигую своїм маленьким оком видозмінене сито ератостена! Я майже впевнений, що ви можете використовувати тут шаблон, який я бачив десь чи іншим.
Аддісон Крим

2
Чому був би вихід для тих, n=0де в таблицях множення немає нуля. Я можу зрозуміти, вийшов n=1би 1, але навіщо включати нуль?
Том Карпентер

@TomCarpenter, це могло бути поганим рішенням, але я знав, що виникне питання "А як щодо N = 0?", Тож я зробив правило N = 0 -> 0. З ретроспективою, можливо, було б краще сказати, що N> 0, але зараз я боюся трохи пізно = /
Стюі Гріффін

2
@StewieGriffin Ви сказали, що вихід має бути матрицею N-by-N, тому вихід для матриці n=0повинен бути матрицею 0 на 0, або питання буде невідповідним.
алефальфа

Відповіді:



8

Mathematica 123 122 117 98 92 73 байт

З 24 байтами збережено завдяки LegionMammal978 та ще 19 - від alephalpha!


Дивно, але в цій таблиці декілька примірників будь-якого цілого числа nматимуть однаковий відносний упорядкування по спіралі, як і в самій таблиці! Перша поява числа nлежить у самій комірці, де це число з’являється спочатку в таблиці (коли заповнює таблицю рядок за рядком). Це означає, що підхід може взагалі нехтувати спіральним обмеженням, оскільки він не має ніякого відношення до результату. (Див. Пояснення нижче.)

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&

Приклад

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&[10]

{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {0, 0, 0, 0, 0, 12, 14, 16, 18, 20}, {0, 0, 0, 0, 15, 0, 21, 24, 27, 30}, {0, 0, 0, 0, 0, 0, 28, 32, 36, 40}, {0, 0, 0, 0, 25, 0, 35, 0, 45, 50}, {0, 0, 0, 0, 0, 42, 48, 54, 60}, {0, 0, 0, 0, 0, 49, 56, 63, 70}, {0, 0, 0, 0, 0, 0, 64, 72, 80}, {0, 0, 0, 0, 0, 0, 0, 81, 90}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}}


Grid[%]

тбл


Пояснення

Ми використовуємо той факт, що спіральний порядок позицій будь-якої цифри, n, такий же, як порядок позицій рядків-колонок, повернутих функцією Positions,!

Місце першого входження кожного числа (будь-яке замовлення за спіраллю або за позицією таблиці) буде першим елементом, повернутим Position. Ця клітина першого появи залишиться такою, якою вона є. Решта екземпляри числа замінюються на 0.

Давайте розглянемо, як це працює, вивчаючи випадок справи n==18. Ідея полягає в тому, щоб почати з таблиці множення:

(t = Table[k Range@#, {k, #}] &[10]) // Grid

і знайдіть позиції рядків-рядків кожного номера. Наприклад, 18 розташовано у рядку 2, колоні 9 (перша інстанція); Рядок 3, колонка 6; Рядок 6, колонка 3; і рядок 9, стовпчик 2. Вони мають відповідні положення спірального порядку {44, 58, 68, 82}.

Position[t, 18]

{{2, 9}, {3, 6}, {6, 3}, {9, 2}}

як видно з наступної таблиці.

таблиця2

Останні 3 екземпляри з 18 потрібно замінити на 0. (Ми будемо використовувати великі жирні сині нулі, щоб їх можна було легко помітити.)

ReplacePart[%, {{3, 6}, {6, 3}, {9, 2}} -> Style[0, {Blue, Bold, 16}]]// Grid

стіл3


Чи є причина, щоб не писати Function?
LegionMammal978

1
У мене виникли проблеми з вкладеними чистими функціями, але ця ітерація цього не потребує. Спасибі.
DavidC

Я рахую 117 байт, виключаючи новий рядок.
LegionMammal978


Ще кілька ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&
гольфів

2

Пітон, 99 95 90 89 87 81 байт

Код для гольфу:

n=range(1,input()+1);m=[]
for x in n:l=[(x*y,0)[x*y in m]for y in n];m+=l;print l

Безголівки:

n=range(1,input()+1);
m=[]
for x in n:
  l=[(x*y,0)[x*y in m]for y in n];
  m+=l;
  print l

Вихід:

10 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
[0, 0, 0, 0, 0, 12, 14, 16, 18, 20]
[0, 0, 0, 0, 15, 0, 21, 24, 27, 30] 
[0, 0, 0, 0, 0, 0, 28, 32, 36, 40]
[0, 0, 0, 0, 25, 0, 35, 0, 45, 50] 
[0, 0, 0, 0, 0, 0, 42, 48, 54, 60]
[0, 0, 0, 0, 0, 0, 49, 56, 63, 70] 
[0, 0, 0, 0, 0, 0, 0, 64, 72, 80]
[0, 0, 0, 0, 0, 0, 0, 0, 81, 90] 
[0, 0, 0, 0, 0, 0, 0, 0, 0, 100]

thanx @valuah за вхідне байтове гоління
CSᵠ

2

MATLAB, 96 88 87 86 79 байт

Це код 79 байт, який слід за прикладом виходів (конкретно для n = 0)

n=input('');m=+(n>0);for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

Цей 75 байтів, має таку саму поведінку, за винятком n = 0, що створить порожній масив відповідно до значення запитання (N по N масив = 0 по 0 = порожній масив).

n=input('');m=[];for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

Це також працює з Octave . Ви можете спробувати онлайн тут . Код уже додано у вигляді файлу з назвою 'multspiral.m'. Тож у запиті Octave введіть multspiralта натисніть клавішу Enter. Потім слід ввести розмір таблиці (наприклад, 4). Потім вихід буде надруковано.


Як це працює?

Спочатку для цього потрібно ввести номер введення (наприклад, 6, 4 і т.д.)

n=input('');

Тоді ми обробляємо випадки n=0і n=1- їм приділяється особлива обробка, оскільки вони є двома, які не відповідають правилу, яке я використовую для генерації масивів - насправді це може бути на 5 байт коротше, якби не незрозумілий n=0випадок.

m=+(n>0);

Потім для всіх значень n>2, ми робимо певну циклічність, поки матриця не виросте до потрібного розміру.

for i=2:n;

Насправді існує лише три простих відмінності між nі n+1для всіх n>=2. Це:

  1. Новий стовпець додається праворуч у масив, який містить числа n(1:n). Це легко обчислити за допомогою:

     a=i*(1:i);
    
  2. Будь-які елементи, які будуть додані в цей новий стовпець, повинні бути видалені з існуючої матриці (встановлена ​​в нуль), оскільки вони завжди будуть надходити пізніше в спіралі, ніж новий стовпець. Це видаляється за допомогою встромленого циклу для встановлення всіх елементів у поточній матриці, які у новому стовпці дорівнюють нулю.

    for j=a;
        m(m==j)=0;
    end;
    
  3. Існує нове нижнє рядок, для якого кожен елемент, крім того, який знаходиться в новому стовпці, буде нульовим. Коли новий стовпець доданий, через навмисне створені індекси поза межами межі автоматично прошиваються 0. Однією з сильних особливостей MATLAB є те, що він може нарощувати масиви без будь-яких спеціальних операцій, тому ми можемо просто додати новий рядок і стовпець з:

    m(1:i,i)=a;
    

Нарешті, у нас є кінець циклу for - який колись досяг, матриця mмістить наш вихід. Оскільки ви гнучкі зі своїм вихідним форматом, матриця відображається просто mу вигляді нового рядка без крапки з комою

end;
m

Наприклад, якщо ми запускаємо програму, вводимо число 10, отримуємо такий вихід:

m =
     1     2     3     4     5     6     7     8     9    10
     0     0     0     0     0    12    14    16    18    20
     0     0     0     0    15     0    21    24    27    30
     0     0     0     0     0     0    28    32    36    40
     0     0     0     0    25     0    35     0    45    50
     0     0     0     0     0     0    42    48    54    60
     0     0     0     0     0     0    49    56    63    70
     0     0     0     0     0     0     0    64    72    80
     0     0     0     0     0     0     0     0    81    90
     0     0     0     0     0     0     0     0     0   100

1

Haskell, 103 99 байт

import Data.Lists
f 0=[[0]]
f n=chunksOf n$foldr(\c d->c:replace[c][0]d)[][a*b|a<-[1..n],b<-[1..n]]

Приклад використання: f 4-> [[1,2,3,4],[0,0,6,8],[0,0,9,12],[0,0,0,16]].

Щойно я виявив Data.Listsмодуль, який має приємні функції в списках (таких як replace) і реекспортувати Data.List, Data.List.Splitі Data.List.Extras.


1

Рубі, 67 63 61 байт

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}

63 байти

->n{s,x=1..n,{};s.map{|c|s.map{|r|e=x[v=c*r]==1?0:v;x[v]=1;e}}}

67 байт

->n{s,x=1..n,[];s.map{|c|s.map{|r|e=x.include?(v=c*r)?0:v;x<<v;e}}}

Використання:

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}[10]
=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 0, 0, 0, 0, 12, 14, 16, 18, 20], [0, 0, 0, 0, 15, 0, 21, 24, 27, 30], [0, 0, 0, 0, 0, 0, 28, 32, 36, 40], [0, 0, 0, 0, 25, 0, 35, 0, 45, 50], [0, 0, 0, 0, 0, 0, 42, 48, 54, 60], [0, 0, 0, 0, 0, 0, 49, 56, 63, 70], [0, 0, 0, 0, 0, 0, 0, 64, 72, 80], [0, 0, 0, 0, 0, 0, 0, 0, 81, 90], [0, 0, 0, 0, 0, 0, 0, 0, 0, 100]]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.