Campo Minado é um jogo de quebra-cabeça popular, onde você deve descobrir quais peças são "minas" sem clicar nessas peças. Em vez disso, você clica em blocos próximos para revelar o número de minas adjacentes. Uma desvantagem do jogo é que é possível acabar em um cenário em que há várias respostas válidas e você pode apenas adivinhar. Por exemplo, considere a seguinte placa:
1110
2*31
3*??
2*4?
112?
Nesse formato, um número representa o número de minas adjacentes, um *
representa uma mina conhecida e um "?" representa uma mina em potencial. O lamentável desse quebra-cabeça em particular é que existem quatro soluções possíveis distintas e válidas :
1110 1110 1110 1110
2*31 2*31 2*31 2*31
3*4* 3*5* 3**2 3**1
2*42 2*4* 2*4* 2*42
112* 1121 1121 112*
Isso significa que o conselho é insolúvel . Aqui está um exemplo de uma placa solucionável :
1121
1??*
12?*
0122
Esta placa é solucionável porque existe apenas uma solução válida possível:
1121
1*4*
12**
0122
Sua tarefa é escrever um programa ou função que use uma placa de caça-minas válida e determine se é solucionável ou não. Por "placa de caça-minas válida", quero dizer que a entrada sempre será retangular, terá pelo menos uma solução e não conterá caracteres inválidos.
Sua entrada pode ser uma matriz de caracteres, uma matriz de cadeias, uma cadeia contendo novas linhas, etc. A saída deve ser um valor verdadeiro, se for solucionável, e um valor falso, se não for. Não estou extremamente preocupado com o desempenho, mas sua solução deve teoricamente funcionar para qualquer tamanho de entrada.
Como sempre, as brechas padrão se aplicam e a solução mais curta em bytes vence!
Exemplos:
Os seguintes exemplos são todos solucionáveis:
1121
1??*
12?*
0122
1110
1???
1110
0000
1110
3???
??20
*310
****
****
****
****
0000
0000
0000
0000
1100
*100
2321
??*2
13*2
1221
1*10
1110
1121
2*??
2*31
2220
1*10
Os exemplos a seguir são todos insolúveis:
1110
2*31
3*??
2*4?
112?
01??11*211
12??2323*1
1*33*2*210
12?2122321
13?3101**1
1***101221
1***
3*52
2*31
12??
02??
01??
00000111
000012*1
00001*21
22101110
**100111
?31123*1
?311**31
**113*20
fonte
2?
não tem soluções, o que significa que não pode vir de um jogo real do Campo Minado Por isso, não é considerado um "board Campo Minado" ... sim.?)Respostas:
GNU Prolog, 493 bytes
Um predicado extra que pode ser útil para testes (não faz parte do envio):
O Prolog é definitivamente o idioma certo para resolver esta tarefa do ponto de vista prático. Este programa praticamente estabelece as regras do Minesweeper e permite que o solucionador de restrições do GNU Prolog resolva o problema a partir daí.
z
ei
são funções utilitárias (z
realiza uma espécie de operação semelhante a dobra, mas em conjuntos de três elementos adjacentes em vez de 2;i
transpõe 3 listas de n elementos para uma lista de n 3 tuplas). Armazenamos internamente uma célula como , onde x é 1 para uma mina e 0 para uma não mina e y é o número de minas adjacentes; expressa essa restrição no quadro. aplica - se a todas as linhas do tabuleiro; e assim verifica se é um quadro válido.x/y
c
r
c
z(r,M)
M
Infelizmente, o formato de entrada necessário para fazer esse trabalho diretamente não é razoável, então eu também precisei incluir um analisador (que provavelmente é responsável por mais código do que o mecanismo de regras real e a maior parte do tempo gasto na depuração; o mecanismo de regras do Minesweeper praticamente funcionou primeira vez, mas o analisador estava cheio de pensamentos).
q
converte uma única célula entre um código de caractere e nosso formato. converte uma linha do tabuleiro (deixando uma célula que se sabe não ser uma mina, mas com um número desconhecido de minas vizinhas, em cada extremidade da linha como uma borda);x/y
l
p
converte o quadro inteiro (incluindo a borda inferior, mas excluindo a borda superior). Todas essas funções podem ser executadas para frente ou para trás, portanto, podem analisar e imprimir o quadro de maneira bonita. (Há algumas oscilações irritantes com o terceiro argumento parap
, que especifica a largura da placa; isso ocorre porque o Prolog não possui um tipo de matriz e, se eu não restringir a placa a ser retangular, o programa entrará em um loop infinito tentando bordas progressivamente mais amplas ao redor do quadro.)m
é a principal função de resolução do Campo Minado. Ele analisa a sequência de entrada, gerando uma placa com uma borda correta (usando o caso recursivo dep
para converter a maior parte da placa e chamando o caso base diretamente para gerar a borda superior, que tem a mesma estrutura da borda inferior). Então chamaz(r,[R|M])
para executar o mecanismo de regras do Campo Minado, que (com esse padrão de chamada) se torna um gerador que gera apenas placas válidas. Nesse ponto, o conselho ainda é expresso como um conjunto de restrições, o que é potencialmente estranho para nós; talvez pudéssemos ter um único conjunto de restrições que poderiam representar mais de uma diretoria. Além disso, ainda não especificamos em nenhum lugar que cada quadrado contenha no máximo uma mina. Como tal, precisamos explicitamente "recolher a forma de onda" de cada quadrado, exigindo que seja especificamente uma mina (única) ou uma não mina, e a maneira mais fácil de fazer isso é executá-la no analisador de trás para a frente (var(V)
noq(63,V)
A caixa foi projetada para impedir que a?
caixa se mova para trás e, portanto, a separação da placa o força a ser totalmente conhecida). Finalmente, retornamos o quadro analisado dem
;m
torna-se assim um gerador que pega uma placa parcialmente desconhecida e gera todas as placas conhecidas consistentes com ela.Isso é realmente suficiente para resolver o Campo Minado, mas a pergunta pede explicitamente para verificar se existe exatamente uma solução, em vez de encontrar todas as soluções. Como tal, escrevi um predicado extra
s
que simplesmente converte o geradorm
em um conjunto e, em seguida, afirma que o conjunto possui exatamente um elemento. Isso significa ques
retornaráyes
verdade ( ) se houver de fato exatamente uma solução ou falsey (no
) se houver mais de uma ou menos de uma.d
não faz parte da solução e não está incluído no bytecount; é uma função para imprimir uma lista de strings como se fosse uma matriz, o que possibilita inspecionar as placas geradas porm
(por padrão, o GNU Prolog imprime strings como uma lista de códigos ASCII, porque trata os dois como sinônimos; este formato é bastante difícil de ler). É útil durante o teste ou se você deseja usarm
como um solucionador prático do Campo Minado (porque usa um solucionador de restrições, é altamente eficiente).fonte
Haskell,
193169168 bytesExemplo de uso:
g "1121 1??* 12?* 0122"
->True
.Como funciona: faça uma lista de todas as placas possíveis com as
?
substituídas por um*
ou!
(!
significa ignorar mais tarde). Isso é feito viamapM c
, mas antes de adicionar e acrescentar vários espaços à string de entrada, para que nossa indexação não fique fora do intervalo. Para cada tal verificação bordo se é uma placa válida por looping sobre todos os elementos (índicej
) e se é um número (d>'/'
) também em relação aos seus vizinhos (índicen
,m
), contar o*
e comparar com o número. Por fim, verifique o comprimento da lista de painéis válidos.fonte
Mathematica,
214192190180176174168165 bytesContém U + F4A1 (uso privado). Esta função sem nome localiza todas as combinações possíveis para
"?"
(ou seja, substitui todos os"?"
s por"*"
ou0
) e verifica se há apenas uma solução válida.Explicação
Defina
b
como"*"
.Defina
q
para a sequência"?"
. Verifique se há"?"
na entrada.Se
True
...Substitua a primeira ocorrência de
q
(="?"
) porb
(="*"
) ou0
( ou seja, duas saídas) e aplique toda a função novamente.Se
False
...Almofada a entrada com uma camada de
0
.Particione a entrada em matrizes 3 x 3 com deslocamento 1. Para cada partição, aplique uma função tal que, se o valor do meio for
b
(="*"
), a saída for ob
(="*"
), e se o valor do meio não forb
(="*"
), o output é o número deb
(="*"
) na entrada. Esta etapa reavalia todas as células numéricas.De todos os resultados, encontre os que correspondem à entrada
Verifique se a entrada tem comprimento 1.
fonte
Perl, 215 bytes
213 bytes de código +
-p0
sinalizadores (2 bytes).A idéia do código é testar todas as possibilidades e verificar se existe uma e apenas uma que leva a um quadro totalmente preenchido válido.
Mais legível, o código se parece com:
Sobre a regex no meio:
Note que
[^V]
apenas significa "qualquer caractere, incluindo \ n".Portanto, a idéia é: 3 caracteres em uma linha, depois 3 na próxima (com
$i
no meio) e depois 3 na próxima. esses 3 grupos de 3 números estão alinhados, graças ao[^V]{$c}
número em que estamos interessados está no meio.E, então,
"$1$2$3"=~y%*%%
conta o número de*
(bombas) entre esses 9 caracteres: se for diferente$i
, adicionamos uma string vazia para corresponder (""
=> correspondência instantânea, a regex retorna true); caso contrário, forçamos uma falha ao tentar corresponderR
( que não pode estar na string).Se os jogos de regex, então a bordo não é válido, então vamos definir
$r
a0
com$r&=!/.../
.E é por isso que adicionamos alguns
A
em todos os lugares em torno de cada linha: para que não tenhamos de nos preocupar com casos extremos de números que estão próximos dos limites do quadro: eles terãoA
como vizinhos, que não são minas (é claro, praticamente qualquer caractere poderia ter trabalho, Eu escolhiA
).Você pode executar o programa na linha de comando assim:
A complexidade não poderia ser pior: é
O(m*9^n)
onden
está o número de?
no quadro em
o número de células no quadro (sem contar a complexidade da regex no meio, o que provavelmente é muito ruim). Na minha máquina, ele funciona muito rápido para até 4?
e começa a ficar mais lento 5, leva alguns minutos para 6 e não tentei números maiores.fonte
JavaScript (ES6),
222222Se toda a entrada for válida - ou seja, com pelo menos 1 solução -, eu posso salvar uma alteração de bytes==1
coms<2
Menos golfe
Teste
fonte
JavaScript (Node.js) , 167 bytes
Experimente online!
Embora op diga "a entrada sempre será retangular, tenha pelo menos uma solução", a amostra falsa 3 não corresponde, por isso ainda preciso de 1 solução, não <2 solução
fonte