맨하탄 아메 오 바스 성장


11

*** ameoba graph ****는 노드가 모두 0에서 음이 아닌 정수 N까지의 값을 갖는 트리 유형이며 x가 N 인 값을 가진 특정 노드는 x가 +1 인 별개의 노드에 연결됩니다. 1.

N = 3에 대한 아메 오바 그래프 (A 3으로 표시 )

아메 오바 3

2는 3을 공유 할 수 없습니다. 정확히 3 개의 3은 각각 2에 "포함"되어야합니다.

도전

당신의 임무는 노드 사이 의 맨해튼 거리를 탐욕스럽게 최소화함으로써 2 차원 그리드에서 이러한 아메 오바 그래프를 유도 적으로 "성장"시키는 것입니다 .

  • 자료의 경우 : 0 단순히 그래프이다 0.
  • 유도 단계 : N + 1이 반복적으로 존재하는 N의 값을 노드 최대한 가까이 새로운 N + 1 개 값 노드를 배치함으로써 생성되는 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 이외의 것은 너무 멀리 있습니다.이를 알아 낸 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 나는 약 50k 노드 인 8을 제한했습니다. 여전히 많지만 희망적으로 관리 할 수 ​​있습니다.

답변:


6

매스 매 티카, 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 분이 걸립니다.

내 알고리즘을 빠르게 분석하려면 :

두 개의 조회 테이블을 사용 f하고 g있습니다. 첫 번째는 비어 있지 않은 셀을 포함하는 스파 스 맵입니다. 후자는 각 셀 값에 대한 모든 좌표 쌍을 포함하는 목록입니다 (여기서는 이전 값을 추적 할 필요조차 없다고 생각합니다). g마지막 반복에서 모든 셀을 확장하기 위해 좌표를 반복합니다. 이를 위해 맨하탄 거리를 반복하고 각 거리에 가능한 모든 벡터를 만들고 결과 셀이 여전히 비어 있는지 확인합니다 (이 경우 채우기). 충분한 새 셀이 작성 될 때까지 반복하십시오.

완료되면 최소 및 최대 좌표를 찾은 다음 g적절한 셀을 f만듭니다. 에서 셀을 조회하여 채 웁니다 . 나머지는 줄 바꿈을 사용하여 모든 것을 단일 문자열로 결합합니다.


5

C- 309305301 275 바이트

Meh, 너무 길다 ... 만 입력 #D하거나 무언가 대신 무언가를 입력 할 수 있다면 #defineC는 정말 좋을 것이다. 물론 -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를 곱하십시오. 그리고 천장을 가져 가라. 이것은 원의 지름의 두 배를 제공하므로 출력은 여유 공간에 맞습니다. 에 저장하십시오 M.
  • V←,⍳⍴Z←' '⍴⍨2/M: Mxby 공간 행렬을 만들어에 저장합니다 Z. 출력이 유지됩니다. 에 모든 요소의 좌표 목록을 저장하십시오 V.
  • Z[G;G←⌈M÷2]←'0':의 중간 요소를 Z로 설정하십시오 0.
  • Z⊢{... }¨⍳⍵: Z숫자 1에 다음 함수를 적용한 후 return :
    • ⍵∘{... }V/,Z=⍕⍵-1: Z이전 노드의 값을 가진 각 요소에 대해 :
      • ⍵∘{... }⍺/⍺: 현재 노드의 경우 N 번
        • ⊃F[⍋+/¨|(F←V/⍨,Z=' ')-⊂⍺]: 현재 노드와 가장 가까운 여유 공간을 확보하십시오.
        • (... ⌷Z)←⍕⍵: 그 공간을 Z현재 노드의 값으로 설정 하십시오.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.