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


13

Этот вдохновлен недавним вызовом Calvin's Hobbies для таблицы умножения .

Напишите функцию или программу, которая принимает целое число в 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-N-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 на 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, 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, 0, 64, 72, 80}, {0, 0, 0, 0, 0, 0, 0, 0, 81, 90}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}}


Grid[%]

TBLE


объяснение

Мы используем тот факт, что спиральный порядок позиций любой цифры 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

Python, 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

Ungolfed:

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]

спасибо @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 by N array = 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и нажмите клавишу ввода. Затем вы должны ввести размер таблицы (например, 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, чтобы установить все элементы в текущей матрице, которые в новом столбце, равны нулю.

    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.