เติบโต Ameobas แมนฮัตตัน


11

กราฟ *** ameoba **** เป็นต้นไม้ชนิดหนึ่งที่มีโหนดทั้งหมดมีค่าตั้งแต่ 0 ถึงจำนวนเต็มที่ไม่ใช่ค่าลบ N และโหนดใด ๆ ที่มีค่า x <N เชื่อมต่อกับ x + 1 โหนดที่แตกต่างที่มีค่า x + 1

กราฟ Ameoba สำหรับ N = 3: (หมายถึง A 3 )

อะเมบะ 3

โปรดทราบว่า 2 ของไม่ได้รับอนุญาตให้แบ่งปันใด ๆ ของ 3; สิ่งที่สามสามต้อง "เป็น" ต่อแต่ละ 2

ท้าทาย

งานของคุณคือการ "เหนี่ยว" กราฟ ameoba เหล่านี้แบบ inductively ในตาราง 2 มิติโดยลดระยะห่างระหว่างโหนดแมนฮัตตันอย่างโลภ:

  • กรณีฐาน: 00เป็นเพียงกราฟ
  • ขั้นตอนอุปนัย: N + 1ถูกสร้างขึ้นโดยซ้ำวาง N +1 ใหม่มูลค่าโหนดใกล้เคียงเป็นไปได้ที่จะไม่มีค่าในโหนดเอที่มีอยู่ไม่มีโครงสร้าง (สามารถปิดได้มากที่สุดเนื่องจากอาจมีการเติมจุดที่ใกล้ที่สุดแล้ว)

สำหรับขั้นตอนอุปนัยขั้นตอนทั่วไปที่คุณต้องปฏิบัติตามคือ:

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 โหนดซึ่งผลักดันมันสิ่งที่เกินกว่า8จะไกลเกินไปขอบคุณ Martin 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 เป็นอะมีบาตัวแรกที่มีตัวอักษรมากกว่าล้านตัว
isaacg

@ MartinBüttnerฉันทำขีด จำกัด 8 ซึ่งมีโหนดประมาณ 50k ยังคงมาก แต่หวังว่าจะจัดการได้

คำตอบ:


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

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

นี่คือตัวอย่างเอาต์พุตสำหรับn = 5:

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

อินพุต8ใช้เวลาประมาณ 4.5 นาที

สำหรับการแบ่งอัลกอริทึมของฉันอย่างรวดเร็ว:

ฉันใช้ตารางค้นหาสองรายการfและg. อันแรกเป็นเพียงแผนที่กระจัดกระจายที่มีเซลล์ที่ไม่ว่างเปล่า รายการหลังเป็นรายการที่มีคู่ค่าพิกัดทั้งหมดสำหรับแต่ละค่าเซลล์ (ฉันคิดว่าฉันไม่จำเป็นต้องติดตามค่าเดิมที่นี่) ฉันทำซ้ำผ่านพิกัดgเพื่อขยายทุกเซลล์จากการทำซ้ำครั้งล่าสุด เมื่อต้องการทำเช่นนั้นฉันซ้ำไปตามระยะทางของแมนฮัตตันสร้างเวกเตอร์ที่เป็นไปได้ทั้งหมดสำหรับแต่ละระยะทางและตรวจสอบว่าเซลล์ที่ได้นั้นยังว่างอยู่หรือไม่ (ในกรณีที่ฉันเติมเต็ม) ทำซ้ำจนกว่าจะมีเซลล์ใหม่เพียงพอ

เมื่อฉันทำฉันพบต่ำสุดและสูงสุดในการประสานงานและฉันสร้างตารางที่เหมาะสมซึ่งเต็มไปด้วยการมองขึ้นเซลล์ในg fที่เหลือก็แค่รวมทุกอย่างไว้ในสายเดียวที่มีตัวแบ่งบรรทัด


5

C - 309 305 301 275 ไบต์

หืมนานเกินไป ... ถ้ามีเพียงคนเดียวที่สามารถพิมพ์#Dหรืออะไรก็ได้แทนที่จะเป็น#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 (), อาร์เรย์ไม่สามารถจัดสรรใน stack ได้อีกต่อไปดังนั้นฉันมีอิสระที่จะใช้หน่วยความจำในลักษณะที่ไม่มีความเสี่ยง


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

ungolfed เล็กน้อย

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

ลักษณะการทำงาน: มันเป็น O (n!) ในระบบของฉันมากถึง n = 5 มันเป็นแบบทันที n = 6 ใช้เวลาหนึ่งวินาที n = 7 ใช้เวลาหนึ่งนาทีและ n = 8 ใช้เวลาหนึ่งชั่วโมง

รุ่นที่ไม่ใช่กอล์ฟ

ทดสอบ:

      {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 และใช้เพดาน นี่ให้เส้นผ่านศูนย์กลางของวงกลมสองเท่าดังนั้นเอาท์พุทที่เหมาะกับห้องที่ว่าง Mร้านนี้ใน
  • V←,⍳⍴Z←' '⍴⍨2/M: ให้เมทริกซ์ M-โดย-M Zของพื้นที่และเก็บไว้ใน นี้จะถือเอาท์พุท Vเก็บรายชื่อของพิกัดขององค์ประกอบทั้งหมดในส่วน
  • Z[G;G←⌈M÷2]←'0': ตั้งองค์ประกอบกลางของการZ0
  • Z⊢{... }¨⍳⍵: คืนค่าZหลังจากใช้ฟังก์ชันต่อไปนี้กับตัวเลข1เพื่อ:
    • ⍵∘{... }V/,Z=⍕⍵-1: สำหรับแต่ละองค์ประกอบZด้วยค่าของโหนดก่อนหน้า:
      • ⍵∘{... }⍺/⍺: สำหรับโหนดปัจจุบัน N ครั้ง
        • ⊃F[⍋+/¨|(F←V/⍨,Z=' ')-⊂⍺]: รับพื้นที่ว่างที่ใกล้กับโหนดปัจจุบันที่สุด
        • (... ⌷Z)←⍕⍵: และตั้งค่าพื้นที่Zนั้นเป็นค่าของโหนดปัจจุบัน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.