蛇を巻いてくれ!


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

回答:



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のおかげで1バイト節約できました。
@FelipeNardiBatistaのおかげで22バイト節約されました。

これは、正方形がどのように構築されるかの次の観察によって機能します。

n = 5の正方形の画像

ご覧のように、各ビットは前の正方形に追加されます。偶数の場合は、現在の場所の右側に移動し、正方形があった場所より1つ低くなり、最後まで左に移動しました。奇数は本質的に反対で、現在の高さより1つ上まで、最後まで1つ左に進みます。

フル/フォーマット済みバージョン:

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:12-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 Awesomeはこれら2つを考えたことはなかったでしょう!ありがとう。
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/⍳は各要素を繰り返すことができ、繰り返しカウントは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バイト

1バイトのゴルフをしてくれた@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);}

ゼロの2次元配列を割り当て、中央のどこかから埋め始めます。最後に、ゼロより大きく、入力の2乗以下の値が出力されます。

オンラインでお試しください!

フォーマット済み:

#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
タイタス

@タイタスありがとうございます私はそれを見ていません
ヨルクヒュルサーマン

1
もう1バイトですfor(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);。そしてもう一つ:"%$l".d。そしてもう1つ:$x*$l*$a+$y*$l-> ($x*$a+$y)*$l
タイタス

1
そして、私は2番目のバージョンでは$s、パディングされたアンダースコア(または文字または数字)に初期化できると思います。その文字は上書きされます。
タイタス

@Titusはありがとうございました、あなたが使用できる.d2バイト節約するために、独自のアプローチで
イェルクHülsermann

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回(⍣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の3249の 247バイト

2D配列を初期化し、奇数nの中心または偶数nのオフセット(-1、-1)である開始点を見つけて、現在の「リング」番号でフィル/カーソルパターンをスケーリングします。私は道順を解釈するためのトリックを逃しているように感じますが、もっと安いものは思いつきません。

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 Zachary Tに感謝します!


バイトをどのように数えましたか?タブ、スペース、改行も同様にカウント
フェリペナルディバティスタ

すべての\ nと\ tを ""に置き換え、len()を取りました。上記をコピーして、何も変更せず、再カウントするのを忘れないようにするために再コピーしましたが、同じ番号を取得しました。私は何か見落としてますか?
ノクタマ

私は1バイトとしてカウント\t\nていますが、それでも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言語(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つのケースのそれぞれに閉じた形式を使用し、最大値を慎重に取得して目的の結果を取得します。

整数の2D配列を返します。これが許可されているかどうかはわかりませんが、コメント尋ねられましたが、OPは返信しませんでした。


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方が良いかもしれませんが、その後、追跡する2つのインデックスと速度が得られます。


3

J、41バイト

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

オンラインでお試しください!

ngnのAPL提出と同じことを行いますが、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)

これにより、numpy配列が作成され、正しいサイズに達するまで回転して辺が追加されます。質問は、偶数と奇数に同じ開始点を使用する必要があるかどうかを指定しませんでした。そうでない場合は、行if n%2==0:a=r(r(a))を削除して21バイトを節約できます。


1
これは、Pythonではない、それはだパイソン+ numpyの
ASCIIのみの

@ ASCII-only受け入れ可能な言語名のマスターリストはどこかにありますか?これは完全に有効なpythonです。
user2699

ライブラリを使用するため、ライブラリの名前も含める必要があります...許可されている言語については、公開されている実装を実行できる言語であれば許可されます
ASCIIのみ

@ ASCII-onlyそれはどこに書かれていますか?私はほとんどのPythonの回答でそれを見たことがありません。
user2699

はい、それらのほとんどはnumpyのを使用していない...とSTDLIBは、外部ライブラリとしてカウントされませんので、
ASCIIのみ

0

J、41バイト

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

標準フォーマット

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

このアプローチはAt Play With J Volutesに基づいています(UrielのAPLは同様の手法を使用しています)。

Jの2番目の答えを正当化するのに十分なほど予想外でエレガントだと思いました。

基本的に、私たちは手続き的なことも幾何学的なこともしません。代わりに、スキャンを合計してグレードアップしたときに、左から右へ、上から下へのスパイラル番号の正しい順序を与える単純なシーケンスを算術的に作成します。次に、それをマトリックスに整形して完了します。

時間が許せば、より詳細な説明を追加しますが、リンクされた記事で詳しく説明します。

オンラインでお試しください!



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)

オンラインでお試しください!

これにより、出力は少しきれいになりますが、出力に特別な基準はありませんでしたので、間違っていなければ最初の答えは機能するはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.