Completa las pistas del Buscaminas


54

Buscaminas es un popular juego de rompecabezas en el que debes descubrir qué fichas son "minas" sin hacer clic en esas fichas. Cada ficha es una mina (representada por *) o una pista, es decir, un número del 0 al 8 que representa cuántas de las 8 fichas vecinas son minas. Su tarea hoy es tomar una tabla que contenga las minas y completar todas las pistas. Por ejemplo, mira el siguiente tablero de 5x4, con 5 minas:

 *  
*  * 
  *  
    *

Después de completar las pistas, el tablero se verá así:

2*211
*33*1
12*32
0112*

Detalles

Debe escribir un programa completo o una función que incluya una cuadrícula de caracteres que contenga solo espacios y asteriscos y genere otra cuadrícula donde cada espacio se reemplace con el número de minas adyacentes (asteriscos). Cualquiera de estos son formatos aceptables para sus cuadrículas:

  • Una cadena con líneas nuevas

  • Una lista 2D de caracteres / cadenas de caracteres individuales

  • Una lista de cadenas

Puede suponer que la cuadrícula será al menos 1x1, aunque es posible que sea todas las minas o todos los espacios.

La cuadrícula de entrada siempre se rellenará con el número apropiado de espacios. Como de costumbre, este es el , por lo que se aplican las lagunas estándar y gana la respuesta más corta en bytes.

Muestra IO

Para que pueda ver el espacio en blanco, mostraré todas las muestras de E / S con paréntesis.

Input:
[    * ]
[*     ]
[      ]
[      ]
[  **  ]
[ *  * ]

Output:
[1101*1]
[*10111]
[110000]
[012210]
[12**21]
[1*33*1]

Input:
[****]
[****]

Output:
[****]
[****]

Input:
[   ]
[   ]
[   ]
[   ]

Output:
[000]
[000]
[000]
[000]

Input:
[*   ]
[**  ]
[    ]
[   *]

Ouput:
[*310]
[**10]
[2221]
[001*]

Input:
[**    ]
[*    *]
[  *   ]
[      ]
[*     ]
[****  ]

Output:
[**1011]
[*4211*]
[12*111]
[121100]
[*43210]
[****10]

Input:
[     *    ]
[        * ]
[     *    ]
[**   ***  ]
[      *** ]
[          ]
[       ** ]
[  * *     ]
[*      ** ]
[       ** ]

Output:
[00001*1111]
[00002221*1]
[22102*4321]
[**102***31]
[221013***1]
[0000013542]
[0112111**1]
[12*2*12442]
[*212112**2]
[1100002**2]

2
Para su información, hice todo el IO de muestra a mano, por lo que es posible que haya algunos errores menores allí. Avíseme si algo se ve mal e intentaré solucionarlo lo antes posible.
DJMcMayhem


1
¿Puede la cuadrícula ser no cuadrada?
Ton Hospel

¿Pueden las minas representadas por otro personaje?
Akangka

@ChristianIrwan No, las minas siempre serán un asterisco.
DJMcMayhem

Respuestas:


21

MATL , 18 17 bytes

Gracias a @ mbomb007 por una corrección en la entrada del caso de prueba 6

32>t3Y6Z+-6b(48+c

La entrada es una matriz de caracteres 2D, en el formato

[' *   '; '*  * '; '  *  '; '    *']

Pruébalo en línea!

Casos de prueba: 1 , 2 , 3 , 4 , 5 , 6 .

Explicación

32>      % Input 2D char array implicitly. Transform it into a 2D logical
         % array with asterisk replaced by true and space by false
t        % Duplicate
3Y6      % Push [1 1 1; 1 0 1; 1 1 1]. This defines the neighbourhood
Z+       % 2D convolution, keeping size. Gives the number of neighbouring
         % mines for each position
-6       % Push -6
b        % Bubble up in stack
(        % Assign -6 to the entries indicated by the logical array, i.e.
         % to the positions that originally contained asterisks 
48+      % Add 48. This transforms each number of neighbouring mines
         % into its ASCII code, and -6 into 42 (ASCII code of asterisk)
c        % Convert to char. Display implicitly

1
Guau. Eso es impresionante.
BladorthinTheGrey

2
Obtener el caso de prueba 6 me cabrearía jugando el juego real.
Urna mágica de pulpo

¿Por qué? El caso de prueba 6 parece el más realista.
WBT

@carusocomputing Obtener el caso de prueba 2 me cabrearía mucho más. : P
DJMcMayhem

10

JavaScript (ES6), 114 96 bytes

a=>a.map((s,i)=>s.replace(/ /g,(_,j)=>g(k=>(s=a[i+k])?g(k=>s[j+k]>' '):0)),g=f=>f(-1)+f(0)+f(1))

Editar: guardado 18 bytes gracias a una idea de @ETHproductions.


Creo que puede ahorrar un montón definiendo una función para verificar si un índice no es espacio:a=>a.map((s,i)=>s.replace(/ /g,(_,j)=>a.slice(i-!!i,i+2).reduce((t,s)=>t+(q=i=>s[i+j]>' ')(-1)+q(0)+q(1),0)))
ETHproductions

@ETHproductions Llevé tu idea al extremo ... ¡No suelo escribir parámetros de funciones!
Neil

7

R, 127 112 bytes

function(M){a=nrow(M);for(i in seq(M))if(M[i]!="*")M[i]=sum(M[pmax(i+c(-1,1,-a+-1:1,a+-1:1),0)]=="*",na.rm=T);M}

gracias a @gtwebb y @ sebastian-c por las mejoras.

Puntos notables:

Las matrices son vectores en R. No necesita indexación 2D para extraer elementos.

seq(M)devolverá una secuencia de la misma "longitud" (filas x columnas) que M.

No se pueden mezclar índices de extracción positivos y negativos en R. El M[-3]código R es legítimo, pero no es lo que se desea.

La entrada tiene la forma de una matriz R. Algunos ejemplos:

> M <- matrix("",5,5)
> M[3,3] <- "*"
> f(M)
     [,1] [,2] [,3] [,4] [,5]
[1,] "0"  "0"  "0"  "0"  "0" 
[2,] "0"  "1"  "1"  "1"  "0" 
[3,] "0"  "1"  "*"  "1"  "0" 
[4,] "0"  "1"  "1"  "1"  "0" 
[5,] "0"  "0"  "0"  "0"  "0" 
> M[2,2] <- "*"
> f(M)
     [,1] [,2] [,3] [,4] [,5]
[1,] "1"  "1"  "1"  "0"  "0" 
[2,] "1"  "*"  "2"  "1"  "0" 
[3,] "1"  "2"  "*"  "1"  "0" 
[4,] "0"  "1"  "1"  "1"  "0" 
[5,] "0"  "0"  "0"  "0"  "0" 
> M[3,2] <- "*"
> f(M)
     [,1] [,2] [,3] [,4] [,5]
[1,] "1"  "1"  "1"  "0"  "0" 
[2,] "2"  "*"  "3"  "1"  "0" 
[3,] "2"  "*"  "*"  "1"  "0" 
[4,] "1"  "2"  "2"  "1"  "0" 
[5,] "0"  "0"  "0"  "0"  "0" 
> 

1
Puede cortar algunos caracteres usando en Tlugar de TRUE. Me las arreglé para deslizar algunas llaves de una de las funciones if también:f=function(M){a=nrow(M);b=ncol(M);for(i in seq(M))if(M[i]!="*")M[i]=sum(M[pmax(i+c(-1,1,-a+-1:1,a+-1:1),0)]=="*",na.rm=T);M}
sebastian-c

1
Usted define b=ncol(M)y luego no lo usa para poder deshacerse de eso.
gtwebb

Puedo eliminar cuatro caracteres (y vectorizar): M->{a=nrow(M);p=M=='*';M[]=ifelse(p,'*',sapply(seq(M),i->sum(p[pmax(i+c(-1,1,-a+-1:1,a+-1:1),0)],na.rm=T)))}- sin embargo, esto engaña un poco porque requiere una <-lambda redefinida , ver klmr / funcional / lambda
Konrad Rudolph el

@Konrad idea interesante, pero lo mantendré en la base R, gracias!
JDL

6

Java, 190 bytes

Editar:

  • -6 bytes desactivados. Gracias a @Frozn
  • -1 byte desactivado. Gracias a mi mismo :)
  • -1 byte desactivado. También vimos algunos errores. Gracias a @Kevin Cruijssen

Snipet

c->{for(int x,y,j,i=-1;++i<c.length;)for(j=-1;++j<c[0].length;){if(c[i][j]<33){c[i][j]=48;for(x=i-2;++x<i+2;)for(y=j-2;++y<j+2;)try{if(c[x][y]==43)c[i][j]++;}catch(Exception e){}}}return c;}

Sin golf:

public class Main{
  public static char[][] minesweeper(char[][] woclues){
    for(int i = 0; i < woclues.length ; i++){
      for(int j = 0; j < woclues[0].length ; j++){
        if( woclues[i][j] == ' '){
          woclues[i][j] = '0';
          for(int x = i - 1; x < i + 2 ; x++){
            for(int y = j - 1; y < j + 2 ; y++){
              try{
                if(woclues[x][y] == '*'){
                  woclues[i][j]++;
                }
              }catch( ArrayIndexOutOfBoundsException e){}
            }
          }
        }
      }
    }
    return woclues;
  }
  public static void main(String[]args){
    char[][] in = new char[args.length][args[0].length()];
    for(int i = 0; i < args.length;i++){
      in[i]=args[i].toCharArray();
    }
    for(char[] c:minesweeper(in)){
      System.out.println(new String(c));
    }
  }
}

Ideónalo.


Puede comparar los valores de caracteres con los valores ASCII que deberían ser más cortos en la mayoría de los casos. También puede combinar las declaraciones dex,y,i,j
Frozn

Ya lo hice c[i][j]==32y así sucesivamente, y simplemente los cambié en la parte de Ungolfed
Roman Gräf

Y soy más bajo que Phyton. ¡Al menos!
Roman Gräf

¿Estás seguro de que tu código no es correcto? Para el primer caso de prueba que da salida: 0000*1\n*10011\n110000\n000000\n00**10\n0*22*1. ¿Podría agregar un enlace de prueba de ideone.com? EDITAR: Además, a menos que yo mismo esté haciendo algo mal, su salida de código de golf: ssss0s\n0sssss\nssssss\nssssss\nss00ss\ns0ss0spara el primer caso de prueba (ha reemplazado todo *con ceros ...): S
Kevin Cruijssen

Editado Agregaré un enlace de prueba tan pronto como mi Internet anterior me lo permita.
Roman Gräf

5

JavaScript (ES6), 107

Entrada / salida como un conjunto de cadenas

f=l=>l.map((r,i)=>r.replace(/ /g,(c,j)=>(s=r=>(c+r).substr(j,3).split`*`.length,s(l[i-1])+s(l[i+1])+s(r)-3)))

tenga en cuenta que cuando se llama a la función s con un elemento de la lista l fuera de los límites, el parámetro aes undefinedy c+aresultará " undefined"gracias a las extrañas reglas de conversión de javascript

Más legible

l=>
  l.map(
    (r,i) =>
      r.replace(/ /g, (c,j) =>
        (
          s = a => (c+a).substr(j,3).split`*`.length,
          s(l[i-1])+s(l[i+1])+s(r)-3
        )
      )
  )

5

Python 2, 138 bytes

def f(s):w=s.find('\n')+1;print''.join([c,`(s[i-(i>0):i+2]+(w*' '+s)[i-1:i+2]+s[i-1+w:i+2+w]).count('*')`][c==' ']for i,c in enumerate(s))

Define una función fque acepta una cadena de entrada como

"  *\n** \n*  \n"

e imprime una cadena en STDOUT:

23*
**2
*31

1
Haga enumerate start from 2 ( enumerate(s,2)) y reemplace todas las apariciones de i + 2with iy i - 1with i - 3. Eso reducirá un par de bytes.
Roberto Bonvallet

5

JavaScript (ES6) 186 182 177 161 152 bytes

f=a=>{for(s='',y=a[0].length;y--;)for(s=`
`+s,x=a.length;x--;)(k=>{for(t=0,i=9;i--;)t+=(a[x+i%3-1]||[])[y+i/3-1|0]==k;s=(a[x][y]<k?t:k)+s})`*`;return s}

Actualizar

El código anterior para " *"devoluciones "2*". Esto se soluciona en el siguiente script.

168 167 bytes

f=a=>{for(s='',y=a[0].length;y--;)for(s=`
`+s,x=a.length;x--;)a[x][y]=='*'?s='*'+s:(k=>{for(t=0,j=3;j--;)for(i=3;i--;)t+=(a[x+i-1]||1)[y+j-1]=='*';s=t+s})`*`;return s}

Pruébalo aquí


1
Creo que t+=(a[x+i%3-1]||[])[y+i/3-1|0]==kdebería funcionar de manera similar y ahorrarle la parte try/ catch.
Arnauld

1
@Arnauld. En realidad, leer una propiedad de número literal no arrojará un error, por lo que también se puede mejorar como (a[x+i%3-1]||1)[y+i/3-1|0].
sbisit

4

Haskell, 115 bytes

z=zip[1..]
x%i=[a|(j,a)<-z x,abs(i-j)<2]
f x=[[head$[c|c>' ']++show(sum[1|'*'<-(%j)=<<x%i])|(j,c)<-z r]|(i,r)<-z x]

Define una función fen listas de cadenas


3

Python 2, 192 bytes

-3 bytes gracias a Copper, -10 bytes si se permite modificar la cuadrícula de entrada, otros -11 bytes continueeliminando y otros -12 bytes para eliminar la variable del contador

def f(L):
 n,S,s=len(L[0]),[0,1,2],[' '];P=[s*(n+2)];K=P+[s+x+s for x in L]+P
 for y in range(len(L)):
    for x in range(n):
     if'*'!=L[y][x]:L[y][x]=`sum(K[y+d][x+e]=='*'for d in S for e in S)`

Utiliza una lista de caracteres Ly crea una versión acolchada K, por lo que no hay problema en los límites. La sangría es

  1. Espacio
  2. Lengüeta
  3. Tab + espacio
  4. Tab + Tab

Uso:

s=""" *   
*  * 
  *  
    *"""
print s
s=[[c for c in x] for x in s.split('\n')]
f(s)
s='\n'.join([ ''.join(x) for x in s])
print s

1
Algunos campos de golf menores: puede colocar sus primeras tres asignaciones de variables en la misma línea separadas por punto y coma y perder la sangría. Además, use if'*'==L[y][x]:para guardar un byte.
Cobre

Si asigna r=range;en la misma línea que n,S,s, puede guardar cinco caracteres reemplazando las llamadas range(...)con r(...).
alexwlchan

@alexwlchan haciendo esto ahorra 2 * angepor lo que 8 bytes, pero tengo que agregar ,ry ,rangeque también es de 8 bytes, por lo que no se gana nada.
Karl Napf

@KarlNapf Gah, tienes razón: me había olvidado de la range.
alexwlchan

3

Ruby, 112

Toma y devuelve una cadena. La cadena debe estar separada por nueva línea y terminada por nueva línea.

->s{w=1+s=~/\n/
s.size.times{|i|s[i]==' '&&(n=0;9.times{|j|(s+$/*w)[i+j%3-1+j/3*w-w]==?*&&n+=1};s[i])=n.to_s}
s}

en programa de prueba

f=->s{
  w=(s=~/\n/)+1                              #Calculate width.
  s.size.times{|i|                           #For each char in s
    s[i]==' '&&(                             #If it is a space
      n=0                                    #set counter n to 0 and visit
      9.times{|j|                            #a 3x3 square of chars.
        (s+$/*w)[i+j%3-1+j/3*w-w]==?*&&n+=1  #If *, increment n.
      }                                      #(Pad s with w newlines to avoid *'s detected by wraparound.)
      s[i]=n.to_s                            #Write n back to s in string format
    )
  }
s}                                           #Return s.

puts f[
" *   
*  * 
  *  
    *
"]

3

TSQL 292 291 bytes

Golfizado:

DECLARE @ varchar(max)=
' *   
*  * 
  *  
    *';
WITH C as(SELECT x+1i,substring(@,x+1,1)v,x/z r,x%z c FROM master..spt_values CROSS APPLY(SELECT number x,charindex(char(10),@)z)z WHERE type='P'and x<len(@))SELECT @=stuff(@,i,1,z)FROM(SELECT i,(SELECT count(*)FROM C WHERE abs(D.c-c)<2and abs(D.r-r)<2and'*'=v)z FROM C D WHERE''=v)h PRINT @

Sin golf:

DECLARE @ varchar(max)=
' *   
*  * 
  *  
    *';
WITH C as
(
  SELECT x+1i,substring(@,x+1,1)v,x/z r,x%z c
  FROM master..spt_values
  CROSS APPLY(SELECT number x,charindex(char(10),@)z)z
  WHERE type='P'and x<len(@)
)
SELECT @=stuff(@,i,1,z)
FROM
(
  SELECT
    i,
    (
      SELECT count(*)
      FROM C
      WHERE 
       abs(D.c-c)<2and abs(D.r-r)<2and'*'=v
    )z
  FROM C D
  WHERE''=v
)h
PRINT @

Violín


¿Cuenta ;al principio de su código? Parece que lo has contado.
Erik the Outgolfer

@EriktheGolfer Sí, donde hay un script anterior a WITH. El compilador dará un error si se elimina. Es posible probar ideas en el violín
t-clausen.dk

Quiero decir, ¿debería estar en el recuento de bytes de la fuente general? Porque parece que debería ser parte de la declaración "STDIN inicial" en su lugar.
Erik the Outgolfer

@EriktheGolfer Realmente no lo sé, supongo que puede ser parte de la declaración. También puede excluir al maestro ... si hay un maestro de USO al comienzo del script. Pero da un mensaje molesto en el violín.
t-clausen.dk

Intenté poner el punto y coma en la línea anterior, y funcionó. Supongo que la última línea es lo que cuenta.
Erik the Outgolfer

2

Raqueta 415 bytes

(let*((l(string->list s))(g (λ(r c)(if(or(>= r n)(>= c n)(< r 0)(< c 0))#f(list-ref l(+ c(* n r))))))(ng (λ(r c)(let*((h'(-1 0 1))(k(filter(λ(x)x)
(for*/list((i h)(j h)#:unless(= 0 i j))(g(+ r i)(+ c j))))))(count(λ(x)(equal? x #\*))k))))(k(for*/list((i n)(j n))(ng i j)))
(ol(map(λ(x y)(if(equal? x #\*)"*"(number->string y)))l k)))(for((i(* n n))(j ol))(display j)(when(= 0(modulo(add1 i)n))(displayln ""))))

Sin golf:

(define (f s n)
  (let* ((l (string->list s))
         (get                            ; fn to get value at a (row, col)
          (lambda(r c)                   ; #f if invalid row or col
            (if (or (>= r n)
                    (>= c n)
                    (< r 0)
                    (< c 0))
                #f (list-ref l (+ c (* n r))))))

         (neighbors                      ; fn to count neighboring "*"
          (lambda(r c)
            (let* ((h '(-1 0 1))
                   (u (filter
                       (lambda(x) x)
                       (for*/list ((i h)(j h)
                                   #:unless (= 0 i j))
                         (get (+ r i) (+ c j))))))
              (count (lambda(x)(equal? x #\*)) u))))

         (k (for*/list ((i n) (j n))    ; for each row,col count neighboring "*"
              (neighbors i j)))
         (ol(map (lambda(x y)           ; get outlist- replace blanks with neighboring star count
                   (if(equal? x #\*) 
                      "*"
                      (number->string y)))
                 l k)))

    (for ((i (* n n))(j ol))            ; display outlist
      (display j)
      (when (= 0 (modulo (add1 i) n))
        (displayln "")))))

Prueba (enumera como una sola cadena con el número de columna especificado; también funcionará con espacios):

(f "----*-*-------------------**---*--*-" 6) 

Salida:

1101*1
*10111
110000
012210
12**21
1*33*1

2

PHP, 145 133 132 127 bytes

for($s=$argv[1];$s[$p];print$c)if(" "==$c=$s[$p++])for($y=-2;$y++<1;)for($x=$p-3;$x++<$p;)$c+="!"<$s[$x+$y*strpos($s,"\n")+$y];

toma la entrada como una sola cadena, nueva línea separada. Corre con -r.

Descompostura

for($s=$argv[1];$s[$p]; // loop through all characters (including newlines)
    print$c                     // 3. print result
)
    if(" "==$c=$s[$p++])        // 1. if character is space
        for($y=-2;$y++<1;)      // 2. count surrounding asterisk characters
            for($x=$p-3;$x++<$p;)
                $c+="!"<$s[$x+$y*strpos($s,"\n")+$y];

"!">$n=$s[$p]en lugar de " "==$n=$s[$p]
guardar

@ JörgHülsermann Eso destruiría los saltos de línea.
Titus

@ JörgHülsermann ... pero el truco funciona para la comparación de asteriscos (en la nueva versión)
Titus

2

Turtlèd , 99 bytes

(whoops sigo olvidando el enlace: |)

Toma entradas con corchetes alrededor de cada línea

Turtlèd no puede tomar entradas de varias líneas, por lo tanto, después de la última línea, escriba |al final de la señal de entrada

Tenga en cuenta que los corchetes no coinciden porque los corchetes abiertos analizan el siguiente carácter como parte del comando de corchetes

[|!.([[]r+.][[l]d)][ u]d[|[]r( #012345678#l(*+)u(*+)r(*+)r(*+)d(*+)d(*+)l(*+)l(*+)ur.)]' [[l]' d]' 

Pruébalo en línea!

Cómo funciona (descripción general):

Hasta que |se ingresa, escribe la entrada en cada línea, con corchetes para ayudarlo a reconocer el final de cada línea. Después de que eso ha sucedido, vuelve a la parte superior de la entrada. Pasa por cada carácter en la entrada. Si es un espacio, mira alrededor del espacio, agregando uno al contador por cada bomba que encuentre. después de cada línea, elimina los corchetes. Cuando llega a la última línea, con el | en él, se detiene y elimina el |. la cuadrícula se imprime implícitamente.


0

C, 152 150 147 145 bytes

i,j,r,c;f(B,R,C)char**B;{for(i=R*C;i--;)for(j=9;j--;){char*b=B[i/C]+i%C;r=i/C+j/3-1;c=i%C+j%3-1;r<0|c<0|r/R|c/C|*b&8||(*b=16|*b+(B[r][c]==42));}}

La entrada tiene la forma de una matriz bidimensional de caracteres, seguida del número de filas y columnas. El resultado será devuelto en su lugar.

(Principalmente) Sin golfos:

i, j, r, c;
f(B, R, C) char **B; {
    for (i = R*C; i--;)
        for (j = 9; j--;) {
            char *b = B[i/C] + i%C;
            r = i/C + j/3 - 1;
            c = i%C + j%3 - 1;
            r < 0 | c < 0 | r / R | c / C | *b & 8 ||
                (*b = 16 | *b + (B[r][c] == 42));
        }
}

El enfoque es directo: haga un bucle sobre cada posición, haga un bucle sobre sus vecinos y sume todos los asteriscos. Hay dos trucos a nivel de bits:

  • Cuando estamos decidiendo si una celda es un asterisco o no, simplemente podemos verificar si el bit de ocho lugares está establecido, porque el número en la celda debe ser menor que 8 (el valor máximo de la celda).

  • Podemos convertir un carácter de espacio en un carácter cero OR-ing 16.

Editar: Golfed dos bytes mediante el uso de /en lugar de >=.

Editar: Otros cinco bytes invirtiendo la dirección de los bucles.


0

C #, 341 bytes

Una implementación ingenua que definitivamente se puede acortar.

s=>s=="*"?1:0;s=>{for(int i=0,j,n,l=s.Length,c=s[i].Length;i<l;++i)for(j=0;j<c;++j)if(s[i][j]!="*"){n=0;if(i>0){n+=a(s[i-1][j]);n+=j>0?a(s[i-1][j-1]):0;n+=j+1<c?a(s[i-1][j+1]):0;}n+=a(s[i][j]);n+=j>0?a(s[i][j-1]):0;n+=j+1<c?a(s[i][j+1]):0;if(i+1<l){n+=a(s[i+1][j]);n+=j>0?a(s[i+1][j-1]):0;n+=j+1<c?a(s[i+1][j+1]):0;}s[i][j]=n+"";}return s;};

0

Python 2, 183 bytes

def s(m):
 j=m.find('\n')+1;q='q'*j*2;m=list(q+m+q)
 for i in range(len(m)):
  if m[i]==' ':m[i]=`sum([m[k+i]=='*'for k in [-j-1,-j,-j+1,-1,1,j-1,j,j+1]])`
 return''.join(m)[j*2:-j*2]
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.