验证扫雷板


33

您的目标是检查完整的扫雷板是否有效。这意味着每个数字都是与其相邻单元格(包括对角线)中地雷的正确计数。董事会不环绕。

与往常一样,您应该提供一个函数或程序,以字节为单位的最短代码将获胜。

另请参阅生成解决全面实施 Minesweeper的过去挑战。

输入:

像这样的单个字符串:02X2 13X2 X211

  • 扫雷器板的行以空格分隔。因此,以上代表3x4板:

    02X2
    13X2
    X211

  • 每个小区是一个字符:X用于矿场,或一个数字08

  • 所有行具有相同的长度。

  • 至少有3行和3列。

  • 输入的内容不能以空格开头或结尾,但是如果需要,可以在结尾添加换行符。

输出:

一致的Truthy上正确板和一致的Falsey不正确的板值。一致意味着所有Truthy输出相同,而所有Falsey输出相同。

测试用例

每行是一个单独的测试用例。

True

02X2 13X2 X211
XXXX XXXX XXXX XXXX
XX4X2 5X6X4 XX6XX 4XX54 2X4XX

False

02X2 13X2 X212
XXXX XXXX X7XX XXXX
XX5X2 5X6X4 XX6XX 4XX54 2X5XX

您可能应该指定一致的虚假输出必须不同于一致的真实输出;-)
John Dvorak

@JanDvorak这应该暗示他们分别是Truthy和Falsey。
xnor 2014年

并不是的。“真实”和“虚假”只是您要让我们定义的两个标签。我看不出它们在我们使用的语言中分别是真实的还是虚假的限制。可能要求它们与众不同的唯一单词是“指示”动词。我不确定它是否属于规格(尽管仍然被视为标准漏洞)。
约翰·德沃夏克

4
@JanDvorak'truthy'和'falsy'实际上是一些通用术语,如果我没有记错的话,基本上是用来描述在键入bool时评估为true或false的事物(不一定是bool)。例如,0通常是虚假的,而1通常是真实的。
KSab 2014年

1
@JanDvorak不,Truthy / Falsey必须匹配正确/错误。
xnor 2014年

Answers:


11

Python 2中,132 129 128

def f(s):w=s.find(' ');E=dict(enumerate(s));return all(E[i]in' X'+`sum(E.get(i+d/3*~w+d%3+w,5)>'O'for d in range(9))`for i in E)

我曾经enumerate在高尔夫球场上用过……甚至range在同一程序的其他地方也用过。显然这里有些问题。

编辑:dict(enumerate(s))而不是进行迭代enumerate(s),因此enumerate不需要调用两次。


多么巧妙的使用~!并使用字典来使越界索引工作正确。
xnor 2014年

@xnor您对~操作员的评论使我感到讽刺,使我注意到我无缘无故地使用了两次,而只使用一次显然会完成相同的事情。我以为字典部分很有趣,谢谢。
feersum 2014年

9

佩斯,43

Jhxzd!f-@zT+" X"`sm/:+*JNztd+d2\Xm+T*kJU3Uz

在这里尝试。

说明:

  • Jhxzd:这是输入+1中第一个空格的位置(z在输入中d为空格)。它是板上垂直相邻单元之间的输入间距。
  • !f:这是!过滤器(f)的逻辑非(),True当且仅当表达式对序列中的每个元素都是虚假的时,才会如此。
  • -@zTT从输入中获取位置(lambda变量)处的字符,并删除以下字符的所有出现:(如果不删除字符,则为真,否则为假。
  • +" X":删除空格,X和
  • `:代表
  • sm:地图到的总和
  • / \X:中的“ X”个计数
  • :+*JNz:输入部分,以J假字符为前缀
  • td+d2:从d-1到d + 2。
  • m+T*kJU3:对于[T,T + J,T + 2 * J]中的d。
  • Uz对于T in range(len(input))

7
Downvoters:为什么要拒​​绝投票?
isaacg 2014年

7

APL(NARS2000)(74)

{~0∊(G>9)∨G=(⍴G)↑{+/∊9<⍵∘⌷¨G∘.⊖(G←2-⍳3)∘.⌽⊂Z}¨⍳⍴Z←G↑⍨2+⍴G←¯1+⎕D⍳⊃⍵⊂⍨⍵≠' '}

如果⎕ML设置为,也可在Dyalog APL中使用3

说明:

  • ⊃⍵⊂⍨⍵≠' '在空格上分割并使用列表形成矩阵。
  • G←¯1+⎕D⍳:找到⎕D每个值的索引,然后减去1,并将其存储在中G。(⎕D包含数字,任何非数字都将变成10)。
  • Z←G↑⍨2+⍴G:在矩阵的边缘添加两行零列,以处理环绕
  • {... }¨⍳⍴Z:对于中的每个位置Z,找到该位置的Moore附近的炸弹数量:
    • G∘.⊖(G←2-⍳3)∘.⌽⊂ZZ向左,向右,向上,向下,向左,向上,向右,向左和向右旋转。
    • ⍵∘⌷¨:对于其中的每个,在每个旋转矩阵中找到的元素
    • +/∊9<:计算高于9的元素数量(这是炸弹的数量)。
  • (⍴G)↑:再次删除添加的零行,
  • G=:检查其中的每个元素G是否等于该位置周围的炸弹数量(对于所有非炸弹正方形均应如此),
  • (G>9)∨:并检查其中的元素G是否高于9(这些是炸弹)。
  • ~0∊1如果结果矩阵不包含零(=所有正方形都是炸弹或正确的数字),并且返回0,则返回。

您计数字节或字符了吗?您应该计算字节数。
Tim S.

5
@TimS .:有很多1字节APL编码,这是一种
marinus 2014年

5

C#,321 320 305

bool s(string B){var L=B.Split(' ').Select(s=>' '+s+' ').ToList();var b=new string(' ',L[0].Length);L.Insert(0,b);L.Add(b);Func<int,int,IEnumerable<int>>E=Enumerable.Range;return E(1,b.Length-2).All(x=>E(1,L.Count-2).All(y=>L[y][x]=='X'||L[y][x]-'0'==E(x-1,3).Sum(X=>E(y-1,3).Sum(Y=>L[Y][X]=='X'?1:0))));}

首先尝试打高尔夫球,我知道C#不是理想的语言。

我希望允许编写实例方法,否则请为添加7个字符static

隔开:

bool s(string B) {
    var L = B.Split(' ').Select(s => ' ' + s + ' ').ToList();
    var b = new string(' ', L[0].Length);
    L.Insert(0, b);
    L.Add(b);
    Func<int, int, IEnumerable<int>> E = Enumerable.Range;
    return E(1, b.Length - 2).All(x =>
        E(1, L.Count - 2).All(y =>
            L[y][x] == 'X' ||
            L[y][x] - '0' == E(x - 1, 3).Sum(X =>
                E(y - 1, 3).Sum(Y =>
                  L[Y][X] == 'X' ? 1 : 0))));
}

与for循环相比,使用Linq可以节省一些空间,但是调试起来比较困难。

我学到了一些东西,例如char => int通过减法进行转换'0'

在板上留出空间似乎更简单,因此在板上进行迭代会更容易。


1
您不能只替换-'0'-48。为我工作,并为各种'X'和''保存了一些字节
RomanGräf16年

5

Python 2,121

def f(B):n=B.find(' ')+1;R=range(len(B));print all(B[I]in' X'+`sum(2>I%n-i%n>-2<I/n-i/n<2<B[i]>'W'for i in R)`for I in R)

这极大地受到了feersum的回答的启发。一天的工作过于繁琐:不检查该单元9个邻居中的地雷,而是检查每个单元是否是相邻地雷。

我们检查两个像元是否与相邻2>r>-2<c<2,其中rc是像元的行和列差,等于{r,c}<{-1,0,1}。这些坐标是根据单元格索引I以及ias c=I%n-i%nr=I/n-i/n。直接将其索引到字符串中并提取行和列,比将其转换为2D对象(如列表列表)更有效。地雷检查B[i]>'W'等于B[i]=='X'

使用方法enumerate会在丑陋的地方保存两个字符,range(len(B))除了它返回一个不支持通过它的两个嵌套循环的迭代器对象。


我认为负模应适用于n;然后您可以使用~B.find
feersum 2014年

@feersum不幸的是,这很麻烦,/因为它也将负数向下舍入。
xnor 2014年

4

Python 2,140

s=input();w=s.index(' ')+1
print all(c in'X 'or(int(c)==sum(s[max(0,a-1):max(0,a+2)].count('X')for a in[i-w,i,i+w]))for i,c in enumerate(s))

4

的JavaScript(ES6),135 133 125 122

f=s=>s.split(" ")[e="every"]((l,i,a)=>[...l][e]((c,j)=>!(-[-1,0,k=1][e]((y,m,q)=>q[e](x=>k+=(a[i+y]||0)[j+x]=="X"))-c+k)))

以字符串形式向函数提供输入:

f("XX4X2 5X6X4 XX6XX 4XX54 2X4XX");

有关说明,请参见下面的旧版本。新版本替换for循环与every通话,并使用变量e="every"someArray[e](...)的,而不是someArray.every(...)

另外,k现在将计数器索引为索引,1以便k+=...表达式始终为真,以保持every循环运行。我们1通过减去操作返回的true结果(数值强制为1)来消除额外的开销。every[-1,0,k=1][e](...)


旧版:

f=s=>s.split(" ").every((l,i,a)=>[...l].every((c,j)=>{q=[-1,k=0,1];for(y of q)for(x of q)k+=(a[i+y]||0)[j+x]=="X";return c=="X"||k==c}))

带有空格和注释的代码:

f=s=>s.split(" ")                 // split on spaces
      .every((l,i,a)=>             // for every line
                                   //     l: line string, i: line number, a: whole array
          [...l].every((c,j)=>{    // for every character
                                   //     c: character, j: index in string
              q=[-1,k=0,1];        // define counter k=0 and q=[-1,0,1]
              for(y of q)          // use q to loop adjacent spaces
                  for(x of q)

                      k+=              // add the following boolean to k:

                          (a[i+y]      //   from line number i+y...
                                 ||0)  //   (or a dummy zero, to prevent lookups on undefined)
                          [j+x]        //   ...get index j+x from the above value...
                                =="X"; //   ...and compare it to "X"

              return !(k-c)     // after the loop, this character passed if
                                // the char equals the number of counted X's (so k-c is 0)
                                // or it is an X itself (so `k-c` is NaN)
          })
      )

JavaScript every数组方法接受回调并将回调应用于数组的每个元素。如果任何回调返回falsey值,则every调用返回false

当加法的一部分时,JS中的布尔值被强制为1或0。对于每一个周围的空间,我们的“添加”它的价值比较的布尔结果X,然后将该值添加到计数器k中的表达k += (... == "X")。因此,k包含计数Xs 的数目,因为true计数为1false计数为0


而不是c=="X"try !c/1,这可以为您节省大量的一对字节!如果失败,请尝试!!c/1。原因是'X'/1 => NaN,而且NaN是虚假的。您检查是否c=='X',为什么不尝试检查是否不是false
Ismael Miguel

不幸的是(!c)/1,@ IsmaelMiguel的计算结果与相同,但没有帮助。我需要加2的括号!(c/1),而且0/1是假的,因此无效的输入“ 0X”将产生错误的结果true。在仍然尊重零的同时,我能做的最好的事情就是将这两个条件组合成一个否定短语,例如!(+c+1&&k-c),但这与我已经拥有的长度相同。
Apsillers 2014年

@IsmaelMiguel谢谢您让我思考一下-我已经意识到可以同时!(k-1-c)测试这两个条件,因为如果k匹配c(减去1个偏移量),则求反为0真;如果c不是数字,NaN则求和也true
apsillers 2014年

你真饿!自初始代码起,您就吃了10个字节!我真的很喜欢您想出的解决方案。+1为您的解决方案!
Ismael Miguel 2014年

3

CJam,70 65 63字节

1l_S#):L)S*+:Q{Ii33/2%[0~1LL)L(L~)L~_))]W):Wf+Qf='X/,(scI==&}fI

这可以打很多球。

提供1有效的木板和0无效的木板。

测试用例

{-1:W;
1l_S#):L)S*+:Q{Ii33/2%[0~1LL)L(L~)L~_))]W):Wf+Qf='X/,(scI==&}fI
}6*]N*

输入项

02X2 13X2 X211
XXXX XXXX XXXX XXXX
XX4X2 5X6X4 XX6XX 4XX54 2X4XX
02X2 13X2 X212
XXXX XXXX X7XX XXXX
XX5X2 5X6X4 XX6XX 4XX54 2X5XX

输出量

1
1
1
0
0
0

在这里在线尝试


3

JavaScript(ES6)98

使用一些函数将功能应用于字符串的每个字符。
函数返回

  • 如果为空则为假
  • 如果为“ X”,则为NaN(反复从非数字字符(如“ X”)中减去值得出NaN)
  • 如果有正确的反斜线“ X”,则为0数值,否则为非0。仅
    使用mapforEach短来进行内部检查

有些在第一个真实值(在这种情况下为非零)处返回true,表示检查失败。否定结果将给出更可识别的真/假。

F=v=>![...v].some(
  (x,p)=>x!=' '&&[1,-1,l=v.search(' '),-l,++l,-l,++l,-l].map(q=>x-=v[p+q]=='X')|x
)

在FireFox / FireBug控制台中测试

;["02X2 13X2 X212","XXXX XXXX X7XX XXXX","XX5X2 5X6X4 XX6XX 4XX54 2X5XX"
,"02X2 13X2 X211","XXXX XXXX XXXX XXXX","XX4X2 5X6X4 XX6XX 4XX54 2X4XX","111 1X1 111"]
.forEach(t => console.log(t, F(t)))

输出量

02X2 13X2 X212 false
XXXX XXXX X7XX XXXX false
XX5X2 5X6X4 XX6XX 4XX54 2X5XX false
02X2 13X2 X211 true
XXXX XXXX XXXX XXXX true
XX4X2 5X6X4 XX6XX 4XX54 2X4XX true
111 1X1 111 true

1

R,156个字符

a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])

带有缩进,空格和换行符,以便于阅读:

a = b = do.call(rbind,strsplit(scan(,""),"")) #Reads stdin and turn into a matrix
for(i in 1:nrow(a)) #Ugly, ugly loop
    for(j in 1:ncol(a))
        b[i,j] = sum(a[abs(i-row(a))<2 & abs(j-col(a))<2]=="X")
v = a!="X"
all(b[v]==a[v])

例子:

> a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])
1: XX4X2 5X6X4 XX6XX 4XX54 2X4XX
6: 
Read 5 items
[1] TRUE
> a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])
1: XXXX XXXX XXXX XXXX
5: 
Read 4 items
[1] TRUE
> a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])
1: XX5X2 5X6X4 XX6XX 4XX54 2X5XX
6: 
Read 5 items
[1] FALSE
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.