这是最后的冲刺……您的团队有一半生病了。您工作到很晚,只是做最后一天的工作,期待...为什么灯会熄灭?我不记得保安人员来了...哦,不!我把钥匙留在家中!
随着局势的恐惧逐渐加深,您决定要逃脱。
任务摘要
要实现逃生,您需要一个计划!但是,您知道任何计划都有失败的可能,并且不同的计划需要不同的努力。
由于感到饥饿,疲倦并且是一名工程师,您决定编写一个简短的程序来确定逃避复杂事件的最佳方法,从而平衡对成功可能性及其所需工作量的担忧。
您绘制建筑物的地图:
#######################
# = #
! = ! <-- window
# ! = # (freedom!)
#################= #
# # = #
# # = #
# # = #
# o ! # # ! = #
##| ! ## # ! = #
#######################
^ ^ ^
me my door ludicrously high shelves
(locked) (climbable)
为了逃脱办公室,您将不得不离开地图。在这里,您会看到2个窗口(!
),其中任何一个窗口都会带您进入自由,但是只有其中一个窗口可以访问。我们将“不在地图上”定义为您的脚不在地图范围内
细胞类型
- empty, you can be here (i.e. the escapee can consume this cell)
# - solid (your desk, your in-tray), you can't be here, but you can stand on it
! - destructible, (co-worker's desk, door, window), you can't be here until you smash it first (turning it into an empty cell)
= - climbable, (fire ladder, filing cabinet, etc.), you can be here
逃生者最初消耗的细胞被认为是空的。
动作规格
您的一次性设备有多种可能的动作。这些是由具有某些整数成功概率的简单状态转换定义的。例如,对于步行,您将逃逸者移动一个单元格,我们通过此过渡表示该单元格:
步
1 stp,100%,镜子
o. o
|. --> |
# #
点表示由于我们进入其中或经过它而必须为空的单元格(或可爬升的,但不是实心或可破坏的)。100%意味着您有100%的机会不伤害自己并结束大胆的逃脱。所有概率都是介于1%和100%(含)之间的整数百分比。第一张图显示了初始状态(站在实体上,站在一些空白处)。第二张图显示了终端状态(移入空白区域)。左侧(初始状态)的任何未指定的单元格(空格)没有特别要求。未指定的单元格(空格,
)(右侧)(末尾状态)应与之前相同(例如,逃生者身后的任何东西,或者我碰巧走到的任何东西(无论是空白处还是其他地方)。请注意,右侧(末尾状态) ),图表只会将单元格从可破坏的状态更改为空的状态,不会发生其他变化。“ 1 stp”表示需要花费1 stp:我们将“ stp”定义为采取步骤所需的能量。
“镜像”表示此动作有两种形式。显示了“右”动作,“左”动作是一个精确的镜像,例如:
.o
.|
#
是镜子(左)的形式
o.
|.
#
右边的动作称为“向右”(例如,“向右踩”)左边的动作称为“向左”(例如,“向左踩”)
在这些图中,逃生者显示为
o
|
站立时(2个单位高),并且
%
蹲伏时(1个单位高)。必须为实体或可破坏的单元格用井号表示#
。不能为实体或可破坏的单元格用点表示.
。爆炸表示必须破坏的细胞!
。下划线显示新创建的空白空间_
。
x
是不会移动的参考点(它不存在,对该单元格必须是什么没有约束(如space ))。
注意:当您撞到地板时,我们会忽略快速减速的问题,是的,在此游戏中,您可以完全史诗般地跳上梯子)
步
1 stp,100%,镜子
o. o
|. --> |
x# x#
爬上去
1 stp,100%,镜子
= =
o. --> o
|. |
x= x=
随机播放
3 stp,100%,镜面
%. %
x# --> x#
爬起来
10 stp,95%,镜子
o. %
|# --> #
x# x#
下降
0 stp,100%
o
| --> o
x. x|
掉落(站立)
0 stp,100%
% o
x. --> x|
爬上
2 stp,100%
= o
o --> |
x| x
蹲伏
2 stp,100%
o
| --> %
x# x#
支架
4 stp,100%
. o
% --> |
x# x#
短跳
4 stp,95%,镜子
o.. o
|.. --> |
x# x#
跳远
7 stp,75%,镜子
o... o
|... --> |
x# x#
跳高
12 stp,90%,镜子
.. o
o. --> |
|
x# x#
放回去吧!
20 stp,80%,镜子
o!. _o
|!. --> _|
x# x#
冲床
8 stp,90%,镜子
o! o_
| --> |
x# x#
踢
8 stp,85%,镜子
o o
|! --> |_
x# x#
邮票
8 stp,90%
o o
| --> |
x! x_
计划
计划是上面定义的一系列动作。例如:
Step Left
High Jump Left
Crouch
Shuffle Left
Shuffle Left
Stand
Long Jump Left
Put your back into it! Left
Step Left
请注意包含滴。应该设置规则,以阻止您执行除丢弃操作之外的任何操作,但是您仍然必须为此计划!
任何计划都有必要的工作量,这是每个步骤的工作量之和。还有一个成功概率,它是每个动作的成功概率的乘积。简单的例子:
Step Right: 1stp, 100%
Long Jump Right: 7stp, 75%
Step Right: 1stp, 100%
Stamp: 8stp, 90%
Drop: 0stp, 100%
Drop: 0stp, 100%
Drop: 0stp, 100%
Drop: 0stp, 100%
Step Left: 1stp, 100%
Step Left: 1stp, 100%
High Jump Left: 12stp, 90%
Effort = 1+7+1+8+1+1+12 = 31
Success Probability = 75%*90*90% = 60.75%
对于地图在页面顶部的“工作实例”,可以发现一个要点。
输入值
输入分为两部分,整数和字符数组或字符串。
整数是您的最小可接受成功率(百分比)。它将被解释为百分比,因此80表示您的计划必须以不小于80%的概率成功。
有效的地图是一个矩形,其中包括直立的转义符(最小尺寸为1x2),并且没有未指定的符号。所有行的长度将相同。您可以将输入作为一维定界字符串(定界符必须是单个一致字符,或者是CRLF和LFCR对之一),作为相似的一维数组或二维数组。如果您选择的输入格式没有以某种方式指示地图的宽度或高度,则您可以接受其他参数(必须在答案中明确说明)。如果适合,可以混合使用命令行参数和标准输入(例如,来自stdin的映射,来自argv的最小成功概率)。以下是有效和无效映射的示例。
有效:
o
|
有效:
# #
! o #
! | #
#########
无效(无转义符):
# #
! #
! #
#########
无效(转义符始终开始站立):
# #
! #
! % #
#########
无效(符号无效):
# #
! ~ #
! #
#########
无效(不是矩形/不同长度的行):
# #
! o #
! | #
#########
您可能会假设您的输入有效(我不在乎您的程序如果处理了无效的输入,会做什么)。
输出量
输出为文本(ASCII)。可以作为字符串返回,或打印到标准输出。该计划必须以LF,CRLF或LFCR界定。同样,在所需的工作之后,必须还有另一个LF,CRLF或LFCR。尾随换行符是可选的。
您必须输出最佳计划以及所需的工作量,或者说“没有希望!” 如果不存在这样的计划。您无需输出成功的可能性。此文本可能带有也可能没有尾随换行符。
最佳计划被定义为一种计划(请参见上文),它需要最少的努力并至少具有给定的成功概率。请注意,您的概率计算必须准确,您可能无法假设浮点数不够好(这就是为什么我不希望您输出它们)。我将尝试设计测试用例以公平地测试它(如果您通过它们并且不做任何愚蠢的假设,那么您可能会认为您提交的内容有效)。
格式:
Required Effort: <effort>
<plan>
例如,对于输入
50
# #
! o #
! | #
#########
适当的输出为:
Required Effort: 23
Step Left
Step Left
Step Left
Kick Left
Punch Left
Step Left
Step Left
Step Left
Step Left
此处成功的概率为76.5%。
对于同一张地图,但成功概率最小为80%,您将不得不“投入”,这将需要更多的精力,但要满足成功概率标准。如果成功的最小概率大于80%,则您需要加倍努力(无论是猛击还是踢过门的一部分然后将其洗掉)。如果成功的最小概率为100%,则必须打印出“没有希望!”
例子
一个输入可能有多个有效计划,您的输出不一定要是完全正确的计划,但它必须具有正确的要求工作量并且是有效计划。您可以使用验证程序来检查解决方案(请参见下文)
输入:
100
o
|
输出:
Required Effort: 0
Drop
输入:
5
# = #
# = !
# = ! ! !
# =#######
# = #
# = o #
# = ! | #
##########
输出:
Required Effort: 57
Step Left
Kick Left
Step Left
Step Left
Step Left
Climb Up
Climb Up
Climb Up
Climb Up
Climb off Right
High Jump Right
Long Jump Right
Step Right
Drop
Kick Right
Crouch
Shuffle Right
Shuffle Right
输入:
60
#########
# ! # #
! ! ! o #
! # ! | #
#########
输出:
Required Effort: 58
Step Left
Kick Left
Crouch
Shuffle Left
Shuffle Left
Stand
Punch Left
Clamber Up Left
Shuffle Left
Drop (Stand)
Kick Left
Crouch
Shuffle Left
Shuffle Left
对于相同的地图(但为80%),输出应为:
There is no hope!
对于相同的地图(但为50%),使用不同的计划时所需的工作量变为56)
输入:
50
#######################
# # = #
! # = !
# # = #
###### #####!## =### #
#= ## # = #
#=############# = #
#= = #
#= o = #
#!!| = #
#######################
输出:
Required Effort: 121
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Climb Up
Climb Up
Climb Up
Climb Up
Climb Up
Climb Up
Climb off Right
Long Jump Left
Step Left
Step Left
Stamp
Drop
Drop
Crouch
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Stand
Clamber Up Left
Stand
Clamber Up Left
Stand
Step Left
Step Left
Step Left
Step Left
Punch Left
Clamber Up Left
Shuffle Left
输入:
66
######
# ###
#o ! !
#| ! !
### ##
######
输出:
Required Effort: 37
Step Right
Put your back into it! Right
Kick Right
Crouch
Shuffle Right
Shuffle Right
输入:
此设计旨在检查可能会成为受害者的许多错误假设,因此可能看起来有些奇怪
30
###################
# ## # # # # = #
! ## # # # = #
# # # = #
## ############= #
# ## # #= #
# = # #= #
! = # #= #
# = # #= #
#o= ! ==#
#|= ! =#
#!= # ==########==#
# # ! !! =#
# # !! ! = #
# # !!!!#########
# # # #
# # # #
###################
具有成功机会约束30的输出:
Required Effort: 199
Long Jump Right
Put your back into it! Right
<snip>
具有成功机会约束32的输出:
Required Effort: 200
Long Jump Right
Punch Right
<snip>
使用顶部的地图作为输入,成功概率限制为1%,您应该获得116的必需工作量(成功机会〜32%,这在我的测试程序中运行大约需要20秒)。
胜利标准
这是代码高尔夫球,请以最短的代码为准。
要获得资格,您的功能或程序必须能够运行,并且能够在一台合理的机器上在30分钟内解决上述每个测试用例。我的求解器在30秒内完成了每个任务。如果测试脚本(如下所示)在30分钟内运行,那么您肯定很高兴。
求解器,验证器,测试脚本和测试案例的示例(包含解决方案)
求解器和求解器验证程序的C#代码在此处可以作为要点获得。要点还包含file.txt
,这是上述操作的机器可读(足够)的形式,并且是程序运行所必需的。该文件与规范之间的任何差异都不是故意的。
要点还包含许多测试用例(包括上面的所有示例),以及一个PowerShell脚本,用于自动针对它们运行提交。如果脚本告诉您特定测试失败,则可以运行OfficeEscapeSolver.exe testcase<n>.txt outputFromYourProgram.txt
以查看更多详细信息。这些测试用例的示例解决方案在另一个Gist中。
所有代码都是一团糟(尽管没有用),但是您不必为了static void Main(...)
改变输出量而走得太远(随意使用此信息,我为您带来了好处!)。
通过测试用例并不一定意味着您的输出格式正确,因为脚本和验证程序非常慷慨。您的输出必须符合上述规范,才能使提交的内容有效。
如果您认为发现了求解程序或测试脚本的错误file.txt
,或的测试案例中存在错误,请对此文章发表评论,或者通过SE Chat ping me。我可能不会注意到其他任何交流尝试。
我不提供Bash或Batch的测试脚本,因为我不知道它们,但是我很高兴提供翻译,如果人们想要的话,我会写一个C#版本。
邮政安布尔
有问题吗?不要拖延,今天问他们!
这项任务意味着需要付出努力,才能给认真的高尔夫球手一些东西以供其咬牙切齿。
感谢ais523对输入/输出的反馈。
如果人们想要更多(不想再发布此帖子),或者想要提供一些自己的东西,我可以在gist文件中提供更多的测试用例。