Invertir un tablero de Buscaminas

32

Buscaminas es un juego de computadora popular en el que probablemente hayas perdido el tiempo jugando donde tratas de revelar las celdas que son minas en una cuadrícula rectangular en base a pistas de cuántas minas vecinas tiene cada celda no minera. Y en caso de que no lo hayas jugado, hazlo aquí .

Un ingenioso hecho matemático sobre una cuadrícula Buscaminas (también conocido como tablero) es que:

Un tablero y su complemento tienen el mismo número total de minas . ( Prueba )

Es decir, si tiene una cuadrícula del Buscaminas completamente revelada, la suma de todos los números en esa cuadrícula, es decir, el total de la mina , será igual al total de la mina del complemento de la cuadrícula, que es la cuadrícula donde se ha reemplazado cada mina con una no mía y cada no mía reemplazada por una mina.

Por ejemplo, para la cuadrícula Buscaminas

**1..
34321
*2**1

el total de la mina es 1 + 3 + 4 + 3 + 2 + 1 + 2 + 1 = 17.

El complemento de la cuadrícula es

24***
*****
3*44*

que tiene el mío total 2 + 4 + 3 + 4 + 4 = 17 nuevamente.

Escribir un programa que toma en una rejilla arbitraria Minesweeper en forma de texto, donde *representa una mina y 1a través de 8representar el número de minas adyacentes a una célula no mía. Se puede utilizar .o 0o (espacio) para representar a las células sin vecinos mina, su opción. Puede suponer que la cuadrícula de entrada se marcará correctamente, es decir, cada celda que no sea una mina indicará con precisión el número total de minas inmediatamente adyacentes a ella de forma ortogonal o diagonal.

Su programa debe imprimir el complemento de la red en el mismo formato (con el mismo ., 0o como se esperaba en la entrada).

El código más corto en bytes gana.

  • En lugar de un programa, puede escribir una función que tome la cuadrícula de entrada como una cadena e imprima o devuelva la cuadrícula del complemento.
  • Una nueva línea final en la entrada o salida está bien, pero no debe haber otros caracteres además de los que forman la cuadrícula.
  • Puede suponer que una cuadrícula de 1 × 1 será la entrada más pequeña.

Casos de prueba

Todas las entradas y salidas podrían intercambiarse ya que el complemento del complemento es la cuadrícula original. Las rejillas también se pueden girar para otros casos de prueba.

Entrada:

111
1*1
111

Salida:

***
*8*
***

Entrada:

.

Salida:

*

Entrada:

*11*1.1**1...1***1.....1*****1..........

Salida:

1**2***11*****1.1*******1...1***********

Entrada: ( Ejemplo de cortar el nudo )

**212*32
333*33**
1*22*333
222222*1
*33*2232
2**22*2*

Salida:

24***4**
***7**64
*8**7***
******8*
4**7****
*33**5*3
Pasatiempos de Calvin
fuente
TI-BASIC no puede aceptar una línea de entrada vacía. ¿Es ?aceptable usar un delimitador final (por ejemplo ) en la línea después de la línea final del tablero, o podría tomar el número de líneas de entrada a través de la línea de comando?
lirtosiast
@ThomasKwa Un delimitador final suena bien para TI-BASIC y otros idiomas que tienen limitaciones extrañas de nueva línea.
Aficiones de Calvin

Respuestas:

12

Pyth, 39 38 bytes

j.es.eh-+K\*l-s:RtWYY+Y2:+K.zk+k3KZb.z

Pruébelo en línea: demostración

El algoritmo principal es realmente sencillo. Simplemente itero sobre cada celda, tomo el cuadro de 3x3 circundante (o más pequeño cuando la celda está en el borde) e imprimo una estrella o el número de no estrellas en ese cuadro.

Explicación:

j.es.eh-+K\*l-s:RtWYY+Y2:+K.zk+k3KZb.z  implicit: .z = list of input strings
 .e                                 .z  map each index k, line b of .z to:
    .e                             b      map each index Y, char Z of b to:
         K\*                                assign "*" to K
                         +K.z               insert K at the front of .z
                        :    k+k3           slice from k to k+3
               :RtWYY+Y2                    take the slice from Y-1 or 0 
                                            to Y+2 for each line
              s                             join, this gives the 3x3 rectangle
                                             (or smaller on the border)
             -                   K          remove all "*"s
            l                               take the length
        +K                                   "*" + ^
       -                          Z         remove Z from this string
      h                                     and take the first char
                                            (if cell=mine take the number, 
                                             otherwise take the number)
  s                                       join the chars of one line
j                                       join by newlines
Jakube
fuente
Muy ordenado, +1
MKII
22

CJam, 58 57 bytes

0WX]2m*qN/{'*f+z}2*f{\~@m<fm<W<}:..+{W<{_'*#'*@'*-,?}/N}/

La entrada no debe terminar con un salto de línea. La salida contiene 0para celdas sin minas cercanas.

Pruébelo en línea en el intérprete de CJam .

Idea

Comenzamos rellenando la matriz de entrada con una fila y una columna de asteriscos.

Para la entrada

*4*
**2

esto resulta en

*4**
**2*
****

Ahora generamos todas las modificaciones posibles que resultan de rotar las filas y columnas 0, -1 o 1 unidades hacia arriba / izquierda:

*4** **** **2* **4* **** ***2 4*** **** *2**
**2* *4** **** ***2 **4* **** *2** 4*** ****
**** **2* *4** **** ***2 **4* **** *2** 4***

Descartamos las "ubicaciones de relleno" de cada rotación, es decir,

*4* *** **2 **4 *** *** 4** *** *2*
**2 *4* *** *** **4 *** *2* 4** ***

y formar una matriz única concatenando los caracteres correspondientes de cada rotación:

******4** 4*******2 **24*****
*******4* *4****2** 2***4****

El primer personaje de cada posición es su personaje original.

  • Si no es un asterisco, debe reemplazarse con un asterisco.

  • Si es un asterisco, el número de no asteriscos en esa cadena es el número de minas vecinas.

Cómo funciona

0WX]2m*   e# Push the array of all vectors of {0,-1,1}^2.
qN/       e# Read all input from STDIN and split at linefeeds.
{'*f+z}2* e# Append a '*' to each row and transpose rows with columns. Repeat.
f{        e# For each vector [A B], push the modified input Q; then:
  \~      e#   Swap Q with [A B] and dump A and B on the stack.
  @m<     e#   Rotate the rows of Q B units up.
  fm<     e#   Rotate each row of the result A units left.
  W<      e#   Discard the last row.
}         e# This pushes all nine rotations with Manhattan distance 1.
:..+      e# Concatenate the corresponding characters for each position.
{         e# For each row:
  W<      e#   Discard the character corresponding to the last column.
  {       e#   For each remaining string:
    _'*#  e#     Find the first index of '*' in a copy.
    '*    e#     Push '*'.
    @'*-, e#     Count the non-asterisks in the string.
    ?     e#     Select '*' if the index is non-zero, the count otherwise.
  }/      e#
  N       e#   Push a linefeed.
}/        e#
Dennis
fuente
77
Tengo miedo, esto es increíble.
Deusovi
Usted señor, acaba de romper el sistema. +1! ¿Puedo preguntar dónde encontraste esta teoría?
GamrCorps
99
@IonLee Este es todo yo. Es una idea bastante simple, en realidad: en lugar de verificar las celdas alrededor de una celda determinada, movemos toda la cuadrícula y observamos lo que cae dentro de la celda.
Dennis
¡Bravo! Nunca hubiera pensado en eso.
GamrCorps
7

Ruby, 119

->s{w=1+s.index('
')
s.size.times{|c|t=0;9.times{|i|(s+?**w*2)[c+i/3*w-w+i%3-1]<?0||t+=1}
print [t,?*,'
'][s[c]<=>?*]}}

Sin golf en el programa de prueba:

f=->s{
  w=1+s.index("\n")                          #width of board
  s.size.times{|c|                           #iterate through input
    t=0;                                     #number of digits surrounding current cell
    9.times{|i|                              #iterate through 3x3 box (centre must be * if this ever gets printed.)
      (s+"*"*w*2)[c+i/3*w-w+i%3-1]<"0"||t+=1 #copy of s has plenty of * appended to avoid index errors
    }                                        #add 1 every time a number is found.
  print [t,"*","\n"][s[c]<=>"*"]             #if * print t. if after * in ACSII it's a number, print *. if before, it's \n, print \n
  }
}


f['**212*32
333*33**
1*22*333
222222*1
*33*2232
2**22*2*']
Level River St
fuente
2

Octava, 76

m=@(s)char(conv2(b=(cell2mat(strsplit(s)'))~='*',ones(3),'same').*~b-6*b+48)

Explicación

  • Convierta una cadena de entrada en una matriz de cadenas usando strsplity cell2mat.

  • Obtenga la matriz lógica que contiene 1donde no hay *en la matriz original.

  • Tome su convolución con una matriz 3x3 de 1's.

  • Enmascararlo con la matriz lógica inversa y colocarlo *en lugar de la máscara.

  • Nota: Las celdas sin vecinos de mina se representan como 0.

Ejecución

>> m(['**100' 10 '34321' 10 '*2**1'])   %// `10` is newline
ans =

24***
*****
3*44*

>> m(['24***' 10 '*****' 10 '3*44*'])
ans =

**100
34321
*2**1
cubilete
fuente