成長するマンハッタンアメオバス


11

*** ameobaグラフ****は、すべてのノードの値が0から非負の整数Nであり、値x <Nの特定のノードが値x +のx + 1個の異なるノードに接続するツリーのタイプです1。

N = 3のアメオバグラフ(A 3と表示

アメオバ3

2が3を共有することは許可されていないことに注意してください。正確に3つの3が各2に「属する」必要があります。

チャレンジ

あなたの仕事は、ノード間のマンハッタン距離を貪欲に最小化することによって、これらのアメオバグラフを2次元グリッドで誘導的に「成長」させることです。

  • 基本ケース: A 0は単なるグラフ0です。
  • 帰納的ステップ: A N + 1は、新しいN + 1値ノードを既存のA N構造内のN値ノードのできるだけ近くに繰り返し配置することによって生成されます。(最も近いスポットはすでに満たされている可能性があるため、可能な限り近くすることができます。)

誘導ステップの場合、従う必要がある一般的な手順は次のとおりです。

for each existing node P with value N:
    for each new N+1 valued node Q you need to connect to P: //this loops N+1 times
        find the set of vacant spots that are minimally distant from P //by Manhattan distance
        place Q in any of these vacant spots

(出力を区別できない別の手順で問題ありません。)

A 4の成長例:

A0 is always the same:

0

For A1 I happen to put the 1 to the right of the 0 (it has to go on one of the 4 open sides):

01

For A2 I happen to put the two 2's above and to the right of the 1:

 2
012


For A3 I find that one of the six 3's I must place cannot be directly next to a 2, so I put in one of the next closest places:

 3
323
0123
  33 <-- this 3 is distance two away from its 2

The process continues in A4. Note that I'm iterating over each 3 and placing four 4's next to it or as close as possible, then moving to the next 3 (the order of 3's does not matter):

 444
443444
4323444
4012344
 44334
  4444
   44

Always keep in mind that nodes cannot be "shared".

プログラム

作成するプログラムは、0から8までの数値(両端を含む)を取り、上記の誘導的成長パターンを使用して、その有効なameobaグラフを出力する必要があります。

8を超えて何が起こるかは問題ではありません。

(A 8は、それを推進している46234個のノードが含まれています。Aを超えた何か8は遠すぎるだろう。これに気付いためのマーティンBüttnerに感謝を。)

入力はstdinまたはコマンドラインから取得し、出力はstdoutまたはファイルに送信する必要があります。

例(上記から直接取得)

Input: 0
Output:

0

Input: 1
Output:

01

Input: 2
Output:

 2
012

Input: 3
Output:

 3
323
0123
  33

Input: 4
Output:

 444
443444
4323444
4012344
 44334
  4444
   44

*これらのタイプのグラフにはすでに名前が付いている場合があります。私はちょうどそれらを作ったと認めます。;)


要因の成長率を考慮して、質問をA35での停止から1メガバイトのファイルでの停止、または同様のものに変更できますか?A10は、100万人以上のキャラクターを持つ最初のアメーバです。
isaacg 14

@MartinBüttner約8万ノードの制限8を作成しました。まだたくさんありますが、うまくいけば管理可能です。

回答:


6

Mathematica、353 288 285 275バイト

n=Input[];f@_=" ";g={z={0,0}};i=f@z=0;For[r=Range,i++<n,g=Reap[(j=i;o={};For[d=0,j>0,o=Rest@o,If[o=={},o=Join@@({e={#,d-#},-e,e={d-#,-#},-e}&/@r@++d)];If[f[c=#&@@o+#]==" ",f@c=i;Sow@c;--j]])&/@g][[2,1]]];Riffle[(x=#;ToString@f@{x,#}&/@m~r~M)&/@r[m=Min@{g,0},M=Max@g],"
"]<>""

ゴルフをしていない:

n = Input[];
f@_ = " ";
g = {z = {0, 0}};
i = f@z = 0;
For[r = Range, i++ < n,
  g = Reap[(
        j = i;
        o = {}; 
        For[d = 0, j > 0, o = Rest@o,
         If[o == {}, 

          o = Join @@ ({e = {#, d - #}, -e, e = {d - #, -#}, -e} & /@  
              r@++d)
          ];  
         If[f[c = # & @@ o + #] == " ",
          f@c = i;
          Sow@c;
          --j 
          ]   
         ]   
        ) & /@ g
     ][[2, 1]] 
  ];  
Riffle[(
     x = #;
     ToString@f@{x, #} & /@ m~r~M
     ) & /@ r[m = Min@{g, 0}, 
    M = Max@g
    ], "
  "] <> ""

以下に出力例を示しますn = 5

      5
     5555     
    555555    
   5555555    
  555555555   
 55555555555  
5555554445555 
5555544444555 
 5555443305555
 55554432144555
 55555443234555
  5555544344555
   555554445555
    5555555555
      5555555 
       55555  
       55     

入力に8は約4.5分かかります。

アルゴリズムの簡単な説明:

私は2つのルックアップテーブルを使用して、だfg。最初のものは、空でないセルを含むスパースマップです。後者は、各セル値のすべての座標ペアを含むリストです(ここでは古いものを追跡する必要さえないと思います)。g最後の反復からすべてのセルを拡張するために、座標を繰り返し処理しています。そのために、マンハッタン距離を反復処理し、距離ごとに可能なすべてのベクトルを作成し、結果のセルがまだ空であるかどうかを確認します(この場合、塗りつぶします)。十分な新しいセルが作成されるまで繰り返します。

完了したら、最小座標と最大座標を見つけ、g適切なグリッドを作成します。このグリッドは、のセルを参照して塗りつぶされfます。残りは、すべてを改行で1つの文字列に結合するだけです。


5

C- 309305301275バイト

長すぎます...の#D代わりに1つしか入力できない場合#define、Cは本当に素晴らしいでしょう。もちろん、-Dコンパイラフラグは使用できますが、ソースファイル内の文字以外の文字を使用することは、私にとってはごまかしのようです。

実行手順:

注意してください!プログラムの起動後に最初に押すキーが入力になります。「0」から「8」以外の文字入力時に、誰が未定義のものが起こるかを知っています。

#define F(D,O)x=*r+O d;for(c=d;h*c--;x+=D)!g[x]?g[*w++=x]=l,--h:5;
L=400;g[1<<18];n;s;*r;*w;*m;h;l;d;x;main(c){n=getch()-32;r=w=g+L*L;for(l=g[*w++=80200]=16;l++<n;)for(m=w;r<m;r++)for(d=1,h=l-16;h;d++){F(L+1,-)F(L-1,-L*)F(-L+1,L*)F(~L,)}for(n=L*L;--n;)putch(n%L?g[n]+32:10);}

Ungolfed(しかし、すでに将来のゴルフについて考えている)バージョン:

void exit(int);

#define L 400

#define FIND(D, X0)   x = *pread X0 d; \
                for(c = d; c--; x+=D) { \
                    if(x%L == 0 || x%L == L-1 || x/L == 0 || x/L == L-1) \
                        exit(5); \
                    if(!g[x]) { \
                        g[*pwrite++ = x] = '0' + l; \
                        if(!--children) \
                            goto pnext; \
                    } \
                }

main()
{
    int n = getch() - '0';
    //char g[3] = {};
    char g[L*L] = {};
    int plist[46324];

    int *pwrite = plist, *pread = plist;
    *pwrite++ = L/2*L + L/2;
    g[*plist] = '0';
    int factorial = 1;
    int l,  c, parents, children, d, x;
    for(l = 1; l <= n; l++) {
        for(parents = factorial; parents--; pread++) {
            children = l;
            for(d = 1; ; d++) {
                FIND(L + 1, - )
                FIND(L - 1, -L* )
                FIND(-L + 1, +L* )
                FIND(-L - 1, + )
            }
            pnext:;
        }
        factorial *= l;
    }
    int i;
    for(i = L*L; i--; )
        putch(i%L ? (g[i] ? g[i] : ' ') : '\n');
}

編集:宣言をmain()の外に移動したため、配列をスタックに割り当てることができなくなったため、オーバーフローの危険なしにメモリを自由に使用できます。


2

ルビー-296

g=[s=' ']*d=10**6
$*[g[50500]=0].to_i.times{|c|d.times{|x|g[x]==c&&(r=1;a=c;(4.times{|v|r.times{|w|g[q=x+r*(1e3*(v-1-v/2)+v%2-v/2)+w*(1e3*~0**(v/2)+~0**v)]==s&&a>~0?(g[q]=c+1;a-=1):0}};r+=1)while~0<a)}}
g=g.join.scan(/.{1000}/)
g.map{|s|s[/\d/]&&(puts s[g.map{|s|s[/\A */].size}.min..-1].rstrip)}

わずかに手放しました。

g=[s=' ']*d=10**6 # Initialize a big 1d array as a 2d grid
$*[g[50500]=0].to_i.times{|c| # For n times
    d.times{|x| # For each index in the grid
        g[x]==c&&( # If the element at x is equal to the current growth stage, c
            r=1;   # Initial manhattan radius = 1
            a=c;   # a is number of times the ameoba must replicate
            (4.times{|v| # For each of the 4 sides of the manhattan diamond
                r.times{|w| # For each node in each side
                    # Spawn the 'c+1' ameoba's from the c ameobas... 
                    # The messy formula gives the index of the space in the grid to try spawning
                    g[q=x+r*(1e3*(v-1-v/2)+v%2-v/2)+w*(1e3*~0**(v/2)+~0**v)]==s&&a>~0?(g[q]=c+1;a-=1):0 
                }
            };
            r+=1 # Increase the raidus of the manhattan diamond by one
            ) while~0<a # while not enough ameoba's have been spawned
        )
    }
}
g=g.join.scan(/.{1000}/) # Join the 1d array into a huge string and slice it into rows
# Strip away the empty spaces all around the graph and print it
g.map{|s|s[/\d/]&&(puts s[g.map{|s|s[/\A */].size}.min..-1].rstrip)} 

2

APL(ダイアログ)(121)

{0::0⋄V←,⍳⍴Z←' '⍴⍨2/M←⌈4×.5*⍨3÷⍨+/!⍳⍵⋄Z[G;G←⌈M÷2]←'0'⋄Z⊣{⍵∘{⍵∘{+((⊃F[⍋+/¨|(F←V/⍨,Z=' ')-⊂⍺])⌷Z)←⍕⍵}¨⍺/⍺}¨V/⍨,Z=⍕⍵-1}¨⍳⍵}⎕

パフォーマンス特性:O(n!)です。私のシステムでは、n = 5までは瞬時です。n = 6は1秒、n = 7は1分、n = 8は1時間かかります。

非ゴルフバージョン

テスト:

      {0::0⋄V←,⍳⍴Z←' '⍴⍨2/M←⌈4×.5*⍨3÷⍨+/!⍳⍵⋄Z[G;G←⌈M÷2]←'0'⋄Z⊣{⍵∘{⍵∘{+((⊃F[⍋+/¨|(F←V/⍨,Z=' ')-⊂⍺])⌷Z)←⍕⍵}¨⍺/⍺}¨V/⍨,Z=⍕⍵-1}¨⍳⍵}⎕
⎕:
      5





           5555             
          555555            
         55555555           
        5555445555          
       555544445555         
      55554433445555        
     5555444323445555       
    5555544321455555        
     555554430455555        
     555555444555555        
       555555555555         
        5555555555          
         55555555           
          55555             
           555              

説明:

  • {... }⎕:キーボードから行を読み取り、評価して、結果を関数に渡します。
  • 0::0:他のコードでエラーが発生した場合、単一を返し0ます。これは、ノードが0のグラフのサイズを計算しようとすると数学が失敗するためです。これは、出力がである必要がある場合に起こります0。(以前のバージョンには⍵=0:0、(入力が0返された0場合はグラフを作成していました)が、0::0(試してみ0て失敗した場合は戻ります)は短くなります)
  • M←⌈4×.5*⍨3÷⍨+/!⍳⍵:出力が大まかな円であると仮定し(これは機能します)、からの階乗を合計1(=出力の面積)、3で除算(piに十分に近い)、平方根(出力の半径を与える)をとり、4を掛けますそして天井を取ります。これにより、円の直径が2倍になるため、出力に余裕があります。これをに保存しMます。
  • V←,⍳⍴Z←' '⍴⍨2/M:スペースのM行M列の行列を作成し、に保存しZます。これにより出力が保持されます。すべての要素の座標のリストをに保存しVます。
  • Z[G;G←⌈M÷2]←'0':の中間要素をZに設定し0ます。
  • Z⊢{... }¨⍳⍵Z次の関数を数値1に適用した後に戻ります
    • ⍵∘{... }V/,Z=⍕⍵-1Z前のノードの値を持つ各要素:
      • ⍵∘{... }⍺/⍺:現在のノードの場合、N回、
        • ⊃F[⍋+/¨|(F←V/⍨,Z=' ')-⊂⍺]:現在のノードに最も近い空き領域を取得し、
        • (... ⌷Z)←⍕⍵:そして、そのスペースをZ現在のノードの値に設定します。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.