Giúp tôi với, tôi bị mắc kẹt trong một nhà máy vô hạn!


26

Thử thách này được lấy cảm hứng lỏng lẻo từ trò chơi Zachtronics Infinifactory .

Bạn được cung cấp một cái nhìn từ trên xuống của một lưới băng tải hình chữ nhật, được đại diện bởi >v<^. Có thể có các ô không có băng tải, được biểu thị bằng khoảng trắng. Đây là một ví dụ:

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

Thiết lập này được bao quanh hoàn toàn bởi một số lượng không gian vô hạn.

Hơn nữa, bạn được cung cấp kích thước của một mảnh hàng hóa hình chữ nhật được đặt trên băng tải ở góc trên cùng bên trái của lưới. Nhiệm vụ của bạn là tìm hiểu xem hàng hóa có bao giờ dừng lại hay liệu cuối cùng nó sẽ di chuyển trong một vòng lặp.

Tất nhiên, hàng hóa có khả năng bao phủ một số băng tải cùng một lúc, vì vậy đây là các quy tắc để tìm ra hướng của hàng hóa trong mỗi bước:

  1. Băng tải đối diện triệt tiêu lẫn nhau. Vì vậy, nếu một hàng hóa 3x2 bao gồm bất kỳ bản vá nào sau đây (được phác thảo bằng dấu gạch nối và đường ống cho rõ ràng), kết quả sẽ giống nhau:

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

    Điều tương tự cũng xảy ra với những điều này:

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

    Vì vị trí chính xác của băng tải bên dưới hàng hóa là không liên quan, nên việc bạn hủy cặp nào không quan trọng.

    Hủy bỏ này được áp dụng trước các quy tắc khác. Do đó, đối với các quy tắc khác, sẽ chỉ có băng tải theo nhiều nhất hai hướng.

  2. Nếu hàng hóa hoàn toàn không bao gồm bất kỳ băng tải nào (vì tất cả các băng tải đều hủy, vì nó chỉ bao gồm các khoảng trống hoặc do nó di chuyển hoàn toàn khỏi lưới điện), nó sẽ dừng lại.
  3. Nếu hàng hóa bao phủ nhiều băng tải của một hướng hơn so với hướng khác, hàng hóa sẽ di chuyển theo hướng đó. Ví dụ: nếu hàng hóa 3x2 bao phủ các bản vá sau

    >>
    ^>^
    

    Nó sẽ di chuyển sang phải, bởi vì có nhiều >hơn ^. Mặt khác, nếu nó được bảo hiểm

    >>^
      ^
    

    quy tắc này sẽ không được áp dụng, bởi vì có một sự ràng buộc giữa >^.

  4. Điều này chỉ để lại các trường hợp trong đó có một ràng buộc giữa các hướng liền kề (một sự ràng buộc giữa các hướng ngược lại sẽ bị hủy bỏ). Trong trường hợp này, hàng hóa tiếp tục di chuyển dọc theo trục mà nó đã di chuyển. Ví dụ: nếu một hàng hóa 3x2 di chuyển phải hoặc di chuyển trái hiện đang bao phủ miếng vá

    >>^
    ^  
    

    nó sẽ di chuyển sang phải Nếu nó đã đến trên miếng vá này di chuyển lên hoặc xuống, bây giờ nó sẽ di chuyển lên. Nếu loại xung đột này xảy ra ở bước đầu tiên của mô phỏng, giả sử rằng hàng hóa đã được di chuyển sang phải.

Ví dụ chi tiết

Hãy xem xét lưới băng tải ở phía trên và một hàng hóa 3x2. Sau đây là một hình dung từng bước của quá trình. Mỗi bước bao gồm lưới, với hàng hóa được đại diện bởi #, một hộp nhỏ hiển thị các băng tải được bao phủ bởi hàng hóa, một hộp khác với các băng tải sau khi hủy và quy tắc xác định nơi hàng hóa di chuyển:

 ###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

Tại thời điểm này, hàng hóa đi vào một vòng lặp giữa hai khung hình cuối cùng.

Bây giờ hãy xem xét một hàng hóa 2x3 thay thế:

 ##<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

Ở bước cuối cùng, quy tắc 2 được áp dụng vì hàng hóa đã di chuyển khỏi lưới điện, do đó, nó sẽ dừng lại và sẽ không có một vòng lặp.

Quy tắc và giả định

Đầu vào của bạn sẽ là lưới băng tải như mô tả ở trên cùng với chiều rộng và chiều cao của hàng hóa. Bạn có thể lấy ba tham số này theo bất kỳ thứ tự và định dạng thuận tiện. Đối với lưới, điều này có nghĩa là bạn có thể đọc một chuỗi đơn với các dòng được phân tách bằng dòng mới hoặc các ký tự khác hoặc một chuỗi các chuỗi hoặc một mảng các ký tự, miễn là các ô lưới riêng lẻ vẫn được biểu thị bằng các ký tự >v<^và không gian.

Bạn nên đầu ra một truthy giá trị nếu kết quả thiết lập trong một vòng lặp của ít nhất hai khung hoặc một falsy giá trị nếu hàng hóa sẽ đến để nghỉ ngơi.

Bạn có thể giả định rằng lưới sẽ được đệm vào một hình chữ nhật có khoảng trắng và hàng hóa ban đầu sẽ vừa với lưới.

Bạn có thể viết chương trình hoặc hàm, lấy đầu vào qua STDIN (hoặc thay thế gần nhất), đối số dòng lệnh hoặc đối số hàm và xuất kết quả qua tham số STDOUT (hoặc thay thế gần nhất), tham số trả về hàm hoặc tham số hàm (out).

Đây là mã golf, vì vậy câu trả lời ngắn nhất (tính bằng byte) sẽ thắng.

Các trường hợp thử nghiệm

Các trường hợp thử nghiệm được nhóm theo lưới.

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

Là một tập hợp các trường hợp thử nghiệm bổ sung, hãy xem xét rằng bất kỳ đầu vào nào trong đó lưới chỉ bao gồm các khoảng trắng phải mang lại kết quả sai lệch.

Tôi đã kiểm tra tất cả các trường hợp kiểm tra theo cách thủ công, vì vậy hãy cho tôi biết nếu bạn nghĩ rằng tôi đã phạm sai lầm.



4
@Firthize Tôi nhận được Twitch chơi các đoạn hồi tưởng về Pokemon ...
ngầm trong

"Đầu vào của bạn sẽ là lưới băng tải như được mô tả ở trên cùng với chiều rộng và chiều cao của hàng hóa. Bạn có thể lấy ba thông số này theo bất kỳ thứ tự và định dạng thuận tiện nào." - điều này có nghĩa là chúng ta có thể có lưới băng tải được đưa vào như một mảng của các mảng? Đó là, một lưới 2x2 với [^^/v<]trở thành [[0,1] [0,1];[0,-1] [-1,0]]? Hoặc bạn có nghĩa là tùy thuộc vào chúng tôi cho dù đó là STDIN, đầu vào chuỗi, đầu vào mảng char, v.v., nhưng nó vẫn phải ở dạng ^, v,> và <?
Glen O

@GlenO Bạn có thể lấy một chuỗi phân tách dòng mới (hoặc ký tự khác), một chuỗi các chuỗi hoặc một mảng các ký tự, nhưng mỗi ô vẫn phải được biểu thị bằng các ký tự ><^vhoặc khoảng trắng. Tôi sẽ làm rõ điều đó.
Martin Ender

Vậy điều gì sẽ xảy ra nếu hàng hóa chuyển sang một cuộc xung đột trong đó hướng tiếp tục không phải là một trong những lựa chọn? Đó là, nếu nó di chuyển sang phải, và bây giờ phải chọn giữa lên và trái.
Joshua

Câu trả lời:


7

Ruby, 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]}

Chỉnh sửa: Cảm ơn rất nhiều đến Ventero, người đã rút ngắn mã rất nhiều bằng cách áp dụng một số thủ thuật tuyệt vời!

Đầu vào và đầu ra

Mã đại diện cho một chức năng ruby ​​có ba tham số:

  • lưới, được biểu diễn dưới dạng một chuỗi các chuỗi (mỗi hàng là một chuỗi khác nhau)
  • chiều rộng của hàng hóa
  • chiều cao của hàng hóa

Nó trả về 1(trung thực) trong trường hợp có vòng lặp, hoặc nil(giả) trong trường hợp hàng hóa được nghỉ.

Xét nghiệm

Ở đây nó đang vượt qua tất cả các bài kiểm tra của Martin: http://ideone.com/zPPZdR

Giải trình

Không có thủ thuật thông minh trong mã; đó là một cách thực hiện khá đơn giản của các quy tắc.

Trong đoạn mã dưới đây, movelà một hàm đệ quy thực hiện di chuyển theo các quy tắc và:

  • trả về sự thật trong trường hợp của một vòng lặp
  • trả lại giả trong trường hợp nghỉ ngơi
  • mặt khác gọi chính nó để thực hiện bước tiếp theo

Một phiên bản dễ đọc hơn có sẵn ở đây .

Lưu ý: mã đánh gôn đã trải qua một vài sửa đổi và không còn giống với phiên bản có thể đọc được.


Vì việc rcó chứa các mục bổ sung ngoài bốn hướng không thành vấn đề , r[y>=0&&x>=0&&g[y]&&g[y][x]]+=1nên lưu một vài byte.
Ventero

Tôi đã tự do chơi golf hơn một chút, hy vọng bạn không phiền: ideone.com/k69BmH
Ventero

@Ventero Wow, bạn đã làm những điều tuyệt vời cho mã. Tôi sẽ không bao giờ nghĩ về việc chuyển đổi băm thành lambda. Tôi đã thử một số ý tưởng của mình để rút ngắn chương trình, nhưng không ở đâu gần với những gì bạn đã làm. Cảm ơn rất nhiều!
Cristian Lupascu

2
Giảm xuống còn 200 thông qua việc xử lý các chỉ số tiêu cực ngắn hơn một chút, đoán bây giờ tôi sẽ để nó ở đó: ideone.com/k69BmH
Ventero

2
Trên thực tế, 198: ideone.com/ptKrzf :)
Ventero

8

Python 2, 207 byte

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

Nhập lưới dưới dạng danh sách các hàng, vd

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

tiếp theo là chiều rộng và chiều cao. Trả về 0hoặc Truetheo đó.

Giải trình

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

Bạn có thể rút ngắn nó bằng cách gán cmpcho một biến?
Màu xanh

Có đủ để phát hiện các chu kỳ bằng cách kiểm tra các vị trí đã truy cập không? Dựa trên quy tắc 4, bước tiếp theo cũng có thể bị ảnh hưởng bởi hướng trước đó. Vì vậy, có vẻ như bạn có thể đến cùng một vị trí hai lần, nhưng không có chu kỳ vì bạn di chuyển theo các hướng khác nhau dựa trên các hướng khác nhau trước đó.
Reto Koradi

@muddyfish Điều đó sẽ
hòa vốn

@RetoKoradi Hy vọng đã được sửa
Sp3000

Có, thêm Dvào phím vị trí nên làm điều đó.
Reto Koradi 17/08/2015

8

Julia - 394 300 246 214 byte

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)

Trả về 1 nếu vòng lặp hàng hóa và 0 nếu dừng. Đó không phải là "đúng" truthy / falsy, trong đó Julia không cho phép 0 và 1 trong những bối cảnh boolean ... nhưng tôi xem xét các giá trị xbool(x)==truelà truthy và bool(x)==falselà falsy.

Đầu vào Aphải có dạng một mảng ký tự. Nếu bạn sao chép / dán lưới băng tải, bạn sẽ cần đưa nó vào dạng thích hợp. Để giúp bạn không phải xử lý thủ công, hãy sử dụng như sau:

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

Trường hợp rõ ràng, (PASTE GRID HERE)nên được thay thế bằng chính lưới điện. Kiểm tra kỹ các khoảng trắng ở cuối mỗi dòng, để đảm bảo rằng nó thực sự có tất cả các khoảng trắng (nó không kiểm tra để đảm bảo rằng tất cả các dòng có độ dài bằng nhau). Lưu ý rằng dòng này không phải là một phần của mã giải pháp thực tế, chỉ là một đoạn mã thuận tiện để sử dụng mã giải pháp dễ dàng hơn một chút.

Ung dung:

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

Lưu ý: 1-[19 8]i%82%3đã được chọn để ánh xạ năm ký tự có thể vào các cặp tọa độ thích hợp theo phương pháp hiệu quả nhất mà tôi có thể tìm thấy. Đây cũng là lý do để sử dụng 5 để lấp đầy khoảng trắng khi tạo G- đó là ký tự một chữ số duy nhất ánh xạ tới [0 0].

Ví dụ về cách sử dụng:

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)=ngắn hơn f=(A,x,y)->.
Alex A.

@AlexA. - đúng, nhưng sau đó, có lẽ tôi sẽ xóa f=và biến nó thành một chức năng ẩn danh khi tôi hoàn thành việc đánh gôn.
Glen O

1
Nó sẽ có cùng độ dài nếu đó là hàm được đặt tên so với hàm ẩn danh khi có nhiều tham số. f()=so với ()->.
Alex A.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.