Preencha as dicas do Campo Minado


54

Campo Minado é um jogo de quebra-cabeça popular, onde você deve descobrir quais peças são "minas" sem clicar nessas peças. Cada peça é uma mina (representada por *) ou uma pista, ou seja, um número de 0 a 8 representando quantas das 8 peças vizinhas são minas. Sua tarefa hoje é pegar uma placa contendo as minas e preencher todas as pistas. Por exemplo, observe a seguinte placa 5x4, com 5 minas:

 *  
*  * 
  *  
    *

Depois de preencher as pistas, o quadro ficará assim:

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

Detalhes

Você deve escrever um programa completo ou uma função que capte uma grade de caracteres contendo apenas espaços e asteriscos e produza outra grade em que cada espaço seja substituído pelo número de minas adjacentes (asteriscos). Qualquer um destes são formatos aceitáveis ​​para suas grades:

  • Uma string com novas linhas

  • Uma lista 2D de caracteres / cadeias de caracteres únicos

  • Uma lista de strings

Você pode assumir que a grade será de pelo menos 1x1, embora seja possível que seja todas as minas ou todos os espaços.

A grade de entrada sempre será preenchida com o número apropriado de espaços. Como de costume, esse é um , então as brechas padrão se aplicam e a resposta mais curta em bytes vence!

IO de amostra

Para que você possa ver o espaço em branco, mostrarei todas as E / S de amostra com colchetes ao redor.

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 sua informação, fiz manualmente todo o IO da amostra, portanto é possível que haja alguns erros menores. Deixe-me saber se algo der errado e tentarei corrigi-lo o mais rápido possível.
DJMcMayhem


11
A grade pode ser não quadrada?
Ton Hospel

As minas podem ser representadas por outro personagem?
Akangka

@ChristianIrwan Não, as minas sempre serão um asterisco.
DJMcMayhem

Respostas:


21

MATL , 18 17 bytes

Obrigado a @ mbomb007 pela correção na entrada do caso de teste 6

32>t3Y6Z+-6b(48+c

A entrada é uma matriz de caracteres 2D, no formato

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

Experimente online!

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

Explicação

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

11
Uau. Isso é impressionante.
BladorthinTheGrey

2
Obter o caso de teste 6 me irritaria ao jogar o jogo real.
Urna Mágica de Polvo

Por quê? O caso de teste 6 parece o mais realista.
WBT

@carusocomputing Obter o caso de teste 2 me irritaria muito mais. : 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: salvou 18 bytes graças a uma ideia de @ETHproductions.


Eu acho que você pode salvar um monte através da definição de uma função para verificar se um índice é não-espaço: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 Levei sua ideia ao extremo ... Normalmente, não consigo escrever parâmetros de função!
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}

obrigado a @gtwebb e @ sebastian-c por melhorias.

Pontos notáveis:

Matrizes são vetores em R. Você não precisa de indexação 2D para obter elementos.

seq(M)retornará uma sequência do mesmo "comprimento" (linhas x colunas) que M.

Você não pode misturar índices de extração positivos e negativos em R. M[-3]é o código R legítimo, mas não o que é desejado.

A entrada está na forma de uma matriz R. Alguns exemplos:

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

11
Você pode cortar alguns caracteres usando em Tvez de TRUE. Eu consegui deslizar algumas chaves fora de uma das funções if também: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

11
Você define b=ncol(M)e, em seguida, não o usa para se livrar disso.
Gtwebb # 24/16

Eu posso raspar quatro personagens (e vectorize): 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)))}- no entanto, este fraudes ligeiramente porque requer uma redefinição <-lambda, consulte klmr / funcional / lambda
Konrad Rudolph

@ Konrad idéia interessante, mas vou mantê-lo para basear R obrigado!
JDL

6

Java, 190 bytes

Editar:

  • -6 bytes desativados. Graças a @Frozn
  • -1 byte desativado. Graças a mim mesmo :)
  • -1 byte desativado. Também viu alguns erros. Obrigado 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;}

Ungolfed:

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

Ideone it.


Você pode comparar os valores de char com os valores ASCII, que devem ser mais curtos na maioria dos casos. Você também pode combinar as declarações dex,y,i,j
Frozn

Eu já fiz c[i][j]==32e assim por diante e apenas mudou-los na parte Ungolfed
Roman Gräf

E eu sou mais baixo que Phyton. Finalmente!
Roman Gräf 23/10

Tem certeza de que seu código não-protegido está correto? Para o primeiro caso de teste ele gera: 0000*1\n*10011\n110000\n000000\n00**10\n0*22*1. Você poderia adicionar um link de teste ideone.com? EDIT: Além disso, a menos que eu estou fazendo algo errado eu, sua saída código golfed: ssss0s\n0sssss\nssssss\nssssss\nss00ss\ns0ss0spara o primeiro caso de teste (que substituiu todos *com zeros ..): S
Kevin Cruijssen

Editado. Vou adicionar um link de teste assim que minha pior internet permitir isso.
Roman Gräf 24/10

5

JavaScript (ES6), 107

Entrada / saída como uma matriz de strings

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

note que quando a função s é chamada com um elemento da lista l fora dos limites, o parâmetro aé undefinede c+aresultará em " undefined"graças às regras peculiares de conversão do javascript

Mais legível

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 uma função fque aceita uma sequência de entrada como

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

e imprime uma string para STDOUT:

23*
**2
*31

11
Faça enumerar start from 2 ( enumerate(s,2)) e substitua todas as ocorrências de i + 2with ie i - 1with i - 3. Isso reduzirá alguns bytes.
Roberto Bonvallet 25/10

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}

Atualizar

O código acima para " *"devoluções "2*". Isso foi corrigido no seguinte 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}

Experimente aqui.


11
Eu acho que t+=(a[x+i%3-1]||[])[y+i/3-1|0]==kdeve funcionar de maneira semelhante e salvar a parte try/ catch.
Arnauld 23/10

11
@Arnauld. Na verdade, a leitura de uma propriedade de número literal não gera um erro, portanto também pode ser aprimorada 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 uma função fnas listas de strings


3

Python 2, 192 bytes

-3 bytes graças ao cobre, -10 bytes se a modificação da grade de entrada for permitida, outros -11 bytes se livrando continuee outros -12 bytes para eliminar a variável do 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)`

Usa uma lista de lista de caracteres Le cria uma versão acolchoada K, para que não haja problemas nos limites. O recuo é

  1. Espaço
  2. Aba
  3. Tabulação + espaço
  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

11
Alguns pequenos golfe: você pode colocar suas três primeiras atribuições de variáveis ​​na mesma linha, separadas por ponto e vírgula e perder o recuo. Além disso, use if'*'==L[y][x]:para salvar um byte.
Cobre

Se você atribuir r=range;na mesma linha que n,S,s, poderá salvar cinco caracteres substituindo as chamadas range(...)por r(...).
23416 alexwlchan

@alexwlchan fazendo isso economiza 2 * ange8 bytes, mas eu tenho que adicionar ,re ,rangeque também é 8 bytes para que nada seja ganho.
Karl Napf

@KarlNapf Gah, você está certo - eu tinha esquecido o range.
alexwlchan

3

Ruby, 112

Pega e retorna uma string. A sequência deve ser separada por nova linha e encerrada.

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

no programa de teste

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

Golfe:

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 @

Ungolfed:

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 @

Violino


A parte ;da frente do seu código conta? Parece que você contou isso.
Erik the Outgolfer

@EriktheGolfer Sim, onde existe um script anterior ao WITH. O compilador apresentará um erro se for removido. É possível testar idéias no violino
t-clausen.dk 24/10

Quero dizer, deveria estar na contagem de bytes da fonte geral? Porque parece que deve fazer parte da instrução "Initial STDIN".
Erik the Outgolfer

@EriktheGolfer Realmente não sei, suponho que possa fazer parte da declaração. Também pode excluir mestre. Se houver um mestre USE no início do script. Mas dá uma mensagem irritante no violino.
t-clausen.dk

Tentei colocar o ponto e vírgula na linha anterior e funcionou. Presumo que a última linha é o que conta.
Erik the Outgolfer

2

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

Ungolfed:

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

Teste (lista como uma única sequência com o número da coluna especificado; também funcionará com espaços):

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

Resultado:

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

recebe entrada como sequência única, nova linha separada. Corra com -r.

demolir

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]em vez de " "==$n=$s[$p]salvar um byte
Jörg Hülsermann 24/10

@ JörgHülsermann Isso destruiria as quebras de linha.
Titus

@ JörgHülsermann ... mas o truque funciona para a comparação asterisco (na nova versão)
Titus

2

Turtlèd , 99 bytes

(gritos, continuo esquecendo o link: |)

Toma entradas com colchetes ao redor de cada linha

Turtlèd não pode receber entrada com várias linhas; portanto, após a última linha, escreva |para sinalizar o final da entrada

Observe que os colchetes incompatíveis são porque os colchetes abertos analisam o próximo caractere como parte do comando bracket

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

Experimente online!

Como funciona (descrição geral):

Até que |seja digitada, ela grava a entrada em cada linha, entre colchetes, para ajudá-lo a reconhecer o final de cada linha. Depois que isso acontece, ele volta ao topo da entrada. Ele passa por cada caractere na entrada. Se for um espaço, ele olha em volta, adicionando um ao contador para cada bomba que encontrar. após cada linha, ele exclui os colchetes. Quando chega à última linha, com o | nele, ele para e exclui o |. a grade é impressa implicitamente.


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

A entrada está na forma de uma matriz bidimensional de caracteres, seguida pelo número de linhas e colunas. O resultado será retornado no local.

(Principalmente) Ungolfed:

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

A abordagem é direta - faça um loop sobre cada posição, faça um loop sobre seus vizinhos e some todos os asteriscos. Existem dois truques no nível de bit:

  • Quando estamos decidindo se uma célula é um asterisco ou não, podemos apenas verificar se o bit de oito lugares está definido, porque o número na célula deve ser menor que 8 (o valor máximo da célula).

  • Podemos transformar um caractere de espaço em um caractere zero por OR-ing 16.

Edit: Golfed off dois bytes usando /no lugar de >=.

Edit: Outros cinco bytes, invertendo a direção dos loops.


0

C #, 341 bytes

Uma implementação ingênua que definitivamente pode ser reduzida.

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