Gulung aku ular nomor!


34

Mengingat integer masukan n, menggambar ular nomor, yaitu, grid mengukur n x nterdiri dari angka-angka 1melalui n^2yang luka sekitar satu sama lain dengan cara sebagai berikut:

Masukan n = 3:

7 8 9
6 1 2
5 4 3

Masukan n = 4:

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

Masukan 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

(Terinspirasi oleh masalah ini dari Project Euler.)

Ini adalah , jawaban terpendek dalam byte menang!


4
Contoh: 4? Atau nomor genap.
TheLethalCoder

1
Bolehkah kita menganggap inputnya ganjil?
Tn. Xcoder



1
Lihat juga perlmonks.com/?node_id=487200 dengan banyak solusi dan tautan dalam balasan.
b_jonas

Jawaban:



18

C #, 203 202 196 193 178 bytes

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;}

Menyimpan satu byte berkat @StefanDelport.
Disimpan 22 byte berkat @FelipeNardiBatista.

Ini bekerja dengan pengamatan berikut bagaimana kotak dibangun:

Gambar kotak di mana n = 5

Seperti yang Anda lihat, setiap bit ditambahkan ke kotak sebelumnya. Untuk bilangan genap kita pergi ke kanan di mana kita berada, turun sampai satu lebih rendah dari tempat persegi itu dan kemudian pergi ke ujung. Angka ganjil pada dasarnya adalah kebalikannya, kita belok kiri, sampai ada satu di atas ketinggian saat ini dan kemudian ke ujung.

Versi Lengkap / Terformat:

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;bisa menjadi n>++i, tidak ada yang bisa saya lihat, +1.
LiefdeWen

1
n%2<1?2:1untuk 2-x%2? Saya belum mengujinya dalam C #, tetapi dalam C dan Python itu berhasil.
Felipe Nardi Batista

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; ....bermain golf sedikit
Felipe Nardi Batista

@FelipeNardiBatista Luar Biasa tidak akan pernah memikirkan keduanya! Terima kasih.
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++;
Felipe Nardi Batista

15

Dyalog APL, 70 56 45 41 byte

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

Cobalah online!

Bagaimana?

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

menghitung perbedaan antara indeks; 1dan ¯1untuk kanan dan kiri, ¯⍵dan untuk naik turun.

1,⊢,¯1,-datang sebagai 1 ⍵ ¯1 ¯⍵, +⍨⍴meregangkan array ini ke panjang ⍵×2, sehingga final 2/⍳dapat mengulangi masing-masing, dengan jumlah pengulangan meningkat setiap elemen kedua:

      (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

kemudian,

(⌈2÷⍨×⍨),

menambahkan elemen kiri atas spiral,

×⍨↑

batasi ⍵ 2 elemen pertama dari daftar jarak ini,

+\

melakukan jumlah kumulatif,

nilai indeks ( ⍵[i] = ⍵[⍵[i]]), untuk menerjemahkan matriks asli dengan indeks setiap elemen, dan akhirnya

,⍨⍴

bentuk sebagai ⍵×⍵matriks.


Bagi mereka yang tertarik, teknik ini dibahas panjang lebar dalam artikel bagus ini .
Jonah

9

C, 321 307 295 284 283 282 byte

Terima kasih kepada @Zachary T dan @Jonathan Frech karena bermain golf satu byte!

#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);}

Mengalokasikan array dua dimensi nol, kemudian mulai mengisinya dari suatu tempat di tengah. Terakhir nilai-nilai yang lebih besar dari nol tetapi lebih kecil dari atau sama dengan kuadrat input dicetak.

Cobalah online!

Diformat:

#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
Apakah mungkin untuk mengganti i,j,k,a,b,m;f(n){n*=n;int**l=calloc(a=m=3*n,4);dengan i,j,k,a,b,m,**l;f(n){n*=n;l=calloc(a=m=3*n,4);untuk menyimpan byte?
Zacharý

1
Anda mungkin dapat mengganti k<=n;dengan n>k;untuk menyimpan byte.
Jonathan Frech

6

PHP , 192 byte

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++]);

Cobalah online!

Cara yang sama membangun string, bukan array

PHP , 217 byte

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);

Cobalah online!


1
[-1,1][$d&1]->$d&1?:-1
Titus

@Titus Terima kasih, saya belum melihatnya
Jörg Hülsermann

1
Berikut adalah salah satu byte lagi: for(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);. Dan satu lagi: "%$l".d. Dan satu lagi: $x*$l*$a+$y*$l-> ($x*$a+$y)*$l.
Titus

1
Dan saya pikir dalam versi kedua Anda dapat menginisialisasi $ske garis bawah empuk (atau huruf atau digit); karakter itu akan ditimpa.
Titus

@Titus Terima kasih dan Anda dapat menggunakan .dpendekatan Anda sendiri untuk menghemat 2 byte
Jörg Hülsermann

6

PHP, 185 176 174 byte

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"
";}

Jalankan sebagai pipa dengan -nRatau uji secara online .

kerusakan

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 byte

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

Cobalah online!

Penggunaan ⎕io←1. Mulai dengan matriks 0-by-1 ( ⍪⍬). 2N kali ( ⍣2⍣⍵) menambahkan ketinggian matriks ( ≢⍵) ke setiap elemennya, menempatkan 1 2...heightdi kanannya ( ,⌸), dan memutar ( ⌽⍉). Ketika selesai, koreksi orientasi hasil ( ⊖∘⌽⍣⍵⌽) dan membalikkan angka dengan mengurangi dari N 2 +1 ( 1+×⍨-).


5

Mathematica, 177 byte

(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, tidak ada bawaan untuk ini di Mathematica?
Tn. Xcoder

5

C ++, 245 228 byte

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<<' ';}}

Cobalah online!

Fungsi menghitung dan mencetak nilai setiap angka dari matriks tergantung pada posisi x, y dengan menerapkan logika ini:

Perhitungan nilai ular tergantung pada posisi

Versi yang diformat :

#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 byte

Saya menginisialisasi array 2D dan menemukan titik awal, yang merupakan pusat untuk ganjil atau offset (-1, -1) untuk genap n, kemudian skala pola isian / kursor dengan angka 'cincin' saat ini. Saya merasa seperti kehilangan trik untuk menafsirkan arah, tetapi saya belum menemukan sesuatu yang lebih murah.

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

Cobalah online!

-2 Berkat Zachary T!


bagaimana Anda menghitung byte Anda? tab, spasi, dan baris baru juga diperhitungkan
Felipe Nardi Batista

Saya mengganti setiap \ n dan \ t dengan "" dan mengambil satu len (). Saya hanya menyalin di atas dan mengubahnya kembali untuk memastikan saya tidak mengubah apa pun dan lupa untuk menghitung ulang tetapi saya mendapat nomor yang sama. Apakah saya melewatkan sesuatu?
nocturama

Saya menghitung \tdan \nsebagai 1 byte dan masih mendapatkan 249 byte
Felipe Nardi Batista

e: ^^^ apakah ada metode yang lebih baik / lebih mudah yang harus saya gunakan? mereka tampaknya selalu digunakan secara bergantian kepada saya. ^^^ Aneh, ini yang saya dapatkan di 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

biasanya editor teks memberi tahu Anda berapa banyak karakter yang dipilih, jadi CTRL + A dan baca apa yang dikatakannya
Felipe Nardi Batista

5

Bahasa Wolfram (Mathematica) , (...) 83 byte

Byte diukur dalam UTF8, \[LeftFloor]( ) dan \[RightFloor]( ) masing-masing biaya 3 byte. Mathematica tidak memiliki rangkaian karakter byte khusus.

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}]&

Cobalah online!


Gunakan formulir tertutup untuk masing-masing dari 4 kasus, kemudian ambil secara maksimal untuk mendapatkan hasil yang diinginkan.

Mengembalikan array bilangan bulat 2D. Saya tidak yakin apakah ini diizinkan, dan meskipun telah ditanyakan dalam komentar , OP tidak menjawab.


4

Clojure, 206 byte

(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))))

Saya kira ini adalah awal yang baik, membangun papan secara berurutan untuk hash-map dan kemudian mem-partisi-nya menjadi n x ndaftar. Itu defmacroberakhir menjadi cukup lama, tetapi kode itu masih lebih pendek daripada tanpa. Apakah ada sintaks yang lebih succint untuk menggambarkannya?

Massal byte menghitung titik awal, dan membangun logika pencarian kecepatan berikutnya v. Mungkin sarang vecakan lebih baik, tetapi kemudian Anda memiliki dua indeks dan kecepatan untuk dilacak.


3

J , 41 byte

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

Cobalah online!

Melakukan hal yang sama dengan pengajuan APL ngn tetapi dimulai dengan matriks 1-per-1 dan mengulangi 2 × N − 2 kali.


Bisakah Anda meningkatkan pendekatan alternatif saya (sekarang terikat pada usia 41) untuk mengalahkan diri sendiri? Saya sudah memberikan golf terbaik saya sejauh ini, tetapi saya curiga setidaknya beberapa byte bisa dicukur.
Jonah

1

Python 165 (atau 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)

Ini menciptakan array numpy, kemudian memutarnya dan menambahkan sisi sampai ukuran yang benar tercapai. Pertanyaannya tidak menentukan apakah titik awal yang sama perlu digunakan untuk angka genap dan ganjil, jika bukan itu kasusnya maka garis if n%2==0:a=r(r(a))dapat dihapus, menghemat 21 byte.


1
ini bukan Python, ini Python + numpy
ASCII-only

@ Khusus ASCII Apakah ada daftar master nama bahasa yang dapat diterima di suatu tempat? Ini adalah python yang benar-benar valid.
user2699

Ini menggunakan perpustakaan, jadi Anda harus memasukkan nama perpustakaan juga ... seperti untuk bahasa yang diizinkan, bahasa apa pun dengan implementasi yang tersedia untuk umum yang diizinkan untuk dijalankan diizinkan
ASCII-only

@ ASCII-hanya di mana itu tertulis? Saya belum melihatnya selesai dengan sebagian besar jawaban python.
user2699

Ya, karena kebanyakan dari mereka tidak menggunakan numpy ... dan stdlib tidak dihitung sebagai perpustakaan eksternal
hanya ASCII

0

J , 41 byte

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

pemformatan standar

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

Pendekatan ini didasarkan pada At Play With J Volutes (APL Uriel menggunakan teknik serupa).

Tidak terduga dan cukup elegan untuk membenarkan jawaban kedua, pikir saya.

Pada dasarnya, kami tidak melakukan apa pun prosedural atau bahkan geometris. Sebagai gantinya, kami secara aritmatika membuat urutan sederhana yang, ketika pemindaian disimpulkan dan dinilai, memberikan urutan yang benar dari angka spiral dari kiri ke kanan, atas ke bawah. Kami kemudian membentuk itu menjadi matriks dan selesai.

Saya akan menambahkan penjelasan yang lebih rinci ketika waktu mengizinkan, tetapi artikel yang ditautkan menjelaskannya secara mendalam.

Cobalah online!


0

Python 3 (Stackless) , 192 188 179 150 byte

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)

Cobalah online!

(2y+1)2(yx)2yr

Disimpan 4-byte sejak rotasi fasor 90 derajat mudah dilakukan tanpa bilangan kompleks


0

R , 183 byte

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

Cobalah online!

Output adalah ular matriks (atau matriks ular, apa pun). Itu mungkin bukan metode yang paling efisien, dan itu mungkin bisa golf, tapi saya pikir itu layak ditampilkan. Sebenarnya saya agak bangga dengan ini!

Metode membangun matriks dari dalam ke luar, selalu menambahkan jumlah bilangan bulat tambahan yang sama dengan jumlah kolom dalam matriks sebelum menambahkan. Pola yang berikut adalah mengikat dengan kolom atau baris, sementara juga membalikkan beberapa nilai sehingga mereka ditambahkan dalam urutan yang benar.

193 byte

Persis sama seperti di atas, tetapi final badalah

matrix(b,x)

Cobalah online!

yang memberikan output yang sedikit lebih bersih, tetapi saya tidak melihat kriteria khusus untuk output, jadi jawaban pertama harus bekerja jika saya tidak salah.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.