让我们玩捉迷藏吧!


12

用户将隐藏,计算机将尝试找到它们。

首先,程序将为网格的大小输入一个值。像5x5、10x10、15x15等。网格并不总是完美的正方形。

网格有点像棋盘:

_______________________________
|     |     |     |     |     |
| A1  |     |     |     |     | A
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     | B2  |     |     |     | B
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     |     | C3  |     |     | C
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     |     |     | D4  |     | D
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     |     |     |     | E5  | E
|_____|_____|_____|_____|_____|
   1     2     3     4     5

现在,用户将选择一个正方形,例如B2(不告诉计算机)

计算机将开始猜测正方形。如果选择正确的正方形,则用户将使用进行响应y。如果没有,他们将输入从所选择的瓷砖(N,NE,E,SE,S,SW,W)中瓷砖的方向。

因此,如果用户选择B2了计算机C3,但计算机猜对了,则用户将输入NW

这是输出和输入的示例:

Grid?
5x5

C3?
NW

C2?
N

B2?
y

得分:

这将与正常挑战的得分有所不同。

获胜者是一个采用最少猜测(平均)才能猜出正确平方的程序。要平均的测试用例将是5x5,然后是10x10的所有可能的平方。

但是,它还必须适用于多达26行(即5x8、6x2、20x5等)的每种网格模式。

请提供一种测试方法,例如JSFiddle。

最后,如果出现平局,则以最短的程序为准。


1
如果我躲藏起来A1并且计算机猜测B9是正确的响应NW还是W
格雷格·马丁

@GregMartin这将是NW。...N,W,S,E必须全部是直的,
而不同行

输入和输出的特定格式是否具有灵活性?如果行数超过26,则称它们为什么?
格雷格·马丁

@GregMartin您可以灵活使用输出,但请尝试使其保持简单。它不必完全相同,但应具有相似的样式。您无需考虑26以上的任何问题,我将对其进行编辑。
JKonowitz

我不知道“相似风格”是什么意思。我们可以将输入作为有序的整数对(行号,列号)吗?(PS:这些类型的问题是为什么在Sandbox中预先发布挑战是一个好主意的原因。)
Greg Martin

Answers:


3

Python的3.6466个 398 392字节,极大极小

x, y = 1, 1
w, h = [int(x) for x in input('Grid?\n').split('x')]


def split_factor(a, b):
    N = b-y
    W = a-x
    S = h+~N
    E = w+~W
    return max(1, N, W, S, E, N*W, S*W, S*E, N*E)


def move(a, b):
    *Z, = zip([a, x, a, a+1, x, x, a+1, a+1],
              [y, b, b+1, b, y, b+1, b+1, y],
              [1, a-x, 1, w+x+~a, a-x, a-x, w+x+~a, w+x+~a],
              [b-y, 1, h+y+~b, 1, b-y, h+y+~b, h+y+~b, b-y])
    return Z[['N', 'W', 'S', 'E', 'NW', 'SW', 'SE', 'NE'].index(d)]

d = ''
while d != 'y':
    print()
    splits = {(a, b): split_factor(a, b) for a in range(x, x+w) for b in range(y, y+h)}
    a, b = min(splits, key=splits.get)
    d = input(f'{a}{"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[b]}?\n')
    x, y, w, h = move(a, b)

输入和输出应采用示例中所示的形式。这样就找到了具有最小“分裂因子”的正方形,该正方形是玩家答案(例如NW,E,y等)可能导致的最大剩余面积,并对此进行了猜测。是的,这始终是游戏剩余区域的中心,但是这种最小化最坏情况的技术将在具有不同规则的类似游戏中更普遍地发挥作用。

不可读的版本:

x=y=d=1
w,h=map(int,input('Grid?\n').split('x'))
while d!='y':print();s={(a,b):max(b-y,h+y+~b)*max(w+x+~a,a-x)for a in range(x,x+w)for b in range(y,y+h)};a,b=min(s,key=s.get);d=input(f'{a}{chr(64+b)}?\n');*z,=zip([a+1,x,a+1,x,a,a,a+1,x],[b+1,b+1,y,y,b+1,y,b,b],[w+x+~a,a-x,w+x+~a,a-x,1,1,w+x+~a,a-x],[h+y+~b,h+y+~b,b-y,b-y,h+y+~b,b-y,1,1]);x,y,w,h=z[~'WENS'.find(d)or-'NWNESWSE'.find(d)//2-5]

2

Mathematica,测试用例的最佳行为,260个字节

For[a=f=1;{c,h}=Input@Grid;z=Characters;t=<|Thread[z@#->#2]|>&;r="";v=Floor[+##/2]&;b:=a~v~c;g:=f~v~h,r!="y",r=Input[g Alphabet[][[b]]];{{a,c},{f,h}}={t["NSu",{{a,b-1},{b+1,c},{b,b}}]@#,t["uWX",{{g,g},{f,g-1},{g+1,h}}]@#2}&@@Sort[z@r/.{c_}:>{c,"u"}/."E"->"X"]]

可以通过将上面的代码剪切并粘贴到Wolfram Cloud中来测试该程序。(不过请快速测试:我认为每个程序运行都有时间限制。)程序的猜测看起来像2 c不是C2,而是根据上面的规范运行。网格必须作为有序整数对输入,例如{26,100},并且对程序猜测的响应必须作为字符串输入,例如"NE""y"

该程序将跟踪与到目前为止的输入一致的最小和最大行号和列号,并始终猜测可能性子网格的中心点(四舍五入)。该程序是确定性的,因此很容易计算固定网格上平均所需的猜测次数。在10x10的网格上,该程序要求对一个正方形进行1次猜测,对8个正方形进行2次猜测,对64个正方形进行3次猜测,对于其余27个正方形进行4次猜测,平均为3.17;这是理论上的最小值,因为有多少1个猜测,2个猜测等序列可以导致正确的猜测。实际上,出于类似的原因,该程序应该在任何大小的网格上都达到理论上的最小值。(在5x5网格上,平均猜测数为2.6。)

少许代码解释,尽管除了打高尔夫球以外其他方法非常简单。(出于说明目的,我交换了一些初始化语句的顺序,这对字节数没有影响。)

1  For[a = f = 1; z = Characters; t = <|Thread[z@# -> #2]|> &;
2      v = Floor[+##/2] &; b := a~v~c; g := f~v~h;
3      r = ""; {c, h} = Input@Grid, 
4    r != "y", 
5    r = Input[g Alphabet[][[b]]];
6      {{a, c}, {f, h}} = {t["NSu", {{a, b - 1}, {b + 1, c}, {b, b}}]@#, 
7        t["uWX", {{g, g}, {f, g - 1}, {g + 1, h}}]@#2} & @@ 
8        Sort[z@r /. {c_} :> {c, "u"} /. "E" -> "X"]
   ]

第1-3行初始化了For循环,实际上这只是一个While变相的循环,所以少了两个字节。任何时候可能的行数和列数范围都存储在中{{a, c}, {f, h}},该子网格的居中猜测由第{b, g}2行中定义的函数计算。第3行根据用户输入初始化max-row c和max-column h,然后还初始化r哪个是循环测试的变量以及后续的用户输入。

当满足第4行的测试要求时,第5行从用户那里得到输入,提示来自当前的猜测{b, g}Alphabet[][[b]]]将行号转换为字母)。然后第6-8行更新了可能性的子网格(因此隐式地进行了下一个猜测)。例如,t["NSu", {{a, b - 1}, {b + 1, c}, {b, b}}](根据第t1行的定义)扩展为

<| "N" -> {a, b - 1}, "S" -> {b + 1, c}, "u" -> {b, b}|>

您可以在其中看到根据用户的最后输入更新的最小行和最大行数。第8行将任何可能的输入转换为格式的有序字符对{ "N" | "S" | "u", "u" | "W" | "X"}; 这里"u"代表正确的行或列,"X"代表East(只是为了使其Sort工作正常)。当用户最终输入时"y",这些行将引发错误,但随后的循环测试将失败,并且错误也永远不会传播(无论如何,程序都会暂停)。


0

批量,分而治之

@echo off
set z = ABCDEFGHIJKLMNOPQRSTUVWXYZ
set /p g = Grid?
set /a w = 0, n = 0, e = %g :x= + 1, s = % + 1
:l
set /a x = (w + e) / 2, y = (n + s) / 2
call set c = %%z :~%y%,1%%
set /p g = %c %%x%?
if %g :w=.% == %g % set /a w = x
if %g :n=.% == %g % set /a n = y
if %g :e=.% == %g % set /a e = x
if %g :s=.% == %g % set /a s = y
if %g :y=.% == %g % goto l

通过创建仍要搜索的区域的边界框来工作。下一个猜测永远是盒子的中心。对于那些未包含在响应中的罗盘点,则将框沿该方向缩小。例如,对于的响应N,将框的左侧,右侧和底部设置为猜测的正方形。

在369字节的内存中,我预计不会击败任何人,因此为了便于阅读,我保留了空格。


好吧,分治法通常适用于大型测试用例,但不适用于小型案例,有没有更好的算法?
马修·鲁

@SIGSEGV不确定您的意思;格雷格和本的答案也使用盒子方法的中心。
尼尔

我们仍然需要更好的算法。
马修·鲁

@SIGSEGV中心框方法是最佳的。没有更好的算法。
TheNumberOne
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.