救命,我被困在一个无限的工厂里!


26

Zachtronics游戏Infinifactory大致激发了这一挑战。

您将获得由表示的矩形输送机网格的俯视图>v<^。可能有一些没有传送带的小室,以空格表示。这是一个例子:

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

此设置隐含无限数量的空格。

此外,还给出了矩形货物的尺寸,该货物放在网格左上角的传送带上。您的任务是弄清楚货物是否曾经停下来,或者最终是否会成环运动。

当然,货物可能会一次覆盖多个输送机,因此以下是在每个步骤中确定货物方向的规则:

  1. 对面的传送带互相抵消。因此,如果3x2货物覆盖以下任何补丁(为清晰起见,用连字符和管道勾勒出轮廓),结果将是相同的:

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

    这些也是一样:

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

    由于输送机在货物下方的确切位置无关紧要,因此取消哪对对都没有关系。

    此取消在其他规则之前应用。因此,对于其他规则,最多只能有两个方向的传送带。

  2. 如果货物根本没有覆盖任何输送机(要么是因为所有输送机都取消了,或者是因为它只覆盖了空间,要么是因为它完全脱离了网格),所以货物就停了下来。
  3. 如果货物在一个方向上覆盖的输送机多于另一方向,则货物在该方向上移动。例如,如果3x2的货物覆盖了以下补丁

    >>
    ^>^
    

    它会向右移动,因为有更多的>^。另一方面,如果涵盖了

    >>^
      ^
    

    该规则将不适用,因为>和之间有联系^

  4. 这仅保留相邻方向之间有平局(相反方向之间的平局将被取消)的情况。在这种情况下,货物将继续沿其已经进入的轴移动。例如,如果向右移动向左移动的3x2货物现在覆盖了补丁

    >>^
    ^  
    

    它会向右移动。如果到达此补丁时它向上或向下移动,则现在将向上移动。如果在模拟的第一步就发生了这种冲突,则假定货物已经向右移动。

详细的例子

考虑顶部的传送带网格和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<^和空格。

你应该输出truthy值,如果在至少两帧或A的循环设定结果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

作为一组额外的测试用例,请考虑网格仅由空格组成的任何输入都必须产生虚假的结果。

我已经手动检查了所有测试用例,所以如果您认为我做错了,请告诉我。


10
试听

4
@Fatalize我越来越抽搐播放口袋妖怪倒叙...
undergroundmonorail

“您的输入将是如上所述的传送带网格以及货物的宽度和高度。您可以以任何方便的顺序和格式采用这三个参数。” -这是否意味着我们可以将输送机网格作为一个阵列接收?也就是说,2x2的网格[^^/v<]变为[[0,1] [0,1];[0,-1] [-1,0]]?还是您是说这取决于我们是STDIN,字符串输入,char数组输入等,但仍然必须采用^,v,>和<的形式?
Glen O

@GlenO您可以使用换行符(或其他字符)分隔的字符串,字符串数组或字符数组数组,但是每个单元格仍应由字符><^v或空格表示。我会澄清这一点。
马丁·恩德

那么,如果货物陷入冲突,而继续前进的方向不是选择之一,会发生什么呢?也就是说,如果它向右移动,现在必须在向上和向左之间进行选择。
约书亚

Answers:


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,他通过应用一些惊人的技巧大大缩短了代码!

输入输出

该代码表示​​一个带三个参数的ruby函数:

  • 网格,表示为字符串数组(每行是一个不同的字符串)
  • 货物宽度
  • 货物的高度

1如果有回圈,它将返回(真实),或者nil如果货物搁置,则返回(虚假)。

测验

它通过了马丁的所有测试:http : //ideone.com/zPPZdR

说明

代码中没有巧妙的技巧。这是规则的非常简单的实现。

在下面的代码中,move是一个递归函数,它根据规则进行移动,并且:

  • 循环时返回真实值
  • 休息时返回虚假
  • 否则调用自己执行下一步

此处提供更具可读性的版本。

注意:高尔夫球代码已进行了一些修改,不再类似于可读版本。


由于r除四个方向外是否包含其他条目都没有关系,因此r[y>=0&&x>=0&&g[y]&&g[y][x]]+=1应节省一些字节。
Ventero

我将高尔夫运动的自由放了一点,希望您不要介意:ideone.com/k69BmH
Ventero

@Ventero哇,您已经对代码做了很棒的事情。我从来没有想过将哈希转换为lambda。我正在尝试一些想法来缩短程序,但与您所做的事情相去甚远。非常感谢!
Cristian Lupascu 2015年

2
通过略微缩短负指数的处理将其降低到200,我现在暂时
Ventero

2
实际上,198:ideone.com/ptKrzf :)
Ventero

8

Python 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', '^<<<<<']

其次是宽度和高度。返回0True相应地。

说明

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变量来缩短它吗?
蓝色

通过检查已访问的位置来检测周期是否足够?根据规则4,下一步骤也可能受到先前方向的影响。因此,您有可能两次到达同一位置,但没有一个周期,因为您根据先前的不同方向朝不同的方向移动。
Reto Koradi

@muddyfish刚刚收支平衡
Sp3000

@RetoKoradi希望已修复
Sp3000,2015年

是的,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。这不是“严格” truthy / falsy,在布尔上下文朱莉娅不允许0和1 ...但我认为值x为此bool(x)==true是truthy和bool(x)==false是falsy。

输入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填充空格的原因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.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.