Verifique uma placa do Campo Minado


33

Seu objetivo é verificar se uma prancha minada concluída é válida. Isso significa que cada número é uma contagem correta de minas nas células adjacentes a ele, incluindo diagonais. O quadro não se enrola.

Como sempre , você deve fornecer uma função ou programa, e o código mais curto em bytes vence.

Veja também os desafios anteriores para gerar , resolver e implementar totalmente o Campo Minado.

Entrada:

A única string como esta: 02X2 13X2 X211.

  • As linhas do tabuleiro de minas são dadas separadas por espaços. Portanto, o acima representa o quadro 3x4:

    02X2
    13X2
    X211

  • Cada célula é um personagem: Xpara uma mina, ou um número 0através 8.

  • Todas as linhas têm o mesmo comprimento.

  • Existem pelo menos 3 linhas e 3 colunas.

  • A entrada não começa ou termina com um espaço, mas você pode incluir uma nova linha no final, se desejar.

Saída:

Um Truthy consistente nas placas corretas e um valor Falsey consistente nas placas incorretas. Consistente significa que todas as saídas Truthy são iguais e todas as saídas Falsey são iguais.

Casos de teste

Cada linha é um caso de teste separado.

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

Você provavelmente deve especificar a saída Falsas consistente deve ser distinto da saída truthy consistente ;-)
John Dvorak

@ JanDvorak Isso deve estar implícito por eles serem Truthy e Falsey, respectivamente.
Xnor

Na verdade não. "truthy" e "falsy" são apenas dois rótulos que você nos permite definir. Não vejo nenhuma restrição de que sejam realmente verdadeiros ou falsos, respectivamente, no idioma que usamos. A única palavra que pode exigir que sejam distintos é o verbo "indicativo". Não sei se isso conta como uma especificação (ainda é proibido como uma brecha padrão).
John Dvorak

4
@JanDvorak 'truthy' e 'falsy' são termos bastante comuns, se não me engano, basicamente usado para descrever coisas (não necessariamente bools) que avaliam verdadeiro ou falso quando digitadas em bools. Por exemplo, 0 é geralmente falso e 1 é geralmente verdadeiro.
KSab

1
@JanDvorak Não, Truthy / Falsey deve corresponder a correto / incorreto.
Xnor

Respostas:


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)

Eu usei enumerateno golfe ... e até usei rangeem outro lugar no mesmo programa. Claramente algo está errado aqui.

Edit: Iterate em dict(enumerate(s))vez de enumerate(s), portanto enumerate, não precisa ser chamado duas vezes.


Que uso inteligente de ~! E de dicionários para fazer a indexação fora dos limites funcionar corretamente.
xnor

@xnor Seu comentário sobre o ~operador ironicamente me fez notar que eu o estava usando duas vezes sem motivo algum, onde usá-lo apenas uma vez obviamente faria a mesma coisa. Eu pensei que a parte do dicionário era engraçada, obrigado.
feersum

9

Pyth, 43

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

Experimente aqui .

Explicação:

  • Jhxzd: Este é o local do primeiro espaço na entrada + 1. ( zna entrada, dé espaço.) É a separação na entrada entre as células verticalmente adjacentes na placa.
  • !f: Esse é o não lógico ( !) de um filtro ( f), que será Truese e somente se a expressão for falsa para todos os elementos da sequência.
  • -@zT: Pegue o caractere no local T(a variável lambda) da entrada e remova qualquer aparência de: (Isso será verdade se o caractere não for removido e falso se for.
  • +" X": Remova o espaço, X e
  • `: Repr de
  • sm: soma do mapa para
  • / \X: contagem de "X" em
  • :+*JNz: A fatia da entrada prefixada por Jcaracteres fictícios
  • td+d2: De d-1 a d + 2.
  • m+T*kJU3: Para d em [T, T + J, T + 2 * J].
  • UzPara T in range(len(input)).

7
Downvoters: Por que os downvotes?
Isaacg

7

APL (NARS2000) (74)

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

Também funciona no Dyalog APL se ⎕MLestiver definido como 3.

Explicação:

  • ⊃⍵⊂⍨⍵≠' ': divida nos espaços e use as listas para formar uma matriz.
  • G←¯1+⎕D⍳: encontre o índice ⎕Dpara cada valor, subtraia 1 e armazene-o em G. ( ⎕Dcontém os dígitos, qualquer não dígito se tornará 10).
  • Z←G↑⍨2+⍴G: adicione duas linhas e colunas de zeros na borda da matriz para lidar com a envolvente
  • {... }¨⍳⍴Z: para cada posição Z, encontre a quantidade de bombas no bairro Moore dessa posição:
    • G∘.⊖(G←2-⍳3)∘.⌽⊂Z: gire para a Zesquerda, direita, cima, baixo, esquerda para cima, direita para cima, esquerda para baixo e direita para baixo.
    • ⍵∘⌷¨: para cada um deles, encontre o elemento em cada uma dessas matrizes rotacionadas
    • +/∊9<: conte quantos elementos são maiores que 9 (é a quantidade de bombas).
  • (⍴G)↑: remova as linhas adicionadas de zeros novamente,
  • G=: verifique se cada elemento Gé igual à quantidade de bombas em torno dessa posição (isso deve ser verdadeiro para todos os quadrados que não são de bomba),
  • (G>9)∨: e verifique se os elementos em Gsão maiores que 9(estas são as bombas).
  • ~0∊: retorna 1se a matriz resultante não contém zeros (= todos os quadrados são bombas ou o número correto) e, 0se existirem.

Você contou bytes ou caracteres? Você deve contar bytes.
Tim S.

5
@ TimS .: Existem muitas codificações de 1 byte APL, aqui está uma .
marinus

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))));}

Primeira tentativa de jogar golfe, e sei que C # não é o idioma ideal.

Espero que seja permitido escrever um método de instância, caso contrário, adicione outros 7 caracteres para static.

Espaçados:

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))));
}

O uso do Linq economiza espaço em comparação com os loops, mas é mais difícil depurar.

Aprendi algumas coisas como converter char => intsubtraindo '0'.

Parecia mais simples preencher o quadro com espaços, para iterá-lo seria mais fácil.


1
Você não pode simplesmente substituir -'0'por -48. Funciona para mim e salva alguns bytes para vários 'X' e ''
Roman Gräf

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)

Isso é fortemente inspirado pela resposta do feersum . A ordem do dia é exagerada: em vez de procurar minas nos 9 vizinhos da célula, verifique todas as células para ver se é uma mina vizinha.

Verificamos se duas células são vizinhas de 2>r>-2<c<2, onde re csão as diferenças de linha e coluna de células, equivalentes a {r,c}<{-1,0,1}. Essas coordenadas são calculadas a partir dos índices das células Ie icomo c=I%n-i%ne r=I/n-i/n. É mais eficiente indexar diretamente na string e extrair linhas e colunas do que convertê-lo em um objeto 2D como uma lista de listas. A verificação da mina é B[i]>'W'equivalente aqui B[i]=='X'.

O uso enumeratesalvaria dois caracteres sobre o feio, range(len(B))exceto que ele retorna um objeto iterador que não suporta dois loops aninhados por ele.


Eu acho que um módulo negativo deve funcionar para n; então você poderia usar ~B.find.
feersum

@feersum Infelizmente, isso estraga tudo, /porque também diminui os negativos.
Xnor

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)))

Forneça entrada para a função como uma sequência:

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

Para uma explicação, consulte a versão antiga, abaixo. A nova versão substitui os forloops por everychamadas e usa a variável e="every"em someArray[e](...)vez de someArray.every(...).

Além disso, o contador kagora é indexado 1para que a k+=...expressão seja sempre verdadeira, a fim de manter o everyloop em execução. Eliminamos esse acréscimo 1subtraindo o trueresultado (que é coercitivo numericamente 1) retornado pela everyoperação [-1,0,k=1][e](...).


Versão antiga:

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}))

Código com espaços e comentários:

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)
          })
      )

O everymétodo da matriz JavaScript recebe um retorno de chamada e aplica o retorno de chamada a todos os elementos da matriz. Se qualquer retorno de chamada retornar um valor falsey, a everychamada retornará false.

Os booleanos em JS são coagidos a 1 ou 0 quando parte de uma adição. Para cada espaço circundante, "adicionamos" o resultado booleano da comparação de seu valor Xe, em seguida, adicionamos esse valor ao contador kna expressão k += (... == "X"). Portanto, kcontém uma contagem do número de Xs circundantes , porque trueconta como 1e falseconta como 0.


Em vez de c=="X"tentar !c/1, você economiza uma quantidade enorme de um par de bytes gritantes! Se falhar, tente !!c/1. O raciocínio é esse 'X'/1 => NaNe NaNé falso. Você verifica se c=='X', por que não tentar verificar se não é false?
Ismael Miguel

@IsmaelMiguel Isso avalia o mesmo que (!c)/1, o que não ajuda, infelizmente; Eu precisaria ter os parênteses para !(c/1), que custam 2. Além disso, 0/1é falsey, portanto a entrada inválida " 0X" teria o resultado incorreto true. O melhor que posso fazer enquanto ainda respeita os zeros é combinar as duas condições em uma frase negada, como !(+c+1&&k-c), mas é o mesmo tamanho que eu já tenho.
Apsillers

@IsmaelMiguel Obrigado por me fazer pensar sobre isso - eu percebi que !(k-1-c)testa ambas as condições, porque se kcorresponde c(menos o deslocamento 1), a negação torna a 0verdade e, se cnão for um número, obtemos NaNa negação é também true.
Apsillers

Você realmente estava com fome! Você comeu 10 bytes desde o código inicial! Eu realmente gosto da solução que você encontrou. +1 para sua solução!
Ismael Miguel

3

CJam, 70 65 63 bytes

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

Isso pode ser muito praticado.

1para uma placa válida e 0para uma placa inválida.

Casos de teste

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

Entrada

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

Saída

1
1
1
0
0
0

Experimente online aqui


3

JavaScript (ES6) 98

Usando some para aplicar uma função a cada caractere da string.
A função retorna

  • falso se em branco
  • NaN se 'X' (subtrair repetidamente valores de um caracter não numérico como 'X' fornece NaN)
  • Um valor numérico de 0 se houver o número certo de 'X' adiacent, senão zero .
    A verificação interna é feita usando o mapa apenas porque é mais curto que paraEach

alguns retornos são verdadeiros no primeiro valor de verdade (neste caso, diferente de zero), o que significa uma falha na verificação. O resultado é negado para fornecer um verdadeiro / falso mais reconhecível.

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
)

Teste no console do 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)))

Saída

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 caracteres

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])

Com recuos, espaços e quebras de linha, para legibilidade:

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])

Exemplos:

> 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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.