도와주세요, 나는 무한한 공장에 갇혀 있습니다!


26

이 도전은 Zachtronics 게임 Infinifactory 에서 느슨하게 영감을 얻었습니다 .

로 표시된 직사각형 컨베이어 그리드의 하향식보기가 제공됩니다 >v<^. 공간이없는 컨베이어가없는 셀이있을 수 있습니다. 예를 들면 다음과 같습니다.

> <vv    <
 v ^ >v v 
  >v^^>vv^
    ^>^ v 
>  v<v  >>
  >v v<^  

이 설정은 무한한 수의 공백으로 암시 적으로 둘러싸여 있습니다.

또한 그리드 왼쪽 상단 모서리에있는 컨베이어에 놓인 직사각형화물 조각의 치수가 제공됩니다. 당신의 임무는화물이 이제까지 멈춰 질 것인지 또는 루프에서 움직일 것인지를 알아내는 것입니다.

물론,화물은 한 번에 여러 컨베이어를 덮을 가능성이 높으므로 각 단계에서화물의 방향을 알아내는 규칙은 다음과 같습니다.

  1. 반대 컨베이어는 서로를 취소합니다. 따라서 3x2화물이 다음 패치 (명확하게하기 위해 하이픈과 파이프로 요약)를 덮으면 결과는 동일합니다.

    +---+   +---+   +---+
    |>>^|   |  ^|   |v^^|
    |^<<|   |^  |   |^^v|
    +---+   +---+   +---+
    

    이것들도 마찬가지입니다.

    +---+   +---+   +---+
    |v^<|   |   |   |><>|
    |>>>|   |>> |   |>><|
    +---+   +---+   +---+
    

    화물 아래 컨베이어의 정확한 위치는 관련이 없으므로 어느 쌍을 취소하든 상관 없습니다.

    이 취소는 다른 규칙보다 먼저 적용됩니다. 따라서 다른 규칙의 경우 최대 두 방향으로 만 컨베이어가 있습니다.

  2. 화물이 컨베이어를 전혀 덮지 않는 경우 (모든 컨베이어가 취소되기 때문에 공간 만 덮거나 그리드에서 완전히 움직여서 취소됨) 정지하게됩니다.
  3. 화물이 다른 쪽보다 한 방향으로 더 많은 컨베이어를 덮으면, 그 방향으로화물이 움직입니다. 예를 들어, 3x2화물이 다음 패치를 포함하는 경우

    >>
    ^>^
    

    >이상 이 있으므로 오른쪽으로 이동합니다 ^. 반면에, 그것이 덮여 있다면

    >>^
      ^
    

    >와 (과) 의 관계가 있기 때문에이 규칙은 적용되지 않습니다 ^.

  4. 이것은 인접한 방향 사이에 타이가있는 경우에만 남습니다 (반대 방향 사이의 타이는 취소되었을 것임). 이 경우화물은 이미 이동 축을 따라 움직이는 유지한다.이 예에서 오른쪽으로 이동하는 경우 또는 왼쪽으로 이동 3 ×화물 현재 패치를 덮고

    >>^
    ^  
    

    오른쪽으로 이동합니다. 패치가 위 또는 아래로 이동 한 경우에는 그 대신 위로 이동합니다. 이러한 종류의 충돌이 시뮬레이션의 첫 번째 단계에서 발생하면화물이 오른쪽으로 이동했다고 가정하십시오.

자세한 예

상단의 컨베이어 그리드와 3x2 카고를 고려하십시오. 다음은 프로세스의 단계별 시각화입니다. 각 단계는화물로 표시된 그리드가있는 그리드,화물로 #덮여있는 컨베이어를 표시하는 작은 상자, 취소 후 컨베이어가있는 다른 상자 및화물이 이동하는 위치를 결정하는 규칙으로 구성됩니다.

 ###vv    <    > <vv    <    > <vv    <    > <vv    <    > <vv    <    > <vv    <
 ###^ >v v     ###^ >v v      v ^ >v v      v ^ >v v      v ^ >v v      v ^ >v v 
   >v^^>vv^    ###v^^>vv^    ###v^^>vv^     ###^^>vv^      ###^>vv^      >###>vv^
     ^>^ v         ^>^ v     ### ^>^ v      ###^>^ v       ###>^ v        ###^ v 
 >  v<v  >>    >  v<v  >>    >  v<v  >>    >  v<v  >>    >  v<v  >>    >  v<v  >>
   >v v<^        >v v<^        >v v<^        >v v<^        >v v<^        >v v<^  

+---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+
|> <|  |   |  | v |  | v |  |  >|  |  >|  | >v|  | >v|  |>v^|  |> ^|  |v^^|  | ^^|
| v |  | v |  |  >|  |  >|  |   |  |   |  |   |  |   |  |  ^|  |   |  | ^>|  |  >|
+---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+  +---+

   Rule 3        Rule 4        Rule 3        Rule 4        Rule 4        Rule 3

 ================================================================================

 > <vv    <    > <###   <    > <vv    <
  v ###v v      v ###v v      v ###v v 
   >###>vv^      >v^^>vv^      >###>vv^
     ^>^ v         ^>^ v         ^>^ v 
 >  v<v  >>    >  v<v  >>    >  v<v  >>
   >v v<^        >v v<^        >v v<^  

+---+  +---+  +---+  +---+  +---+  +---+
|^ >|  |  >|  |vv |  | v |  |^ >|  |  >|
|v^^|  | ^^|  |^ >|  |  >|  |v^^|  | ^^|
+---+  +---+  +---+  +---+  +---+  +---+

   Rule 3        Rule 4        Rule 3

이 시점에서화물은 마지막 두 프레임 사이의 루프로 들어갑니다.

이제 2x3화물을 대신 고려하십시오.

 ##<vv    <    >##vv    <    > <vv    <    > <vv    <    > <vv    <    > <vv    <
 ## ^ >v v      ##^ >v v      ##^ >v v      v ^ >v v      v ^ >v v      v ^ >v v 
 ##>v^^>vv^     ##v^^>vv^     ##v^^>vv^     ##v^^>vv^      ##^^>vv^      >v^^>vv^
     ^>^ v         ^>^ v      ## ^>^ v      ## ^>^ v       ##^>^ v       ##^>^ v 
 >  v<v  >>    >  v<v  >>    >  v<v  >>    >##v<v  >>    > ##<v  >>    > ##<v  >>
   >v v<^        >v v<^        >v v<^        >v v<^        >v v<^        ## v<^  

 +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+
 |> |  |> |    | <|  |  |    |v |  |v |    | >|  | >|    |>v|  |>v|    |  |  |  |
 | v|  | v|    |v |  |v |    | >|  | >|    |  |  |  |    |  |  |  |    | v|  | v|
 |  |  |  |    | >|  |  |    |  |  |  |    |  |  |  |    | v|  | v|    |>v|  |>v|
 +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+    +--+  +--+

   Rule 4        Rule 3        Rule 4        Rule 3        Rule 3        Rule 3

 ================================================================================

 > <vv    <    > <vv    <    > <vv    <
  v ^ >v v      v ^ >v v      v ^ >v v 
   >v^^>vv^      >v^^>vv^      >v^^>vv^
     ^>^ v         ^>^ v         ^>^ v 
 > ##<v  >>    >  v<v  >>    >  v<v  >>
   ## v<^        ## v<^        >v v<^  
   ##            ##            ##
                 ##            ##
                               ##

 +--+  +--+    +--+  +--+    +--+  +--+
 | v|  | v|    |>v|  |>v|    |  |  |  |
 |>v|  |>v|    |  |  |  |    |  |  |  |
 |  |  |  |    |  |  |  |    |  |  |  |
 +--+  +--+    +--+  +--+    +--+  +--+

   Rule 3        Rule 4        Rule 2

마지막 단계에서,화물이 그리드 밖으로 이동했기 때문에 규칙 2가 적용되므로화물이 정지되고 루프가 발생하지 않습니다.

규칙과 가정

화물의 너비와 높이와 함께 위에서 설명한 컨베이어 그리드가 입력됩니다. 편리한 순서와 형식으로이 세 가지 매개 변수를 사용할 수 있습니다. 그리드를 들어, 선 하나의 문자열을 읽을 수있는이 수단은 각각의 그리드 셀이 여전히 문자로 표현되는만큼, 줄 바꿈 또는 다른 문자 또는 문자열의 배열, 또는 문자의 배열의 배열로 분리 >v<^하고 공백.

당신은 출력 A는해야 truthy의 적어도 두 개의 프레임 또는의 루프에서 설치 결과 경우 값을 falsy 값이화물은 휴식을 제공됩니다.

그리드가 공백이있는 사각형으로 채워지고화물이 처음 그리드에 맞춰 진다고 가정 할 수 있습니다.

STDIN (또는 가장 가까운 대안), 명령 행 인수 또는 함수 인수를 통해 입력을 받고 STDOUT (또는 가장 가까운 대안), 함수 리턴 값 또는 함수 (out) 매개 변수를 통해 결과를 출력하는 프로그램 또는 함수를 작성할 수 있습니다.

이것은 코드 골프이므로 가장 짧은 대답 (바이트)이 이깁니다.

테스트 사례

테스트 사례는 그리드로 그룹화됩니다.

Grid (2x2):

>v
^<

Width  Height  Loop?
1      1       True
1      2       True
2      1       True
2      2       False

Grid (3x3):

> v

^ <

Width  Height  Loop?
1      1       False
1      2       False
1      3       False
2      1       False
2      2       True
2      3       True
3      1       False
3      2       True
3      3       False

Grid (4x3):

>^>v
v^v 
^ <<

Width  Height  Loop?
2      2       False

Grid (6x5):

>v>v>v
^v^v^v
^v^v^v
^>^>^v
^<<<<<

Width  Height  Loop?
1      1       True
1      2       False
2      1       True
2      2       True
2      4       True
2      5       False
3      1       False
3      2       True
3      3       True
3      5       True
6      2       False
6      3       True
6      5       False

Grid (10x6):

> <vv    <
 v ^ >v v 
  >v^^>vv^
    ^>^ v 
>  v<v  >>
  >v v<^  

Width  Height  Loop?
1      1       False
2      3       False
2      6       False
3      2       True
5      4       False
6      1       True
10     6       False

추가 테스트 사례 집합으로 그리드가 공백으로 만 구성된 입력은 잘못된 결과를 가져와야합니다.

모든 테스트 사례를 수동으로 확인 했으므로 실수했다고 생각되면 알려주십시오.



4
내가 ... 트 위치 재생 포켓몬 플래시백을 얻고있다 @Fatalize
undergroundmonorail

"화물의 너비와 높이와 함께 위에서 설명한 컨베이어 그리드가 입력됩니다.이 세 가지 매개 변수는 편리한 순서와 형식으로 취할 수 있습니다." -컨베이어 그리드를 어레이 배열로 가져올 수 있습니까? 즉, 2x2 그리드 [^^/v<][[0,1] [0,1];[0,-1] [-1,0]]? 또는 STDIN, 문자열 입력, 문자 배열 입력 등인지 여부는 우리에게 달려 있지만 여전히 ^, v,> 및 <형식이어야합니까?
Glen O

@GlenO 줄 바꿈 (또는 다른 문자)으로 구분 된 문자열, 문자열 배열 또는 문자 배열을 사용할 수 있지만 각 셀은 여전히 ​​문자 ><^v나 공백 으로 표시되어야 합니다. 나는 그것을 명확히 할 것이다.
Martin Ender

계속되는 방향이 선택 사항 중 하나가 아닌화물이 충돌로 이동하면 어떻게됩니까? 즉, 오른쪽으로 움직이면 이제 위와 왼쪽 중에서 선택해야합니다.
Joshua

답변:


7

루비 306 298 251 204 198

->g,w,h{m=->y,x,d,v=[]{q=y,x
r=->s{([""]*h+g)[y+h,h].map{|l|(?x*w+l)[x+w,w]}.join.count s}
z=k=r[?v]-r[?^],j=r[?>]-r[?<]
q[d=[d,1,0][j*j<=>k*k]]+=z[d]<=>0
v&[q<<d]!=[]?q!=v[-1]:m[*q,v<<q]}
m[0,0,1]}

편집 : 몇 가지 놀라운 트릭을 적용하여 코드를 많이 단축 한 Ventero에게 감사드립니다!

입력과 출력

이 코드는 세 가지 매개 변수를 취하는 루비 함수를 나타냅니다.

  • 문자열 배열로 표시되는 그리드 (각 행은 다른 문자열 임)
  • 화물의 폭
  • 화물의 높이

1루프가있는 경우 nil(거친) 또는 화물이 놓인 경우 (거짓)을 반환합니다 .

테스트

여기에 모든 Martin 테스트가 통과되었습니다. http://ideone.com/zPPZdR

설명

코드에는 영리한 트릭이 없습니다. 아주 간단한 규칙 구현입니다.

아래 코드 move에는 규칙에 따라 이동하는 재귀 함수가 있습니다.

  • 루프의 경우 진실을 반환
  • 휴식시 거짓을 반환
  • 그렇지 않으면 다음 이동을 실행하기 위해 자체 호출

더 읽기 쉬운 버전이 여기에 있습니다 .

참고 : 골프 코드는 몇 가지 수정을 거쳐 더 이상 읽을 수있는 버전과 유사하지 않습니다.


r네 방향 외에 추가 항목이 포함되어 있는지 여부 는 중요하지 않으므로 r[y>=0&&x>=0&&g[y]&&g[y][x]]+=1몇 바이트를 저장해야합니다.
Ventero

나는 골프의 자유를 조금 더 가져 갔다. 마음에 들지 않기를 바란다. ideone.com/k69BmH
Ventero

@Ventero 와우, 당신은 코드에 놀라운 일을 해냈습니다. 해시를 람다로 변환하는 것에 대해 생각한 적이 없었습니다. 나는 프로그램을 단축하기 위해 내 아이디어 중 일부를 시도했지만 당신이 한 일 근처에는 없었습니다. 고마워요!
Cristian Lupascu

2
마이너스 인덱스를 약간 짧게 처리하여 200으로 줄였습니다. 지금은 그대로 두겠습니다. ideone.com/k69BmH
Ventero

2
실제로, 198 : ideone.com/ptKrzf :)
Ventero

8

파이썬 2, 207 바이트

def f(L,w,h,u=0,v=0,D=1,S=[]):a,b,c,d=map(`[r[u*(u>0):u+w]for r in L[v*(v>0):v+h]]`.count,"v^><");D=cmp(abs(a-b),abs(c-d))<D;T=u,v,D;return T in S or a-b|c-d and f(L,w,h,u+cmp(c,d)*D,v+cmp(a,b)*0**D,D,S+[T])

그리드를 행 목록으로 입력하십시오. 예 :

['>v>v>v', '^v^v^v', '^v^v^v', '^>^>^v', '^<<<<<']

너비와 높이가 뒤 따릅니다. 반품 0또는 True그에 따라.

설명

def f(L,          # Grid
      w,h,        # Width, height of cargo
      u=0,v=0,    # Position of top-left of cargo, initially (0, 0)
      D=1,        # Moving left/right = 1, up/down = 0
      S=[]        # Seen (pos, axis) pairs, initially empty
     ):     

     # Arrows under cargo - no need for "".join since we only need to count v^<>
     A = `[r[u*(u>0):u+w]for r in L[v*(v>0):v+h]]`

     # Count for each arrow
     a,b,c,d=map(A.count,"v^><")

     # Golfed form of abs(a-b) < abs(c-d) or (abs(a-b) == abs(c-d) and D == 1)
     D=cmp(abs(a-b),abs(c-d))<D
     T=u,v,D

     return (T in S                # Return True if (pos, axis) previously seen
             or a-b|c-d               # Return 0 if all conveyors cancel
             and f(L,w,h,             # Otherwise, recurse
                   u+cmp(c,d)*D,      # Update u if moving left/right
                   v+cmp(a,b)*0**D,   # Update v if moving up/down
                   D,
                   S+[T]          # Add (pos, axis) to seen
                  )
            )

cmp변수 에 할당 하여 단축 할 수 없습니까 ?
Blue

이미 방문한 위치를 확인하여주기를 감지하는 것으로 충분합니까? 규칙 4를 기반으로 다음 단계도 이전 방향의 영향을받을 수 있습니다. 따라서 동일한 위치에 두 번 도착할 수 있지만 이전 방향에 따라 다른 방향으로 이동하기 때문에 사이클이 없을 수 있습니다.
Reto Koradi

@muddyfish 그냥 깨질 것입니다
Sp3000

@RetoKoradi 희망찬 고정
Sp3000

예, D위치 키에 추가하면 됩니다.
Reto Koradi

8

줄리아 - 394 300 246 214 바이트

f(A,x,y)=(Z=sign;(S,T)=size(A);X=x+1;Y=y+1;G=fill(5,S+2y,T+2x);G[Y:S+y,X:T+x]=A;C=0G;D=1;while C[Y,X]!=D C[Y,X]=D;i,j=sum(i->1-[19 8]i%82%3,G[Y:Y+y-1,X:X+x-1]);D=Z(2i^2-2j^2+(i!=0)D);X+=Z(i+D*i);Y+=Z(j-D*j)end;D^2)

화물이 반복되는 경우 1을 반환하고 정지 한 경우 0을 반환합니다. 부울 상황에서 0과 1을 허용하지 줄리아 않는다는 점에서 그것은하지 "엄격"truthy / falsy ...하지만 난 값을 고려 x하는 bool(x)==truetruthy하고 bool(x)==falsefalsy됩니다.

입력 A은 문자형 배열 형식이어야합니다. 컨베이어 그리드를 복사 / 붙여 넣기하는 경우 적절한 형태로 가져와야합니다. 수동으로 처리하지 않아도하려면 다음을 사용하십시오.

A=foldl(hcat,map(collect,split("""(PASTE GRID HERE)""","\n")))'

분명한 (PASTE GRID HERE)경우 그리드 자체로 교체해야합니다. 각 줄의 끝에있는 공백을 다시 확인하여 실제로 모든 공백이 있는지 확인하십시오 (모든 행의 길이가 같은지 확인하지는 않음). 이 줄은 실제 솔루션 코드의 일부가 아니며 솔루션 코드를 조금 더 쉽게 사용할 수있는 편리한 코드입니다.

언 골프 드 :

function f(A,x,y)
  # Determine size of grid for use later
  (S,T)=size(A)
  # Initialise starting position (performed here to save characters)
  X=x+1
  Y=y+1
  # Create an expanded field that is functionally "spaces" (to provide
  # spaces at edges for the cargo to stop in)
  G=fill(5,S+2y,T+2x)
  # Put the conveyor grid into centre of the expanded field
  G[Y:S+y,X:T+x]=A
  # Create an array storing the most recent movement direction:
  # will use 1=horizontal, -1=vertical, 0=stopped
  C=0G
  # Initialise current direction (same system as C)
  D=1
  # Loop until it finds itself repeating a coordinate/direction pair
  while C[Y,X]!=D
    # Mark current coordinate/direction pair in array
    C[Y,X]=D
    # Determine the net coordinate pairing, stored in two variables
    # for golf purposes *SEE NOTE*
    i,j=sum(i->1-[19 8]i%82%3,G[Y:Y+y-1,X:X+x-1])
    # Determine new movement axis (if D=0, cargo stopped)
    D=sign(2i^2-2j^2+(i!=0)D)
    # Update X or Y depending on signs of D and the appropriate direction
    X+=sign(i+D*i)
    Y+=sign(j-D*j)
  end
  # if D=±1, return 1 (cargo is still moving), otherwise return 0
  return D^2
end

참고 : 1-[19 8]i%82%3내가 찾을 수있는 가장 효율적인 방법으로 5 개의 가능한 문자를 적절한 좌표 쌍에 매핑하도록 선택되었습니다. 이것은 또한 5를 사용하여 공백을 채우는 이유이기도합니다 . G이는로 매핑되는 한 자리 문자입니다 [0 0].

사용 예 :

julia> A=foldl(hcat,map(collect,split(""">v>v>v
       ^v^v^v
       ^v^v^v
       ^>^>^v
       ^<<<<<""","\n")))';

julia> f(A,2,1)
true

julia> f(A,3,3)
true

julia> f(A,5,2)
false

f(A,x,y)=보다 짧습니다 f=(A,x,y)->.
Alex A.

@AlexA. -사실이지만 f=골프를 마치면를 제거하고 익명의 기능으로 만들 것입니다.
Glen O

1
여러 매개 변수가있을 때 명명 된 함수와 익명 함수 인 경우 길이가 동일합니다. f()=()->.
Alex A.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.