Code Golf:旋转迷宫

Tho*_*ing 20 language-agnostic code-golf rosetta-stone

Code Golf:旋转迷宫


制作一个包含迷宫文件的程序.迷宫的墙壁由#.迷宫必须包括一个球,由a o和任意数量的孔给出@.迷宫文件既可以通过命令行输入,也可以通过标准输入读入.请在您的解决方案中指定哪个.

然后您的程序执行以下操作:

1: If the ball is not directly above a wall, drop it down to the nearest wall.
2: If the ball passes through a hole during step 1, remove the ball.
3: Display the maze in the standard output (followed by a newline).
   Extraneous whitespace should not be displayed.
   Extraneous whitespace is defined to be whitespace outside of a rectangle 
   that fits snugly around the maze.
4: If there is no ball in the maze, exit.
5: Read a line from the standard input. 
   Given a 1, rotate the maze counterclockwise. 
   Given a 2, rotate the maze clockwise. 
   Rotations are done by 90 degrees. 
   It is up to you to decide if extraneous whitespace is allowed.
   If the user enters other inputs, repeat this step.
6: Goto step 1.
Run Code Online (Sandbox Code Playgroud)

您可以假设所有输入迷宫都已关闭.注意:在这方面,一个洞有效地充当了墙.

您可以假设所有输入迷宫都没有无关的空白.

按字符数计算的最短源代码获胜.


用javascript编写的示例:http: //trinithis.awardspace.com/rotatingMaze/maze.html


示例迷宫:

######
#o  @#
######
Run Code Online (Sandbox Code Playgroud)
###########
#o        #
# ####### #
###@      #
  #########
Run Code Online (Sandbox Code Playgroud)
###########################
#                         #
#       #     @           #
#       #         #      ##
#       #         ####o####
 #      #                 #
  #                       #
   #              #########
    #                     @
     ######################
Run Code Online (Sandbox Code Playgroud)

mob*_*mob 14

Perl,143(128)char

172 152 146 144 143个字符,

sub L{my$o;$o.=$/while s/.$/$o.=$&,""/meg;$_=$o}$_.=<>until/

/;{L;1while s/o / o/;s/o@/ @/;L;L;L;print;if(/o/){1-($z=<>)||L;$z-2||L&L&L;redo}}
Run Code Online (Sandbox Code Playgroud)

换行很重要.

使用标准输入并期望输入包含迷宫,然后是空行,然后是指令(1或2),每行一个指令.

说明:

sub L{my$o;$o.="\n"while s/.$/$o.=$&,""/meg;$_=$o}
Run Code Online (Sandbox Code Playgroud)

L是一个使用正则表达式将多行表达式$_逆时针旋转90度的函数.hobbs在我最喜欢的代码高尔夫解决方案中一直使用正则表达式.

$_.=<>until/\n\n/;
Run Code Online (Sandbox Code Playgroud)

将输入插入到第一对连续换行符(即迷宫)中$_.

L;1 while s/o / o/;s/o@/ */;
L;L;L;print
Run Code Online (Sandbox Code Playgroud)

要丢球,我们需要将o角色向下移动一行,因为它下面有一个空间.对于单个标量表达式来说,这很难做到,所以我们要做的是逆时针旋转迷宫,将球移动到"右".如果一个洞出现在球的"右侧",则球将落入洞中(它不在规范中,但我们可以将其更改@为a *以显示球落入哪个洞).然后在我们打印之前,我们需要将板顺时针旋转90度(或逆时针旋转3次),以便再次向下"向下".

if(/o/) { ... }
Run Code Online (Sandbox Code Playgroud)

如果迷宫中还有一个球,请继续.否则该块将结束,程序将退出.

1-($z=<>)||L;$z-2||L+L+L;redo
Run Code Online (Sandbox Code Playgroud)

阅读说明$z.对于指令"1"逆时针旋转板一次,对指令"2"逆时针旋转三次.

如果我们再使用3个字符+s/o[@*]/ */代替;s/o@/ */,那么我们可以支持多个球.

这个程序的简单版本,其中指令为"2"用于顺时针旋转迷宫,任何其他指令用于逆时针旋转,可以用128个字符完成.

sub L{my$o;$o.=$/while s/.$/$o.=$&,""/meg;$_=$o}$_.=<>until/

/;L;{1while s/o / o/+s/o@/ @/;L,L,L;print;if(/o/){2-<>&&L,L;redo}}
Run Code Online (Sandbox Code Playgroud)

  • 我仍然记得hobbs使用正则表达式_旋转表的方式.我希望噩梦很快就会消失. (4认同)

Nab*_*abb 8

GolfScript - 97个字符

n/['']/~{;(@"zip-1%":|3*~{{." o"/"o "*"@o"/"@ "*.@>}do}%|~.n*."o"/,(}{;\~(2*)|*~\}/\[n*]+n.+*])\;
Run Code Online (Sandbox Code Playgroud)

这并没有像我希望的那样(可能在以后).

(这些是我的笔记而不是解释)

n/['']/~                             #[M I]
{
;(@                                  #[I c M]
"zip-1%":|3*~                        #rotate
{{." o"/"o "*"@o"/"@ "*.@>}do}%      #drop
|~                                   #rotate back
.n*                                  #"display" -> [I c M d]
."o"/,(                              #any ball? -> [I c M d ?]
}{                                   #d is collected into an array -> [I c M]
;\~(2*)|*~                           #rotate
\                                    #stack order
}/
\[n*]+n.+*])\;                       #output
Run Code Online (Sandbox Code Playgroud)


Hos*_*ork 8

Rebmu:298个字符

我正在修补自己在Code Golf语言设计中的实验!我还没有将矩阵技巧扔进标准包中,复制GolfScript的想法可能会有所帮助.但是现在我正在努力改进基本的噱头.

无论如何,这是我的第一次尝试.代码中需要四个内部空间,但不需要换行:

.fFS.sSC L{#o@}W|[l?fM]H|[l?m]Z|[Tre[wH]iOD?j[rvT]t]
Ca|[st[xY]a KrePC[[yBKx][ntSBhXbkY][ntSBhYsbWx][xSBwY]]ntJskPCmFkSk]
Ga|[rtYsZ[rtXfZ[TaRE[xY]iTbr]iTbr]t]B|[gA|[ieSlFcA[rnA]]]
MeFI?a[rlA]aFV[NbIbl?n[ut[++n/2 TfCnIEfLtBRchCbSPieTHlTbrCHcNsLe?sNsZ]]
gA|[TfCaEEfZfA[prT][pnT]nn]ulBbr JmoADjPC[3 1]rK4]
Run Code Online (Sandbox Code Playgroud)

它可能看起来像是我的键盘上的猫.但是,一旦你通过一个节省空间的小技巧(字面意思是节省空间)称为"糊涂",它就不那么糟糕了.这个想法是Rebmu不区分大小写,因此使用大写运行的交替来压缩符号.而不是FooBazBar => foo baz bar我应用不同的含义. FOObazBAR => foo: baz bar(第一个令牌是分配目标)vs fooBAZbar => foo baz bar(所有普通令牌).

运行unmush时,您可以获得更多可读性,但扩展到488个字符:

. f fs . s sc l: {#o@} w: | [l? f m] h: | [l? m] z: | [t: re [w h] i od? 
j [rv t] t] c: a| [st [x y] a k: re pc [[y bk x] [nt sb h x bk y] [nt sb 
h y sb w x] [x sb w y]] nt j sk pc m f k s k] g: a| [rt y s z [rt x f z 
[t: a re [x y] i t br] i t br] rn t] b: | [g a| [ie s l f c a [rn a]]] 
m: e fi? a [rl a] a fv [n: b i bl? n [ut [++ n/2 t: f c n ie f l t br 
ch c b sp ie th l t br ch c n s l e? s n s z]] g a| [t: f c a ee f z f 
a [pr t] [pn t] nn] ul b br j: mo ad j pc [3 1] r k 4]
Run Code Online (Sandbox Code Playgroud)

Rebmu也可以扩展它.也有冗长的关键字(first而不是fs),你可以混合和匹配.这是函数定义和一些注释:

; shortcuts f and s extracting the first and second series elements
. f fs
. s sc 

; character constants are like #"a", this way we can do fL for #"#" etc
L: {#o@}

; width and height of the input data
W: | [l? f m] 
H: | [l? m]

; dimensions adjusted for rotation (we don't rotate the array)
Z: | [t: re [w h] i od? j [rv t] t] 

; cell extractor, gives series position (like an iterator) for coordinate
C: a| [
    st [x y] a 
    k: re pc [[y bk x] [nt sb h x bk y] [nt sb h y sb w x] [x sb w y]] nt j 
    sk pc m f k s k
] 

; grid enumerator, pass in function to run on each cell
G: a| [rt y s z [rt x f z [t: a re [x y] i t br] i t br] t] 

; ball position function
B: | [g a| [ie sc l f c a [rn a]]]
Run Code Online (Sandbox Code Playgroud)

W是width函数,H是原始数组数据的高度.数据永远不会旋转......但是有一个变量j告诉我们应该应用多少90度的右转弯.

函数Z为我们提供了在考虑旋转时调整后的大小,函数C采用坐标对参数并将一系列位置(类似于指针或迭代器)返回到该坐标对的数据中.

有一个数组迭代器G,你将函数传递给它,它将为网格中的每个单元调用该函数.如果您提供的函数返回一个值,它将停止迭代,迭代函数将返回该值.该功能B扫描迷宫中的球并返回坐标(如果找到),或none.

这是带有一些评论的主循环:

; if the command line argument is a filename, load it, otherwise use string
m: e fi? a [rl a] a 

; forever (until break, anyway...)
fv [
    ; save ball position in n 
    n: B

    ; if n is a block type then enter a loop
    i bl? n [

        ; until (i.e. repeat until)
        ut [
            ; increment second element of n (the y coordinate)
            ++ n/2 

            ; t = first(C(n))
            t: f C n

            ; if-equal(first(L), t) then break
            ie f l t br

            ; change(C(B), space)
            ch C B sp

            ; if-equal(third(L),t) then break 
            ie th L t br 

            ; change(C(n), second(L))
            ch C n s L 

            ; terminate loop if "equals(second(n), second(z))"
            e? s n s z
         ]
     ] 

     ; iterate over array and print each line
     g a| [t: f c a ee f z f a [pr t] [pn t] nn]

     ; unless the ball is not none, we'll be breaking the loop here...
     ul b br 

     ; rotate according to input
     j: mo ad j pc [3 1] r k 4
]
Run Code Online (Sandbox Code Playgroud)

关于这个计划并没有那么特别聪明.这是我的想法的一部分,这是为了看看什么样的压缩可以得到简单,无聊的方法,不依赖任何技巧.我认为它展示了Rebmu的一些新颖潜力.

看看更好的标准库如何影响解决方案的简洁性将会很有趣!

GitHub上提供最新的最新评论来源:rotating-maze.rebmu


Jer*_*iko 6

Ruby 1.9.1 p243

355 353个字符

我是Ruby的新手,所以我相信这可能会短得多 - 可能是我缺少的一些细微差别.

执行时,映射文件的路径是它读取的第一行.我试图让它成为执行参数的一部分(会保存3个字符),但有问题:)

简短版本:

def b m;m.each_index{|r|i=m[r].index(?o);return r,i if i}end;def d m;x,y=b m;z=x;
while z=z+1;c=m[z][y];return if c==?#;m[z-1][y]=" "; return 1 if c==?@;m[z][y]=?o;end;end;
def r m;m.transpose.reverse;end;m=File.readlines(gets.chomp).map{|x|x.chomp.split(//)};
while a=0;w=d m;puts m.map(&:join);break if w;a=gets.to_i until 0<a&&a<3;
m=r a==1?m:r(r(m));end
Run Code Online (Sandbox Code Playgroud)

详细版本:

(我在压缩版本中有所改变,但你明白了)

def display_maze m
 puts m.map(&:join)
end

def ball_pos m
  m.each_index{ |r|
    i = m[r].index("o")
    return [r,i] if i
  }
end

def drop_ball m
  x,y = ball_pos m
  z=x
  while z=z+1 do
    c=m[z][y]
    return if c=="#"
    m[z-1][y]=" "
    return 1 if c=="@"
    m[z][y]="o"
  end
end

def rot m
  m.transpose.reverse
end

maze = File.readlines(gets.chomp).map{|x|x.chomp.split(//)}

while a=0
  win = drop_ball maze
  display_maze maze
  break if win
  a=gets.to_i until (0 < a && a < 3)
  maze=rot maze
  maze=rot rot maze if a==1
end
Run Code Online (Sandbox Code Playgroud)

可能的改进领域:

  • 将迷宫读入干净的2D阵列(目前为55个字符)
  • 找到并返回(x,y)球的坐标(目前为61个字符)

欢迎提出任何改进建议.