流氓寻路


21

流氓寻路

给定下面描述的元素的二维数组(表示地牢),您的任务将输出或返回一个数字,该数字表示流氓可以在不唤醒任何怪物的情况下收集的金块数量。

数组的元素如下:

  1. 空格由.您的呼叫或一个空格表示;
  2. 当然,Rogue的起始位置由@; 表示。
  3. 一块金代表$;
  4. 墙壁用#;
  5. 怪物由以下正则表达式中的字符表示:[a-zA-Z*&]

该数组不应包含上面未列出的任何字符,因此您可以假定不是墙壁,空白空间,流氓或金币的任何东西都是怪兽。

寻路的规则是:

  1. 流氓只能穿过空的牢房或含金的牢房。
  2. 转向到相邻或对角线相邻的单元格;
  3. 拿起黄金是立即的;
  4. 流氓在不醒来的情况下不能与怪物相邻或对角相邻超过一个回合,这是被禁止的;
  5. 流氓可以多次进入怪物的意识区域,只有流氓在其附近连续走两圈时,怪物才会醒来。

输入和输出规则

您可以采用任何合理的格式获取输入,包括二维数组,平面数组,字符串或其他任何格式。如果它使您的生活更轻松,那么您也可以考虑数组的尺寸。

可以确保流氓一开始不会在怪物附近。

完整的程序或功能很好。

计分

这是,分数是提交的字节数,越少越好。

测试用例

为了方便阅读,我在此处使用空格表示点,如果您愿意,可以使用空格(请参见上文)。还要注意,这纯粹是偶然的,流氓总是在左上角,您的代码也应该处理任何其他有效位置。

1)
@..
.$.
...  -> 1

只是一个健康测试。

2)
@....
...g$
.....  -> 0

再次进行健全性测试。

3)
@....
...$g
.....  -> 1

流氓可以通过向左移动来抢金。

4)
@....g..
.......$
........
.....h..  -> 1

流氓可以在两个怪物之间作曲折曲折,每个怪物之间的停留时间不得超过一圈。

5)
@....z..
.......$
.....b..  -> 0

先前测试用例的策略在这里不起作用-怪物敏感区域重叠。

6)
@$#.
###$
....  -> 1

健全性测试。

7)
@..#..
$.$g.$
...#..  -> 2

同上。

8)
@#.d#$
$...##
e.....
..$...
##..$b
.#..g$  -> 3

在这里的所有黄金中,只能安全地到达三个:通过向下移动一个然后返回到起始位置,可以获得接近起始位置的黄金。为了从左上角逃脱,流氓必须向右下斜对角移动两次。中间的黄金不构成挑战。可以通过从中间金的右边对角向内移动然后向后移动来获得g和保护的外部金b。其余的无法获得:右上角的黄金被墙壁挡住,右下角的黄金需要在怪物敏感性区域内转两圈。

以下测试用例由mbomb007慷慨捐赠。

9)
  12345678
a @....g.D
b .......$
c ......#.
d .....h..  -> 1

这是一个棘手的问题。路径是b4-b5-c6-b7-c8-b8(grab)

10)
  12345678
a @....g.D
b .......$
c .......#
d .....h..  -> 1

路径是[bc]4-c5-b6-c7-b8(grab)

11)
  12345678
a @....g.D
b ......#$
c .......#
d .....h..  -> 1

多余的墙实际上没有任何改变,[bc]4-c5-b6-c7-b8(grab)仍然是一种解决方案。


您应该添加一个更大,更复杂的示例。另外,地牢的最小和最大尺寸是多少?1x1地牢@是有效输入吗?
mbomb007 '18


@ mbomb007我添加了一个新示例。至于网格的大小,我认为将其限制为至少3x3是合理的。
Michail '18 -4-2

@ mbomb007介意我在其中编辑您的示例吗?一旦理解,他们就很好地展示了逻辑。
Michail

放心吧。那就是我做他们的目的。还应该指出,旋转测试用例不应对其结果产生任何影响。
mbomb007 '18

Answers:


5

先前的解决方案(其中的一部分)可以在tio链接的页脚容器中找到(这些可读性更高)

的JavaScript(Node.js的)883个 436 411 360345 311字节

g=>g.map((r,y)=>[...r].map((c,x)=>A+=c=="$"&&P(g,x,y)),A=0)|A
P=(g,x,y,m={},p={},I=i=9,M={})=>{if(/[.$]/.test(c=(g[y]||0)[x])){for(;i--;)if(/^[^.@$#]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])){if(m[C])return
M[C]=1}for(;I--;)if(!p[(X=x+~-(I/3))+","+(Y=y+I%3-1)]&&P(g,X,Y,M,{...p,[x+","+y]:1}))return 1}return c=="@"}

在线尝试!

外植-

而不是从玩家那里获得现金,我从案件转到@。我想我应该更快一些,因为我知道什么时候停止寻找(到达@),并且当您寻找现金时,您需要一直移动直到您覆盖所有景点(以及到达目的地的方式)。所以这种方法很简单-主要功能 g.map((r,y)=>[...r].map((c,x)=>A+=c=="$"&&P(g,x,y)),A=0)|A:找到现金->如果找到了它->开始寻找玩家->如果找到了他->增量A现在让我们进入路径查找器aka P if(/[.$]/.test(c=(g[y]||[])[x]))只是检查是否当前单元格是“特殊”->如果是,那么我们要返回它是否为玩家。特殊情况:@#(怪物)

for(;i--;) if(/^[a-zA-Z*&]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])) -> if my neighbor is a monster {if(m[C])return false -> and it already was in the previous turn - this path is not value M[C]=1} -> if not just add it to the neighbors monsters for(;I--;) if(!p[(X=x+~-(I / 3))+","+(Y=y+I%3-1)]&&P(g,X,Y,M,{...p,[x+","+y]:1}))return true 再次遍历邻居-如果我还没有在那儿(p是走的路径),继续路径(呼叫P)


高尔夫不错!我注意到了几件事:(1)您的代码在第二行和第七行上具有多余的尾随空格,并且大多数换行符都是不必要的(只有第1行和第6行需要换行),并且I / 3具有不必要的空间。消除空白,您的分数实际上是324!(2)return true 可以是return 1(真值),return false也可以简单地是return(暗示undefined,假值)。(3)^[^.@$#]$检查非怪物的正则表达式比检查怪物短^[a-zA-Z*&]$。干得好!
apsillers'Apr

是的,我知道我可以使它更短:)
DanielIndie

@apsillers更新到免费空间解决方案了:)
DanielIndie
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.