Накрути меня номер змея!


34

Учитывая входное целое число n, нарисуйте числовую змею, то есть сетку, n x nсостоящую из чисел, 1проходящих через n^2друг друга, следующим образом:

Вход n = 3:

7 8 9
6 1 2
5 4 3

Вход n = 4:

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

Вход n = 5:

21 22 23 24 25
20  7  8  9 10
19  6  1  2 11
18  5  4  3 12
17 16 15 14 13

(Вдохновлен этой проблемой от Project Euler.)

Это , выигрывает самый короткий ответ в байтах!


4
Пример: 4? Или любое четное число.
TheLethalCoder

1
Можем ли мы предположить, что ввод нечетный?
г-н Xcoder



1
Смотрите также perlmonks.com/?node_id=487200 со многими решениями и ссылками в ответах.
b_jonas

Ответы:


43

MATL , 3 байта

1YL

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

объяснение

Встроенный ... ¯ \ _ (ツ) _ / ¯


31
Почему ... почему это встроенный?
TheLethalCoder

2
Я предполагаю, что это как-то связано с "Волшебным квадратом"?
Волшебная Урна Осьминога

8
@TheLethalCoder Поскольку Matlab была, и я подумал , что было бы полезно ( который она есть на самом деле )
Луис Mendo

18

C #, 203 202 196 193 178 байт

n=>{var r=new int[n,n];for(int o=n-2+n%2>>1,i=r[o,o]=1,c=2,w=o,h=o,b=1-2*(i%2),j;n>i++;){r[h,w+=b]=c++;for(j=0;j<i-1;++j)r[h+=b,w]=c++;for(j=0;j<i-1;++j)r[h,w-=b]=c++;}return r;}

Сохраненный байт благодаря @StefanDelport.
Сохранено 22 байта благодаря @FelipeNardiBatista.

Это работает следующим наблюдением за тем, как строятся квадраты:

Изображение квадрата, где n = 5

Как вы можете видеть, каждый бит добавляется к предыдущему квадрату. Для четных чисел мы идем направо от того места, где мы находились, до тех пор, пока они не оказались на единицу ниже, чем у квадрата, а затем остались до конца. Нечетные числа, по сути, противоположны, мы идем налево, до тех пор, пока не окажемся на единицу выше текущей высоты, а затем до самого конца.

Полная / Отформатированная версия:

using System;
using System.Linq;

class P
{
    static void Main()
    {
        Func<int, int[,]> f = n =>
        {
            var r = new int[n, n];
            for (int o = n - 2 + n % 2 >> 1, i = r[o, o] = 1, c = 2, w = o, h = o, b = 1 - 2 * (i % 2), j; n > i++;)
            {
                r[h, w += b] = c++;

                for (j = 0; j < i - 1; ++j)
                    r[h += b, w] = c++;

                for (j = 0; j < i - 1; ++j)
                    r[h, w -= b] = c++;
            }

            return r;
        };

        Console.WriteLine(String.Join("\n", f(3).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");
        Console.WriteLine(String.Join("\n", f(4).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");
        Console.WriteLine(String.Join("\n", f(5).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");

        Console.ReadLine();
    }
}

public static class ArrayExtensions
{
    public static T[][] ToJagged<T>(this T[,] value)
    {
        T[][] result = new T[value.GetLength(0)][];

        for (int i = 0; i < value.GetLength(0); ++i)
            result[i] = new T[value.GetLength(1)];

        for (int i = 0; i < value.GetLength(0); ++i)
            for (int j = 0; j < value.GetLength(1); ++j)
                result[i][j] = value[i, j];

        return result;
    }
}

1
++i<=n;могу стать n>++i, больше ничего не вижу, +1.
LiefdeWen

1
n%2<1?2:1к 2-x%2? Я не проверял это в C #, но в C и Python это работало.
Фелипе Нарди Батиста

1
for(int o=n-2+n%2>>1,i=r[o,o]=1,c=2,w=o,h=o,j;n>i++;){var b=i%2<1; ....немного поиграл в гольф
Фелипе Нарди Батиста

@FelipeNardiBatista Удивительно, никогда бы не подумал об этих двоих! Спасибо.
TheLethalCoder

1
var b=1-2*(i%2);r[h,w+=b]=c++;for(j=0;j<i-1;++j)r[h+=b,w]=c++;for(j=0;j<i-1;++j)r[h,w-=b]=c++;
Фелипе Нарди Батиста

15

Dyalog APL, 70 56 45 41 байт

,⍨⍴∘(⍋+\)×⍨↑(⌈2÷⍨×⍨),(+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳

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

Как?

(+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳

рассчитывает разницу между показателями; 1и ¯1направо и налево, ¯⍵и вверх и вниз.

1,⊢,¯1,-приходит как 1 ⍵ ¯1 ¯⍵, +⍨⍴растягивает этот массив до длины ⍵×2, так что финал 2/⍳может повторить каждый из них с увеличением числа повторений каждого второго элемента:

      (1,⊢,¯1,-) 4
1 4 ¯1 ¯4
      (+⍨⍴1,⊢,¯1,-) 4
1 4 ¯1 ¯4 1 4 ¯1 ¯4
      (2/⍳) 4
1 1 2 2 3 3 4 4
      ((+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳) 4
1 4 ¯1 ¯1 ¯4 ¯4 1 1 1 4 4 4 ¯1 ¯1 ¯1 ¯1 ¯4 ¯4 ¯4 ¯4

тогда,

(⌈2÷⍨×⍨),

добавляет верхний левый элемент спирали,

×⍨↑

ограничить первые ⍵ 2 элемента этого списка расстояний,

+\

выполняет накопительную сумму,

оценивает индексы ( ⍵[i] = ⍵[⍵[i]]), чтобы перевести исходную матрицу с индексами каждого элемента, и, наконец,

,⍨⍴

формы в виде ⍵×⍵матрицы.


Для тех, кто заинтересован, эта техника подробно обсуждается в этой превосходной статье .
Иона

9

C 321 307 295 284 283 282 байта

Спасибо @Zachary T и @Jonathan Frech за игру в гольф!

#define F for(b=a;b--;)l
i,j,k,a,b,m;**l;f(n){n*=n;l=calloc(a=m=3*n,4);F[b]=calloc(m,4);for(l[i=j=n][j]=a=k=1;n>k;++a){F[i][++j]=++k;F[++i][j]=++k;++a;F[i][--j]=++k;F[--i][j]=++k;}for(i=0;i<m;++i,k&&puts(""))for(j=k=0;j<m;)(a=l[i][j++])>0&&a<=n&&printf("%*d ",(int)log10(n)+1,k=a);}

Выделяет двумерный массив нулей, затем начинает заполнять его где-то посередине. Наконец, печатаются значения, которые больше нуля, но меньше или равны квадрату ввода.

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

отформатирован:

#define F for(b=a; b--;)l
i, j, k, a, b, m; **l;
f(n)
{
    n *= n;
    l = calloc(a=m=3*n, 4);

    F[b] = calloc(m, 4);

    for(l[i=j=n][j]=a=k=1; n>k; ++a)
    {
        F[i][++j] = ++k;
        F[++i][j] = ++k;
        ++a;

        F[i][--j] = ++k;
        F[--i][j] = ++k;
    }

    for(i=0; i<m; ++i, k&&puts(""))
        for(j=k=0; j<m;)
            (a=l[i][j++])>0 && a<=n && printf("%*d ", (int)log10(n)+1, k=a);
}

1
Можно ли заменить i,j,k,a,b,m;f(n){n*=n;int**l=calloc(a=m=3*n,4);на, i,j,k,a,b,m,**l;f(n){n*=n;l=calloc(a=m=3*n,4);чтобы сохранить байт?
Захари

1
Вы можете заменить k<=n;на, n>k;чтобы сохранить байт.
Джонатан Фрех

6

PHP , 192 байта

for($l=strlen($q=($a=$argn)**2)+$d=1,$x=$y=$a/2^$w=0;$i++<$q;${yx[$w%2]}+=$d&1?:-1,$i%$d?:$d+=$w++&1)$e[$x-!($a&1)][$y]=sprintf("%$l".d,$i);for(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);

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

Таким же образом построить строку вместо массива

PHP , 217 байт

for($l=strlen($q=($a=$argn)**2)+$d=1,$x=$y=($a/2^$w=0)-!($a&1),$s=str_pad(_,$q*$l);$i++<$q;${yx[$w%2]}+=$d&1?:-1,$i%$d?:$d+=$w++&1)$s=substr_replace($s,sprintf("%$l".d,$i),($x*$a+$y)*$l,$l);echo chunk_split($s,$a*$l);

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


1
[-1,1][$d&1]->$d&1?:-1
Тит

@ Titus Спасибо, я этого не видел
Йорг Хюльсерманн

1
Вот еще один байт: for(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);. И еще один: "%$l".d. И еще один: $x*$l*$a+$y*$l-> ($x*$a+$y)*$l.
Тит

1
И я думаю, что во второй версии Вы можете инициализировать $sс мягким подчеркиванием (или буквой или цифрой); этот символ будет перезаписан.
Тит

@Titus Спасибо, и вы можете использовать .dсвой собственный подход для сохранения 2 байтов
Йорг Хюльсерманн

6

PHP, 185 176 174 байта

for(;$n++<$argn**2;${xy[$m&1]}+=$m&2?-1:1,$k++<$p?:$p+=$m++%2+$k=0)$r[+$y][+$x]=$n;ksort($r);foreach($r as$o){ksort($o);foreach($o as$i)printf(" %".strlen($n).d,$i);echo"
";}

Запустите как трубу с -nRили проверьте это онлайн .

сломать

for(;$n++<$argn**2;     # loop $n from 1 to N squared
    ${xy[$m&1]}+=$m&2?-1:1, # 2. move cursor
    $k++<$p?:               # 3. if $p+1 numbers have been printed in that direction:
        $p+=$m++%2+             # increment direction $m, every two directions increment $p
        $k=0                    # reset $k
)$r[+$y][+$x]=$n;           # 1. paint current number at current coordinates

ksort($r);              # sort grid by indexes
foreach($r as$o){       # and loop through it
    ksort($o);              # sort row by indexes
    foreach($o as$i)        # and loop through it
        printf(" %".strlen($n).d,$i);   # print formatted number
    echo"\n";               # print newline
}

6

APL (Dyalog Classic) , 32 29 байт

1+×⍨-{⊖∘⌽⍣⍵⌽{⌽⍉,⌸⍵+≢⍵}⍣2⍣⍵⍪⍬}

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

Использует ⎕io←1. Начинается с матрицы 0 на 1 ( ⍪⍬). 2N times ( ⍣2⍣⍵) добавляет высоту матрицы ( ≢⍵) к каждому из ее элементов, помещает 1 2...heightее справа ( ,⌸) и поворачивает ( ⌽⍉). Когда это закончено, корректирует ориентацию результата ( ⊖∘⌽⍣⍵⌽) и переворачивает числа, вычитая их из N 2 +1 ( 1+×⍨-).


5

Mathematica, 177 байтов

(n=#;i=j=Floor[(n+1)/2];c=1;d=0;v={{1,0},{0,-1},{-1,0},{0,1}};a=Table[j+n(i-1),{i,n},{j,n}];Do[Do[Do[a[[j,i]]=c++;{i,j}+=v[[d+1]], {k,l}];d=Mod[d+1,4],{p,0,1}],{l,n-1}];Grid@a)&

8
Waaait, нет встроенного для этого в Mathematica?
г-н Xcoder

5

C ++, 245 228 байт

void f(){for(int i=0,j=-1,v,x,y,a,b;i<n;i++,j=-1,cout<<endl)while(++j<n){x=(a=n%2)?j:n-j-1;y=a?i:n-i-1;v=(b=y<n-x)?n-1-2*(x<y?x:y):2*(x>y?x:y)-n;v=v*v+(b?n-y-(y>x?x:y*2-x):y+1-n+(x>y?x:2*y-x));cout<<setw(log10(n*n)+1)<<v<<' ';}}

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

Функция вычисляет и печатает значение каждого номера матрицы в зависимости от ее положения x, y , применяя эту логику:

Расчет значений змей в зависимости от положения

Отформатированная версия :

#include <iostream>
#include <iomanip>
#include <math.h>

using namespace std;

void f(int n)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int value = 0;

            // Invert x and y when n is even
            int x = n % 2 == 0 ? n - j - 1 : j;
            int y = n % 2 == 0 ? n - i - 1 : i;
            if (y < (n - x))
            {
                // Left-top part of the matrix
                int padding = x < y ? x : y;
                value = n - 1 - padding * 2;
                value *= value;
                value += y >= x ? n - x - y : n + x - y - (y * 2);
            }
            else
            {
                // Right-bottom part of the matrix
                int padding = x > y ? n - x : n - y;
                value = n - padding * 2;
                value *= value;
                value += x > y ? y - padding + 1 : n + y - x - (padding * 2) + 1;
            }

            cout << setw(log10(n * n) + 1);
            cout << value << ' ';
        }

        cout << endl;
    }
}

int main()
{
    int n;
    while (cin >> n && n > 0)
    {
        f(n);
        cout << endl;
    }
}

5

Python 3 , 249 247 байт

Я инициализирую двумерный массив и нахожу начальную точку, которая является центром для нечетного n или смещения (-1, -1) для четного n, затем масштабирую шаблон заливки / курсора с текущим номером «кольца». Я чувствую, что мне не хватает уловки для интерпретации указаний, но я не придумал ничего более дешевого.

def f(n):
 M=[n*[0]for a in range(n)]
 x=y=n//2-1+n%2
 M[x][y]=i=s=1
 while 1:
  t=s*2
  for d in'R'+'D'*(t-1)+'L'*t+'U'*t+'R'*t:
   if i==n*n:print(*M,sep='\n');return
   v=[1,-1][d in'LU']
   if d in'UD':x+=v
   else:y+=v
   M[x][y]=i=i+1
  s+=1

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

-2 спасибо Захари Т!


как ты посчитал свои байты? табуляция, пробелы и переводы строк также имеют значение
Фелипе Нарди Батиста,

Я заменил все \ n и \ t на "" и взял len (). Я просто скопировал вышеупомянутое и переделал его, чтобы убедиться, что я ничего не изменил и забыл пересчитать, но я получил тот же номер. Я что-то пропустил?
Ноктурама

Я считаю \tи \nкак 1 байт и все еще получаю 249 байт
Фелипе Нарди Батиста

e: ^^^ есть ли лучший / более простой метод, который мне следует использовать? они всегда казались мне взаимозаменяемыми. Странно, это то, что я получаю в IDLE:len("def f(n): M=[n*[0]for a in range(n)] x=y=n//2-(n%2<1) M[x][y]=i=s=1 while 1: t=s*2 for d in'R'+'D'*(t-1)+'L'*t+'U'*t+'R'*t: if i==n*n:print(*M,sep='\n');return v=[1,-1][d in'LU'] if d in'UD':x+=v else:y+=v M[x][y]=i=i+1 s+=1") 223
nocturama

обычно текстовые редакторы сообщают вам, сколько символов выбрано, поэтому нажмите CTRL + A и прочитайте, что там написано
Фелипе Нарди Батиста,

5

Wolfram Language (Mathematica) , (...) 83 байта

Байт, измеренный в UTF8, \[LeftFloor]( ) и \[RightFloor]( ) стоит 3 байта каждый. Mathematica не имеет специального набора байтовых символов.

Table[Max[4x^2-Max[x+y,3x-y],4y
y-{x+y,3y-x}]+1,{y,b+1-#,b=⌊#/2⌋},{x,b+1-#,b}]&

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


Использует закрытую форму для каждого из 4 случаев, а затем максимально тщательно, чтобы получить желаемый результат.

Возвращает двумерный массив целых чисел. Я не уверен, разрешено ли это, и хотя об этом было сказано в комментариях , ФП не ответила.


4

Clojure, 206 байтов

(defmacro F[s]`(if(~'r(+ ~'p ~'v ~s))~'v ~s))
#(loop[i 1 p(*(quot(dec %)2)(inc %))v 1 r{}](if(<(* % %)i)(partition %(map r(range i)))(recur(inc i)(+ p v)({1(F %)-1(F(- %))%(F -1)(- %)(F 1)}v)(assoc r p i))))

Я полагаю, это неплохое начало, он строит доску последовательно в хэш-карту и затем разбивает ее на n x nсписки. Это defmacroоказалось довольно длинным, но код все еще короче, чем без него. Существует ли более лаконичный синтаксис для его описания?

Большая часть байтов вычисляет начальную точку и строит логику поиска следующей скорости v. Возможно, вложенное vecбудет лучше, но тогда вам нужно следить за двумя показателями и скоростями.


3

J , 41 байт

(]|.@|:@[&0](|.@|:@,.*/@$+#\)@]^:[1:)2*<:

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

Делает то же самое, что и представление APL в ngn, но начинается с матрицы 1 на 1 и повторяется 2 × N-2 раза.


Можете ли вы улучшить мой альтернативный подход (теперь привязанный к 41), чтобы победить себя? Пока я дал свой лучший гольф, но я подозреваю, что можно сбрить еще как минимум несколько байтов.
Иона

1

Python 165 (или 144)

from pylab import *
def S(n):
 a=r_[[[1]]];r=rot90;i=2
 while any(array(a.shape)<n):
  q=a.shape[0];a=vstack([range(i,i+q),r(a)]);i+=q
 if n%2==0:a=r(r(a))
 print(a)

Это создает массив пустышек, затем поворачивает его и добавляет сторону, пока не будет достигнут правильный размер. В вопросе не указано, нужно ли использовать одну и ту же начальную точку для четных и нечетных чисел, в противном случае if n%2==0:a=r(r(a))можно удалить строку , сэкономив 21 байт.


1
это не Python, это Python + numpy
только ASCII

@ ASCII-only Есть ли где-нибудь основной список допустимых названий языков? Это совершенно правильный питон.
user2699

Он использует библиотеку, поэтому вам нужно также включить имя библиотеки ... что касается разрешенных языков, то разрешен любой язык с общедоступной реализацией, которую вы можете запустить
только ASCII

@ Только для ASCII, где это написано? Я не видел, чтобы это было сделано с большинством ответов Python.
user2699

Да, потому что большинство из них не использует numpy ... и stdlib не считается внешней библиотекой
ASCII-only

0

J , 41 байт

,~$[:/:[:+/\_1|.1&,(]##@]$[,-@[)2}:@#1+i.

стандартное форматирование

,~ $ [: /: [: +/\ _1 |. 1&, (] # #@] $ [ , -@[) 2 }:@# 1 + i.

Этот подход основан на игре с игрой J (APL Уриэля использует похожую технику).

«Это неожиданно и достаточно элегантно, чтобы оправдать второй ответ, - подумал я.

По сути, мы не делаем ничего процедурного или даже геометрического. Вместо этого мы арифметически создаем простую последовательность, которая при суммировании и сортировке сканирования дает правильный порядок спирального числа слева направо, сверху вниз. Затем мы формируем это в матрицу и все готово.

Я добавлю более подробное объяснение, когда позволит время, но связанная статья объясняет это подробно.

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


0

Python 3 (Stackless) , 192 188 179 150 байт

lambda n:[list(map(v,list(range(t-n,t)),[y]*n))for t in[1+n//2]for y in range(n-t,-t,-1)]
v=lambda x,y,r=0:y>=abs(x)and(3-2*r+4*y)*y+x+1or v(y,-x,r+1)

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

(2Y+1)2-(Y-Икс)-2Yр

Сохранено 4 байта, поскольку поворот вектора на 90 градусов легко выполняется без комплексных чисел


0

R 183 байта

x=scan()
b=t(d<-1)
while(2*x-1-d){m=max(b)
y=(m+1):(m+sum(1:dim(b)[2]|1))
z=d%%4
if(z==1)b=cbind(b,y)
if(z==2)b=rbind(b,rev(y))
if(z==3)b=cbind(rev(y),b)
if(z==0)b=rbind(y,b)
d=d+1}
b

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

Выход - это матрица змеи (или матрица змеи, что угодно). Вероятно, это не самый эффективный метод, и он может быть в гольф, но я подумал, что это стоит показать. Я горжусь этим на самом деле!

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

193 байта

Точно такой же , как и выше, но окончательные bесть

matrix(b,x)

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

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

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