# Fill in the Minesweeper clues

Minesweeper is a popular puzzle game where you must discover which tiles are "mines" without clicking on those tiles. Each tile is either a mine (represented by *) or a clue, i.e. a number from 0 to 8 representing how many of the 8 neighboring tiles are mines. Your task today is to take a board containing the mines and fill in all of the clues. For example, look at the following 5x4 board, with 5 mines:

 *
*  *
*
*


After filling in the clues, the board will look like this:

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


# Details

You must write either a full-program or a function that takes in a grid of characters containing only spaces and asterisks and outputs another grid where each space is replaced with the number of adjacent mines (asterisks). Any of these are acceptable formats for your grids:

• A string with newlines in it

• A 2D list of characters/single character strings

• A list of strings

You can assume the grid will be at least 1x1, although it is possible for it to be all mines or all spaces.

The input grid will always be padded with the appropriate number of spaces. As usual, this is , so standard loopholes apply and the shortest answer in bytes wins!

# Sample IO

So that you can see the whitespace, I will show all sample IO with brackets around it.

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

Output:
[1101*1]
[*10111]


[12**21]
[1*33*1]

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

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

Input:
[   ]
[   ]
[   ]
[   ]

Output:





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

Ouput:
[*310]
[**10]

[001*]

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

Output:
[**1011]
[*4211*]
[12*111]

[*43210]
[****10]

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

Output:
[00001*1111]
[00002221*1]
[22102*4321]
[**102***31]
[221013***1]

[0112111**1]
[12*2*12442]
[*212112**2]
[1100002**2]

• FYI, I made all of the sample IO by hand, so it's possible there are some minor errors in there. Let me know if something looks off and I'll try to fix it ASAP. Oct 23, 2016 at 4:45
• Related.
– xnor
Oct 23, 2016 at 4:50
• Can the grid be non-square ? Oct 23, 2016 at 8:56
• Can the mines represented by another character? Oct 23, 2016 at 11:58
• @ChristianIrwan No, the mines will always be an asterisk. Oct 23, 2016 at 12:59

# MATL, 18 17 bytes

Thanks to @mbomb007 for a correction in the input of test case 6

32>t3Y6Z+-6b(48+c


Input is a 2D char array, in the format

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


Try it online!

Test cases: 1, 2, 3, 4, 5, 6.

### Explanation

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

• Wow. That is impressive. Oct 24, 2016 at 15:01
• Getting test case 6 would piss me off playing the actual game. Oct 24, 2016 at 15:51
• Why? Test case 6 seems the most realistic.
– WBT
Oct 24, 2016 at 20:57
• @carusocomputing Getting test case 2 would piss me off a lot more. :P Oct 25, 2016 at 21:09

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


Edit: Saved 18 bytes thanks to an idea by @ETHproductions.

• I think you can save a bunch by defining a function to check if an index is non-space: 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))) Oct 23, 2016 at 18:38
• @ETHproductions I took your idea to the extreme... I don't usually get to write function parameters!
– Neil
Oct 23, 2016 at 18:56

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


thanks to @gtwebb and @sebastian-c for improvements.

Notable points:

Matrices are vectors in R. You don't need 2-D indexing to get elements out.

seq(M) will return a sequence of the same "length" (rows x columns) as M.

You can't mix positive and negative extraction indices in R. M[-3] is legitimate R code, but not what is desired.

Input is in the form of an R matrix. Some examples:

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

• You can cut a few characters off by using T instead of TRUE. I managed to slide some braces off one of the if functions too: 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} Oct 24, 2016 at 16:27
• You define b=ncol(M) and then don't use it so you could get rid of that. Oct 24, 2016 at 22:28
• I can shave off four characters (and vectorise): 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)))} — however, this cheats slightly because it requires a redefined <- lambda, see klmr/functional/lambda Oct 25, 2016 at 15:02
• @Konrad interesting idea, but I'll keep it to base R thanks!
– JDL
Oct 25, 2016 at 15:06

## Java, 190 bytes

Edit:

• -6 bytes off. Thanks to @Frozn
• -1 byte off. Thanks to myself :)
• -1 byte off. Also spotted some mistakes. Thanks to @Kevin Cruijssen

Snipet

c->{for(int x,y,j,i=-1;++i<c.length;)for(j=-1;++j<c.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.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.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.

• You can compare the char values against the ASCII values which should be shorter in most cases. You can also combine the declarations of x,y,i,j Oct 23, 2016 at 14:00
• I already did c[i][j]==32 and so on and just changed them in the Ungolfed part Oct 23, 2016 at 14:09
• And I'm shorter than Phyton. At least! Oct 23, 2016 at 19:16
• Are you sure your ungolfed code is correct? For the first test case it outputs: 0000*1\n*10011\n110000\n000000\n00**10\n0*22*1. Could you perhaps add an ideone.com test link? EDIT: Also, unless I'm doing something wrong myself, your golfed code output: ssss0s\n0sssss\nssssss\nssssss\nss00ss\ns0ss0s for the first test case (it has replaced all * with zeros..) :S Oct 24, 2016 at 8:03
• Edited. I'll add a test link as soon as my pior internet allows that to me. Oct 24, 2016 at 8:13

# JavaScript (ES6), 107

Input/output as an array of 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 when the function s is called with an element of the list l out of the bounds, the parameter a is undefined and c+a will result in " undefined" thanks to the quirky conversion rules of javascript

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


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


Defines a function f that accepts an input string like

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


and prints a string to STDOUT:

23*
**2
*31

• Make enumerate start from 2 (enumerate(s,2)), and replace all occurrences of i + 2 with i and i - 1 with i - 3. That'll shave off a couple of bytes. Oct 25, 2016 at 0:54

# JavaScript (ES6) 186182177161 152 bytes

f=a=>{for(s='',y=a.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}


# Update

The above code for " *" returns "2*". This is fixed in the following script.

# 168 167 bytes

f=a=>{for(s='',y=a.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}


# Try it here.

• I think t+=(a[x+i%3-1]||[])[y+i/3-1|0]==k should work in a similar way and save you the try / catch part. Oct 23, 2016 at 11:19
• @Arnauld. Actually, reading a property of literal number will not throw an error, so it can be also improved as (a[x+i%3-1]||1)[y+i/3-1|0]. Oct 24, 2016 at 16:33

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]  Defines a function f on lists of strings # Python 2, 192 bytes -3 bytes thanks to Copper, -10 bytes if modifying the input grid is allowed, another -11 bytes by getting rid of continue and another -12 bytes for eliminating the counter variable def f(L): n,S,s=len(L),[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)  Uses a list of list of characters L and creates a padded version K, so no problem at boundaries. Indentation is 1. Space 2. Tab 3. Tab+Space 4. Tab+Tab Usage: 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  • A few minor golfs: you can put your first three variables assignments on the same line separated with semicolons and lose the indentation. Also, use if'*'==L[y][x]: to save a byte. Oct 23, 2016 at 11:07 • If you assign r=range; on the same line as n,S,s, you can save five characters by replacing the calls to range(...) with r(...). Oct 23, 2016 at 22:36 • @alexwlchan doing this saves 2*ange so 8 bytes, but i have to add ,r and ,range which is also 8 bytes so nothing earned. Oct 24, 2016 at 8:34 • @KarlNapf Gah, you're right -- I'd forgotten about the range. Oct 24, 2016 at 10:12 # Ruby, 112 Takes and returns a string. String must be newline separated and newline terminated. ->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}


in test program

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[ " * * * * * "]  # TSQL 292 291 bytes Golfed: 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 @  Fiddle • Does the ; at the front of your code count? It seems that you have counted it. Oct 24, 2016 at 13:28 • @EriktheGolfer Yes, where there is script prior to WITH. Compiler will give an error if it is removed. It is possible to test ideas in the fiddle Oct 24, 2016 at 13:33 • I mean, should it be in the byte count of the general source? Because it seems like it should be part of the "Initial STDIN" statement instead. Oct 24, 2016 at 13:34 • @EriktheGolfer I don't really know, I suppose it can be part of the declaration. Can also exclude master.. if there is a USE master in the beginning of the script. But it gives an annoying message in the fiddle. Oct 24, 2016 at 13:38 • I tried putting the semicolon on the previous line, and it worked. I assume the last line is what counts. Oct 24, 2016 at 13:42 ## Racket 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 "")))))  Testing (lists as a single string with column number specified; will also work with spaces): (f "----*-*-------------------**---*--*-" 6)  Output: 1101*1 *10111 110000 012210 12**21 1*33*1  # PHP, 145133132 127 bytes for($s=$argv;$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];  takes input as single string, newline separated. Run with -r. breakdown for($s=$argv;$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] instead of " "==$n=$s[\$p] saves one Byte Oct 24, 2016 at 16:24
• @JörgHülsermann That would destroy the linebreaks. Oct 24, 2016 at 16:27
• @JörgHülsermann ... but the trick works for the asterisk comparison (in the new version) Oct 24, 2016 at 16:35

# Turtlèd, 99 bytes

(whoops I keep forgetting the link :| )

Takes inputs with brackets around each line

Turtlèd cannot take multi-line input, so after the last line, write | to signal end of input

Note the mismatched brackets are because open brackets parse the next char as part of the bracket command

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


## How it works (general description):

Until | is entered, it writes out the input on each line, with brackets to help it recognise the end of each line. After that has happened, it goes back up to the top of input. It goes through each character in input. If it is a space, it looks around the space, adding one to the counter for each bomb it finds. after each line, it deletes the brackets. When it gets to the last line, with the | in it, it stops, and deletes the |. the grid is implicitly printed.

# APL (Dyalog Unicode), 24 bytes

{4⌷x←'*'=,⍵:'*'⋄+/x}⌺3 3


Try it online!

A direct stencil operation.

Input as a character matrix, output as a hybrid matrix.

Testcase converter

## C, 152150147 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));}}


Input is in the form of a two-dimensional array of characters, followed by the numbers of rows and columns. The result will be returned in-place.

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


The approach is straight-forward — loop over each position, loop over its neighbors, and add up all the asterisks. There are two bit-level tricks:

• When we're deciding if a cell is an asterisk or not, we can just check if the eights-place bit is set, because the number in the cell must be less than 8 (the maximum cell value).

• We can turn a space character into a zero character by OR-ing 16.

Edit: Golfed off two bytes by using / in place of >=.

Edit: Another five bytes by reversing the direction of the loops.

## C#, 341 Bytes

A naïve implementation that can definitely be shortened.

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


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