Inverser un plateau de dragueur de mines

32

Démineur est un jeu informatique populaire auquel vous avez probablement perdu du temps à jouer où vous essayez de révéler les cellules qui sont des mines dans une grille rectangulaire en fonction des indices du nombre de mines voisines que possède chaque cellule non minière. Et si vous ne l'avez pas joué, faites-le ici .

Un fait mathématique astucieux à propos d'une grille de démineur (aka conseil) est que:

Une planche et son complément ont le même nombre total de mines . ( Preuve )

C'est-à-dire que si vous avez une grille de démineur complètement révélée, la somme de tous les nombres sur cette grille, c'est-à-dire le total de la mine , sera égale au total de la mine du complément de la grille, qui est la grille où chaque mine a été remplacée avec une non-mine et chaque non-mine remplacée par une mine.

Par exemple, pour la grille Démineur

**1..
34321
*2**1

le total de la mine est 1 + 3 + 4 + 3 + 2 + 1 + 2 + 1 = 17.

Le complément de la grille est

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

qui a le mien total 2 + 4 + 3 + 4 + 4 = 17 à nouveau.

Ecrire un programme qui prend dans une grille Démineur arbitraire sous forme de texte où *représente une mine et 1par 8représenter le nombre de mines adjacentes à une cellule non-moi. Vous pouvez utiliser .ou 0ou (espace) pour représenter des cellules sans voisin, selon votre choix. Vous pouvez supposer que la grille d'entrée sera correctement marquée, c'est-à-dire que chaque cellule non minière indiquera avec précision le nombre total de mines immédiatement adjacentes orthogonalement ou en diagonale.

Votre programme a besoin d'imprimer le complément de la grille dans le même format ( en utilisant le même ., 0ou comme prévu dans l'entrée).

Le code le plus court en octets gagne.

  • Au lieu d'un programme, vous pouvez écrire une fonction qui prend la grille d'entrée sous forme de chaîne et imprime ou renvoie la grille complémentaire.
  • Un retour à la ligne de fin dans l'entrée ou la sortie est correct, mais il ne doit pas y avoir d'autres caractères que ceux qui forment la grille.
  • Vous pouvez supposer qu'une grille 1 × 1 sera la plus petite entrée.

Cas de test

Toutes les entrées et sorties pourraient être échangées car le complément du complément est la grille d'origine. Les grilles peuvent également être tournées pour d'autres cas de test.

Contribution:

111
1*1
111

Sortie:

***
*8*
***

Contribution:

.

Sortie:

*

Contribution:

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

Sortie:

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

Entrée: ( exemple Cut The Knot )

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

Sortie:

24***4**
***7**64
*8**7***
******8*
4**7****
*33**5*3
Les passe-temps de Calvin
la source
TI-BASIC ne peut pas accepter une ligne d'entrée vide. L'utilisation d'un délimiteur de fin (par exemple ?) sur la ligne après la dernière ligne de la carte est-elle acceptable, ou pourrais-je prendre le nombre de lignes d'entrée via la ligne de commande?
lirtosiast
@ThomasKwa Un délimiteur de fin sonne bien pour TI-BASIC et d'autres langues qui ont d'étranges limitations de nouvelle ligne.
Calvin's Hobbies

Réponses:

12

Pyth, 39 38 octets

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

Essayez-le en ligne: démonstration

L'algorithme principal est vraiment simple. Je parcours simplement chaque cellule, je prends la boîte 3x3 environnante (ou plus petite lorsque la cellule est à la frontière) et j'imprime une étoile ou le nombre de non-étoiles dans cette boîte.

Explication:

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
la source
Vraiment bien, +1
MKII
22

CJam, 58 57 octets

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

L'entrée ne doit pas se terminer par un saut de ligne. La sortie contient 0pour les cellules sans mines à proximité.

Essayez-le en ligne dans l' interprète CJam .

Idée

Nous commençons par remplir la matrice d'entrée avec une ligne et une colonne d'astérisques.

Pour l'entrée

*4*
**2

cela se traduit par

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

Maintenant, nous générons toutes les modifications possibles qui résultent de la rotation des lignes et des colonnes 0, -1 ou 1 unités vers le haut / gauche:

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

Nous éliminons les "emplacements de rembourrage" de chaque rotation, c.-à-d.

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

et former une matrice unique en concaténant les caractères correspondants de chaque rotation:

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

Le premier caractère de chaque position est son caractère d'origine.

  • S'il ne s'agit pas d'un astérisque, il doit être remplacé par un astérisque.

  • S'il s'agit d'un astérisque, le nombre de non-astérisques dans cette chaîne est le nombre de mines voisines.

Comment ça marche

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
la source
7
J'ai peur - c'est incroyable.
Deusovi
Vous monsieur, venez de casser le système. +1! Puis-je vous demander où vous avez trouvé cette théorie?
GamrCorps
9
@IonLee Celui-ci est tout moi. C'est une idée assez simple, vraiment: au lieu de vérifier les cellules autour d'une cellule donnée, nous déplaçons la grille entière et observons ce qui tombe dans la cellule.
Dennis
Bravo! Je n'aurais jamais pensé à ça.
GamrCorps
7

Rubis, 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]<=>?*]}}

Non testé dans le programme de test:

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
la source
2

Octave, 76

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

Explication

  • Convertissez la chaîne d'entrée en matrice de chaînes à l'aide de strsplitet cell2mat.

  • Obtenez la matrice logique contenant 1où il n'y *en a pas dans la matrice d'origine.

  • Prenez sa convolution avec une matrice 3x3 de 1.

  • Masquez-le avec la matrice logique inverse et mettez *en place le masque.

  • Remarque: Les cellules sans voisin de mine sont représentées comme 0.

Exécution

>> 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
gobelet
la source