Büyüyen Manhattan Ameobas


11

Bir *** ameoba grafiği ****, düğümlerin tümü 0'dan negatif olmayan bir tamsayı N'ye kadar değerleri olan ve x <N değerine sahip herhangi bir belirli düğüm, x + 1 değerlerine sahip x + 1 ayrı düğüme bağlanan bir ağaç türüdür. 1.

N Ameoba grafiktir 3 = (belirtilen bir 3 )

ameoba 3

2'lerin 3'lerin hiçbirini paylaşmasına izin verilmediğine dikkat edin; tam olarak üç 3'ün her birine 2 ait olması gerekir.

Meydan okuma

Senin görevin, düğümler arasındaki Manhattan mesafesini açgözlülükle minimize ederek bu ameoba grafiklerini 2 boyutlu bir ızgarada endüktif olarak "büyütmek" :

  • Temel durum: A 0 basitçe grafiktir 0.
  • İndüktif adım: Yeni N + 1 değerli düğümleri, mevcut A N yapısındaki N değer düğümlerine tekrar tekrar mümkün olduğunca yakın yerleştirerek bir N + 1 üretilir . (Mümkün olduğunca yakın olabilir, çünkü en yakın noktalar zaten dolu olabilir.)

Tümevarım adımı için izlemeniz gereken genel prosedür:

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

(Ayrılmaz çıktı ile farklı bir prosedür uygundur.)

A 4 için büyüme örneği :

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".

program

Yazdığınız program 0 ila 8 (dahil) arasında bir sayı almalı ve yukarıda açıklanan endüktif büyüme paternini kullanarak geçerli bir ameoba grafiği çıkarmalıdır.

8'in ötesinde ne olduğu önemli değil.

(A 8 , iten 46234 düğüm içerir. A 8'in ötesindeki her şey çok uzak olurdu. Bunu fark ettiği için Martin Büttner'e teşekkürler.)

Giriş stdin veya komut satırından gelmeli ve çıkış stdout veya bir dosyaya gitmelidir.

Örnekler (doğrudan yukarıdan alınmıştır)

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

* Bu tür grafiklerin zaten bir adı olabilir. Sadece uydurduğumu itiraf ediyorum. ;)


Faktöriyel büyüme oranı ışığında, soru A35'te durmaktan 1 Megabaytlık bir dosyada durmaya veya benzer bir şeye dönüştürülebilir mi? A10, bir milyondan fazla karaktere sahip ilk amiptir.
isaacg

@ MartinBüttner Yaklaşık 50 bin düğüm olan 8 limitini yaptım. Hala çok ama umarım yönetilebilir.

Yanıtlar:


6

Mathematica 353 288 285 275 bayt

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],"
"]<>""

Ungolfed:

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
    ], "
  "] <> ""

İşte örnek çıktı n = 5:

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

Giriş 8yaklaşık 4,5 dakika sürer.

Algoritmamın hızlı bir dökümü için:

İki arama tablosu kullanıyorum fve g. Birincisi, boş olmayan hücreleri içeren seyrek bir harita. İkincisi, her hücre değeri için tüm koordinat çiftlerini içeren bir listedir (bence burada eskilerini takip etmeme bile gerek yok). Her yinelemeyi gson yinelemeden uzatmak için koordinatları yineliyorum. Bunu yapmak için, her mesafe için tüm olası vektörleri oluşturarak ve ortaya çıkan hücrenin hala boş olup olmadığını kontrol ederek (bu durumda onu doldururum) Manhattan mesafelerini yineliyorum. Yeterli sayıda yeni hücre oluşturulana kadar tekrarlayın.

İşim bittiğinde, minimum ve maksimum koordinatı gbuldum ve içindeki hücreleri arayarak dolu uygun bir ızgara oluşturuyorum f. Gerisi her şeyi satır sonları ile tek bir dizeye katıyor.


5

C - 309305301875 bayt

Çok uzun ... sadece biri #Dyerine bir şey yazabilseydi #define, C gerçekten harika olurdu. Tabii -Dderleyici bayrakları mümkündür ama bu beni kandırıyor gibi görünüyor, kaynak dosyadakiler dışında karakterler var.

Koşu talimatları:

Dikkatli ol! Program başladıktan sonra bastığınız ilk tuş girişi oluşturur. Tanımlanmamış şeylerin ne olacağını bilen '0' - '8' dışında bir karakter girişi üzerine.

#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 (ama zaten gelecekteki golf hakkında düşünüyor) sürümü:

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

Düzenleme: Ben bildirimleri main () dışında taşındı beri, diziler artık yığın tahsis edilemez, bu yüzden taşma riski olmadan kesin bir şekilde bellek kullanmakta özgür olduğunu fark ettim.


2

Yakut - 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)}

Hafifçe soluksuz.

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 (Dyalog) (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}¨⍳⍵}⎕

Performans özellikleri: O (n!). Sistemimde n = 5'e kadar anlık; n = 6 bir saniye, n = 7 bir dakika ve n = 8 bir saat sürer.

Golfsiz sürüm

Ölçek:

      {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              

Açıklama:

  • {... }⎕: klavyeden bir satır oku, değerlendir ve sonucu işleve ilet.
  • 0::0: diğer kod bir hata verirse bir tane döndürün 0. Bunun nedeni, 0 düğümlü bir grafiğin boyutunu hesaplamaya çalışırken matematik başarısız olur, bu da çıktının ne zaman olması gerektiği gibi olur 0. (Önceki sürümde ⍵=0:0(giriş 0döndürülürse 0grafiği yaparsanız) vardı, ancak 0::0(sadece deneyin ve 0başarısız olursa döndürün) daha kısadır.)
  • M←⌈4×.5*⍨3÷⍨+/!⍳⍵: Çıkış varsayarak kaba bir daire (bu çalışmaları), den faktöriyeller toplamıdır 1için 4 ile çarpın kare kök salması (çıkışın yarı çap vermektir), (pi yeterince yakın) 3 ile (çıkış alanı =), ayırmak, ve tavanı al. Bu, dairenin çapının iki katını verir, böylece çıktı yedek odaya sığar. Bunu içinde saklayın M.
  • V←,⍳⍴Z←' '⍴⍨2/M: M-by-M uzay matrisi yapın ve saklayın Z. Bu çıktıyı tutacaktır. İçindeki tüm öğelerin koordinatlarının bir listesini saklayın V.
  • Z[G;G←⌈M÷2]←'0': Orta elemanı set Ziçin 0.
  • Z⊢{... }¨⍳⍵: return Z, sayılara aşağıdaki fonksiyonu uygulandıktan sonra 1için :
    • ⍵∘{... }V/,Z=⍕⍵-1: bir Zönceki düğümün değerine sahip her eleman için :
      • ⍵∘{... }⍺/⍺: geçerli düğüm için, N kez,
        • ⊃F[⍋+/¨|(F←V/⍨,Z=' ')-⊂⍺]: mevcut düğüme en yakın boş alanı elde edin,
        • (... ⌷Z)←⍕⍵: ve o boşluğu Zgeçerli düğümün değerine ayarlayın .
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.