Создать пирамидальную матрицу


23

Пирамидальная матрица - это квадратная матрица, в которой все числа увеличиваются или уменьшаются от центральной точки, как две матрицы ниже:

1  1  1  1  1
1  2  2  2  1
1  2  3  2  1
1  2  2  2  1
1  1  1  1  1

Или:

3  3  3  3  3
3  2  2  2  3
3  2  1  2  3
3  2  2  2  3
3  3  3  3  3

Если задано ненулевое целое число n, создайте пирамидальную матрицу, в которой числа идут от одного 1к nдругому в порядке возрастания (если n <0) или в порядке убывания (если n> 0) от центра. Если nчёт, то будет 4 центральных номера (см. Примеры).

Как всегда:

  • Дополнительный формат ввода и вывода
    • Количество пробелов, разделитель и т. Д. Необязательно

Тестовые случаи:

1
1

-1
1

5
1  1  1  1  1  1  1  1  1
1  2  2  2  2  2  2  2  1
1  2  3  3  3  3  3  2  1
1  2  3  4  4  4  3  2  1
1  2  3  4  5  4  3  2  1
1  2  3  4  4  4  3  2  1
1  2  3  3  3  3  3  2  1
1  2  2  2  2  2  2  2  1
1  1  1  1  1  1  1  1  1

-5
5  5  5  5  5  5  5  5  5
5  4  4  4  4  4  4  4  5
5  4  3  3  3  3  3  4  5
5  4  3  2  2  2  3  4  5
5  4  3  2  1  2  3  4  5
5  4  3  2  2  2  3  4  5
5  4  3  3  3  3  3  4  5
5  4  4  4  4  4  4  4  5
5  5  5  5  5  5  5  5  5

2
1  1  1  1
1  2  2  1
1  2  2  1
1  1  1  1

-2
2  2  2  2
2  1  1  2
2  1  1  2
2  2  2  2

-4
4  4  4  4  4  4  4  4
4  3  3  3  3  3  3  4
4  3  2  2  2  2  3  4
4  3  2  1  1  2  3  4
4  3  2  1  1  2  3  4
4  3  2  2  2  2  3  4
4  3  3  3  3  3  3  4
4  4  4  4  4  4  4  4

10
Почему четный случай отличается от нечетного? Нет причин, по которым все матрицы не могут следовать одному и тому же шаблону.
Грег Мартин

2
Поскольку вход должен был быть длиной боковой стенки, в этом случае есть разница между нечетным и четным. Вместо этого я решил использовать максимальное значение, но сохранил четную и нечетную разницу. Это может показаться странным и не может быть хорошим объяснением, но это объяснение почему есть разница. :-)
Стьюи Гриффин

2
Можем ли мы предположить -10 < n < 10?
Тит

2
Это нормально, если он не выглядит как идеальный квадрат, если только он численно выражен. Если строки со многими десятками шире, чем строки с несколькими десятками, то это нормально ...
Стьюи Гриффин

Ответы:


5

Желе , 18 17 байт

|1ŒḄfR«þ`
AÇạẋ¡CG

Попробуйте онлайн! или проверьте все контрольные примеры .

Как это работает

|1ŒḄfR«þ`  Helper link. Argument: k (positive integer)

|1         Take the bitwise OR with 1. This increments k if it is even.
  ŒḄ       Bounce; yield [1, 2, ..., k | 1, ..., 2, 1].
    fR     Filter range; remove elements not in [1, ..., k] from the array.
           This results in [1, 2, ..., k, ..., 2, 1] if k is odd and in
           [1, 2, ..., k, k, ..., 2, 1] if k is even.
        `  Pass the last return value as left and right argument to:
      «þ     Minimum table; take the minimum of each pair of elements in the
             generated array, returning a 2D array.


AÇạẋ¡CG      Main link. Argument: n

A            Take the absolute value of n.
 Ç           Call the helper link on the result.
     C       Complement; yield 1 - n.
    ¡        Conditional application:
   ẋ           If repeating the return value of Ç 1 - n times results in a non-
               empty array, i.e., if n < 1:
  ạ              Take the absolute differences of the generated integers and 1 - n.
      G      Grid; join columns by spaces, rows by linefeeds.

7

EXCEL: 126 байт

=MAX(MIN(MIN(CELL("row",RC)-1,CELL("col",RC)-1),MIN(((ABS(R1C1)-1)*2+3)-CELL("row",RC),((ABS(R1C1)-1)*2+3)-CELL("col",RC))),0)

Попробуйте онлайн *

Примечание: этот ответ использует нотацию R1C1. Если вы собираетесь попробовать это сами. Вы должны включить это в настройках Excel.

данная формула должна быть в каждой ячейке, присутствующей за пределами (2,2). Поместите желаемый размер пирамиды в (1,1).

быстрый экран-шапка формулы в действии:
введите описание изображения здесь

Вот дополнительная картинка веселья с условным форматированием!

* Обновление занимает очень много времени.


Это не обрабатывает негативные случаи или даже случаи должным образом. Также вы можете сократить код до =MAX(MIN(MIN(ROW()-1,COLUMN()-1),MIN(((ABS(A1)-1)*2+3)-ROW(),((ABS(A1)-1)*2+3)-COLUMN())),0)92 байт. Он все еще не обрабатывает случаи, и формула не может быть перемещена, так как ссылка на ячейку не заблокирована.
gtwebb 22.09.16

1
Больше игры в гольф те же проблемы, хотя. =MEDIAN(MIN(ROW()-1,COLUMN()-1),ABS(A1)*2+1-MAX(ROW(),COLUMN()),0)
gtwebb 22.09.16

@gtwebb спасибо, что сказал мне. Я должен исправить

-1. Это не работает Это не обрабатывает отрицательный ввод. Он не обрабатывает даже ввод. Если вы вводите эту формулу в каждую подходящую ячейку, вам нужно Rangeили вам понадобится более 126 байтов.
AdmBorkBork

7

Python 2, 109 99 98

n=input()
r=range(1,abs(n)+1)
l=r+r[~n|-2::-1]
for j in l:print[abs((n<0)*~-n+min(i,j))for i in l]

Создать список

l = [1,2,3,4,5,4,3,2,1]

и поиграть с этим немного.


edit: новый способ создания списка + thx Lynn для двух байтов


If n is even, then there will be 4 center numbers
Род

@ Род Нет, не будет. Что заставляет вас думать так?
pacholik

3
это одно из правил
Род

@ Род Ох. Всего несколько минут назад. Ред.
pacholik

2
Это не ново, просто не выделено: c
Rod

6

MATL , 26 24 байта

oXyG|to-:"TTYaQ]G0<?G+q|

Попробуйте онлайн! Или проверьте все контрольные примеры (слегка измененный код, служащий набором тестов).

объяснение

Код сначала строит выходной массив, предполагая положительный ввод n. Массив инициализируется как 1для нечетного ввода или как пустой массив для четного ввода (это создается как единичная матрица с размером, равным четности ввода). Затем повторяется следующее nвремя для четного ввода и n-1время для нечетного ввода: расширяйте массив, содержащий кадр 0, и добавляйте 1ко всем элементам.

Например, шаги для ввода n:

  • Начальный массив:

    1
    
  • Расширить с рамкой:

    0 0 0
    0 1 0
    0 0 0
    
  • Добавлять 1 :

    1 1 1
    1 2 1
    1 1 1
    
  • Расширить с рамкой:

    0 0 0 0 0
    0 1 1 1 0
    0 1 2 1 0
    0 1 1 1 0
    0 0 0 0 0
    
  • Добавлять 1 :

    1 1 1 1 1
    1 2 2 2 1
    1 2 3 2 1
    1 2 2 2 1
    1 1 1 1 1
    

Это дает правильный вывод для положительного ввода. Если вход отрицательный, массив необходимо изменить, добавив минус1 и приняв абсолютное значение:

    3 3 3 3 3
    3 2 2 2 3
    3 2 1 2 3
    3 2 2 2 3
    3 3 3 3 3

Вы можете наблюдать рост массива (модифицированный код для отображения промежуточных шагов) на MATL Online! Переводчик все еще бета. Если это не работает, нажмите «Выполнить» еще раз или перезагрузите страницу.

Код комментария

o        % Take input implicitly and push 0 if even or 1 if odd
Xy       % Identity matrix of that size. Gives either 1 or empty array
G|       % Absolute value of input
to-      % Subtract 1 if odd
:"       % For loop: repeat that many times
  TTYa   %   Add a frame of zeros in the two dimensions
  Q      %   Add 1 to all elements
]        % End for
G        % Push input again
0>       % is it negative?
?        % If so
  G      %   Push input again
  +      %   Add
  q      %   Subtract 1
  |      %   Absolute value
         % End if implicitly
         % Display implicitly

Я вижу, вы использовали код из вопроса об анимации. Потрясающе! Самое смешное, что этот код также выиграл бы в этом вопросе, даже если он длиннее вашей другой версии;).
Волшебная Урна Осьминога

1
@carusocomputing Да, это похоже: дублирование, отображение, пауза 1 секунда, четкий вывод :-)
Луис Мендо,

Кроме того, не знаю, почему, но любой вход выше 14 останавливается на 14. Отмените это, это ограничение онлайн-консоли «Время работы истекло»
Волшебная Урна Осьминога

@carusocomputing Ошибка говорит об истечении времени работы. Я полагаю, это займет слишком много времени для переводчика. Попробуйте уменьшить паузу, чтобы сказать .2секунды
Луис Мендо,

@carusocomputing Да, это тайм-аут на онлайн-переводчике. В настоящее время мы ограничиваем количество рабочих мест до 30 секунд. Как предполагает Луис, вы можете уменьшить время паузы
Suever

3

Python 2.7: 123 122 120 байт

пробники еще могут сохранить несколько байтов ...

from numpy import*
n=input()
N=abs(n)
e=N*2-N%2
a=ones([e,e])
for i in range(N):a[i:e-i,i:e-i]=(i+1)*(n>0)or-n-i
print a

edit1: N=abs(n)сохранить 1 байт

edit2: (i+1)*(n>0)or-n-iсохранить 2 байта


3

Haskell, 119 113 110 104 102 101 байт

f x|(h,t)<-splitAt(mod x 2)$[x,x-1..1]++[1.. -x]=foldl(\m n->(n#)<$>(n<$m)#m)[[y]|y<-h]t
x#y=x:y++[x]

Возвращает матрицу в виде списка целых чисел, например: f 2-> [[1,1,1,1],[1,2,2,1],[1,2,2,1],[1,1,1,1]].

Как это работает:

            [x,x-1..1]++[1.. -x]      -- make list from x down to 1 followed by
                                      -- 1 to (-x). One of the sublists will be
                                      -- empty. The resulting list contains the
                                      -- numbers of the pyramid from inside to out.
   (h,t)<-splitAt(mod x 2)            -- bind h to the first element if x is odd
                                      -- or to the empty list if x is even
                                      -- bind t to the rest (tail or full list)

foldl (     ) [[y]|y<-h] t            -- fold the following function into t with a
                                      -- starting value of [] if x is even or
                                      -- [[h]] if x is odd

   \m n ->                            -- the current matrix m with the next number
                                      -- n is transformed into a new matrix:

               (n#)<$>(n<$m)#m        -- prepend and append a n to 
                                      -- m prepended and append by a line of n's

x#y=x:y++[x]                          -- helper function to prepend and append an
                                      -- element x to a list y

2

Perl, 175 байт

Включает 1 байт для -p.

($t,$v,$w)=($_,(abs)x2);$k=$_.$k for 1..$v;map{$r.=$_ for(@v=1..$_-1),$_ x(2*$v---$w%2),reverse@v;$r.=$/}1..$v;$_=$r.~~reverse$r;eval"y/1-$w/$k/"if$t<0;$w%2&&s/

.*//||s;

;

(Есть завершающий символ новой строки, который я не знаю, как показать с уценкой, но он вам нужен).

Потребности -p, а также -M5.010и -Eдля запуска:

perl -pE '($t,$v,$w)=($_,(abs)x2);$k=$_.$k for 1..$v;map{$r.=$_ for(@v=1..$_-1),$_ x(2*$v---$w%2),reverse@v;$r.=$/}1..$v;$_=$r.~~reverse$r;eval"y/1-$w/$k/"if$t<0;$w%2&&s/

.*//||s;

;
' <<< 5

Черт, это слишком долго ... Я попробую другие подходы, когда у меня будет время.


Почему вы используете eval?
Тит

@Titus Потому y///что не интерполирует, так что используйте двойные кавычки для интерполяции $wи $kзатем evalдля выполнения y///.
Дада

2

Python 2, 109 байт

n=input()
a=abs(n)
s=a*2-a%2
r=range(s)
for y in r:print[(min,max)[n<0](x+1,s-x,y+1,s-y)-(n<0)*s/2for x in r]

2

J, 29 26 байт

1+**[:<./~**i.,2&|1&}.i.@-

использование

   f =: 1+**[:<./~**i.,2&|1&}.i.@-
   f 1
1
   f _1
1
   f 2
1 1 1 1
1 2 2 1
1 2 2 1
1 1 1 1
   f _2
2 2 2 2
2 1 1 2
2 1 1 2
2 2 2 2
   f 3
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
   f _3
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3

объяснение

i.Глагол диапазона выводит [0, 1, ..., n-1]для положительного nи [n-1, n-2, ..., 0]отрицательного, nчто полезно здесь.

1+**[:<./~**i.,2&|1&}.i.@-  Input: integer n
                         -  Negate n
                      i.@   Creates range for -n
               2&|          Take n modulo 2, returns 0 or 1
                  1&}.      If n is odd, drop the first value from the range for -n
                            Else do nothing and pass it unmodified
              ,             Append it to
            i.              The range for n
          *                 Get the sign of n
           *                Multiply elementwise with the joined ranges
    [:<./~                  Form a table of the minimum values of the range
  *                         Get the sign of n
   *                        Multiply elementwise with the joined ranges
1+                          Add 1 to each and return

2

Mathematica, 78 байт

Abs[Fold[ArrayPad[#,1,#2]&,Table[0,#,#]&@Mod[#,2,1],Range[Abs@#-1]]+1~Min~-#]&

объяснение

Table[0,#,#]&@Mod[#,2,1]

Сделать исходную матрицу: 1x1, если нечетное, 2x2, если четное.

Range[Abs@#-1]

Создайте список от 1 до abs (вход) - 1.

Fold[ArrayPad[#,1,#2]&, ..., ...]

Дополните исходный массив, используя вышеупомянутый список.

... +1~Min~-#

Добавьте 1 или -вход, в зависимости от того, что меньше.

Abs

Примените абсолютное значение ко всей матрице.


1

PHP, 177 157 байт

for($y=-$n=abs($z=$argv[1])+1;++$y<$n;)if($y&&($n&1||$y-1)){for($x=-$n;++$x<$n;)if($x&&($n&1||$x-1)){$v=max(abs($x),abs($y));echo$z<0?$v:$n-$v," ";}echo"
";}

бежать с php -r '<code>

перебирает строки и столбцы, печатает значения в зависимости от их расстояния до центра.

  • $n=abs($z)+1: +1Спасает пару +1и-1 в более поздних выражениях
  • циклы переходят от -$n+1(предварительного увеличения в условии!) к $n-1( -abs($z)к abs($z))
  • строка / столбец 0 (и для нечетного $n: 1) пропускаются
    ( $n&1верно для четных столбцов здесь! Помните +1?)
  • Печать для положительных $ z также извлекает выгоду из +1 .

1

Хаскелл, 191 183 173 169 168 байт

r=reverse;m=map
x!y=(((++)<*>(x.r)).).zipWith(++).m y
g n|n<0=m(m$abs.((n-1)+)).g$abs n|1<2=[id!id,tail!init]!!mod n 2=<<m r$r$m(\x->(x<$[1..x])++[x+1..n])[1..n]
g.(0-)

Использование:

mapM_ print $ (g.(0-)) 3

[1,1,1,1,1]
[1,2,2,2,1]
[1,2,3,2,1]
[1,2,2,2,1]
[1,1,1,1,1]

Спасибо Ними за 2 10 20 24 байта!


1
negateэто (0-)
Ними,

1
Вы можете изменить , fчтобы [id!id,tail!init]!!mod n 2затем рядный его в gи использовать 1<2охранник , чтобы связать промежуточный результат отрасли: g n| ... |q<-r<$>a n=([id!id,tail!init]!!mod n 2)q$a n. Вам не нужно имя для основной функции.
Ними,

1
О, ты aтоже можешь встроить (и переключиться обратно на 1<2охрану) g n| ... |1<2=[id!id,tail!init]!!mod n 2=<<map r$r$(\x->(x<$[1..x])++[x+1..n])<$>[1..n].
Ними,

1
Последний один на сегодня: m=mapв !: ...(++).m yи g: g n|n<0=m(m(abs.((n-1)+)))$g$abs n|1<2=[id!id,tail!init]!!mod n 2=<<m r$r$m(\x->(x<$[1..x])++[x+1..n])[1..n].
Ними,

1

JavaScript (ES6), 107 байт

(n,l=Math.abs(n+n-n%2))=>[...Array(l--)].map((_,i,a)=>a.map((_,j)=>(j=Math.min(i,l-i,j,l-j),n<0?-n-j:j+1)))

lэто размер массива. n<0?-n-j:j+1Кажется неуклюжим , но я не могу найти что - нибудь лучше.


1

Vim, 152 143 байта

Я уверен, что это может быть больше в гольфе, особенно те последние две строки, но мой мозг жарен.

D:let@z=@-/abs(@-)
a"nywYp:s/\d/x/g<C-v>
YggP:%s/.*/x \0 x<C-v>
:%s/x\+/\=@n-@z/g<C-v>
<Esc>v0"qda<C-r>=@z<0?1:@-*@z
<Esc>@=@-%2?"":"YPJYp"
@=@-*@z-1.(@-*@z>1?"@q":"")

Попробуйте онлайн!

Вот это в формате xxd с непечатными символами:

0000000: 443a 6c65 7440 7a3d 402d 2f61 6273 2840  D:let@z=@-/abs(@
0000010: 2d29 0a61 226e 7977 5970 3a73 2f5c 642f  -).a"nywYp:s/\d/
0000020: 782f 6716 0a59 6767 503a 2573 2f2e 2a2f  x/g..YggP:%s/.*/
0000030: 7820 5c30 2078 160a 3a25 732f 785c 2b2f  x \0 x..:%s/x\+/
0000040: 5c3d 406e 2d40 7a2f 6716 0a1b 7630 2271  \=@n-@z/g...v0"q
0000050: 6461 123d 407a 3c30 3f31 3a40 2d2a 407a  da.=@z<0?1:@-*@z
0000060: 0a1b 403d 402d 2532 3f22 223a 2259 504a  ..@=@-%2?"":"YPJ
0000070: 5970 220a 403d 402d 2a40 7a2d 312e 2840  Yp".@=@-*@z-1.(@
0000080: 2d2a 407a 3e31 3f22 4071 223a 2222 29    -*@z>1?"@q":"")

объяснение

Он строит пирамиду из центра, окружая номер центра xes:

x x x
x 5 x
x x x

Затем он заменяет xes следующим числом и xснова окружает его es:

x x x x x
x 4 4 4 x
x 4 5 4 x
x 4 4 4 x
x x x x x

...и так далее. Для четных чисел это делает то же самое, но начинается с базы 2х2.

Вот код "без гольфа". Это несколько необычно в том смысле, что я «записываю» макрос, вводя его в буфер (следовательно, все <C-v>s), а затем удаляя его в регистр, что является лучшим способом, которым я нашел для создания макроса без фактического нажатия клавиш.

D:let@z=@-/abs(@-)<CR>       " Delete the input (into @-) and set @z to -1 if @- is negative; otherwise 1
a                            " Enter insert mode to compose the macro
  "nyw                         " Copy the number under the cursor to @n
  Yp                           " Copy this line and paste it below
  :s/\d/x/g<C-v><CR>           " Replace digits in the copy with 'x'
  YggP                         " Copy this line and paste it at the top of the buffer
  :%s/.*/x \0 x<C-v><CR>       " Add an 'x' before and after each line
  :%s/x\+/\=@n-@z/g<C-v><CR>   " Replace all 'x'es (and 'xx'es etc.) with the next number
<Esc>v0"qd                   " Done composing macro; delete it into @q (buffer is now empty)
a<C-r>=@z<0?1:@-*@z          " Append the center number (1 or abs(@-)) to the buffer
<Esc>@=@-%2?"":"YPJYp"       " If the input is even, make a 2x2 square
@=@-*@z-1.(@-*@z>1?"@q":"")  " Execute the macro abs(@-)-1 times if it's > 1

0

PHP, 215 байт

for($i=0;$i<$m=($r=($s=abs($n=$argv[1]))*2-$s%2)**2;){$i%$r?:print"\n";$l=min(($x=$i%$r+1)<$s?$x:$x=$r-$x+1,($z=1+floor($i++/$r))<$s?$z:$z=$r-$z+1);$o=($n>0)?$l:$s+1-$l;echo str_pad(" ",1+strlen($s)-strlen($o)).$o;}

0

R, 112 байт

k=abs(n);l=2*k;m=diag(l);for(i in 1:k){m[i:(l+1-i),i:(l+1-i)]=i};if(n%%2==1){m=m[-k,-k]};if(n<0){m=abs(m-1+n)};m

Требуется целое число nв рабочей области, в противном случае запустите n=scan()дополнительные 8 байтов.

k=abs(n)
l=2*k
m=diag(l)                    # Initialize quadratic 2*|n| matrix
for(i in 1:k){
    m[i:(l+1-i),i:(l+1-i)]=i # Assign values to matrix elements according
                             # to their index
}
if(n%%2==1){
   m=m[-k,-k]                # If n is odd, delete middle row and column
}
if(n<0){
    m=abs(m-1+n)             # If n < 0, flip values
}
m                            # Print matrix
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.