19
\$\begingroup\$

Minesweeper is a logic game found on most OS's. The goal of the game is to determine where the mines are on a grid, given numbers indicating the number of mines around that spot.

Given a grid size, and a set of mines, generate the Minesweeper grid for that set of mines.

Input: Two integers indicating the grid size, and an undefined number of integers indicating the mine positions. Positions will be given as (column position, row position), and the indexes will start at row 1.

Output: The Minesweeper grid. If there are no mines around a block, print an x. For each new row, print a newline. Please output all mines as an asterisk *. Do not leave any whitespace between the values in the row when printing.

Test Cases:

Input "5 5 1 3 3 5 2 4":

xxxxx
11xxx
*21xx
2*21x
12*1x

Input "3 4 3 1 1 4 2 3 3 2":

x2*
13*
2*2
*21

Shortest code wins.

\$\endgroup\$
8
  • \$\begingroup\$ Are we safe to assume all inputs will have an even number of args? i.e. 5 5 1 will never be passed? \$\endgroup\$
    – Gaffi
    Commented Jun 26, 2012 at 17:17
  • \$\begingroup\$ @Gaffi: Yep. The input will always be valid input. \$\endgroup\$
    – beary605
    Commented Jun 26, 2012 at 22:45
  • \$\begingroup\$ The spec currently leaves the reader to deduce from the examples that the positions use 1-based indexes and that row 1 is at the top. (Or is the latter, at least, negotiable?) \$\endgroup\$ Commented Jun 27, 2012 at 9:17
  • \$\begingroup\$ @PeterTaylor: Yep. I guess I should make it more obvious. \$\endgroup\$
    – beary605
    Commented Jun 27, 2012 at 14:18
  • 1
    \$\begingroup\$ No problem. I'm still determined to find a way to shave a couple of characters off and regain the lead though. :-) \$\endgroup\$
    – Gareth
    Commented Jun 30, 2012 at 7:06

18 Answers 18

11
\$\begingroup\$

GolfScript 122 98 94 93 91 88 87 85 82 81 80 71

~]2/(\:m;~\:w*,{[.w%)\w/)]:^m\?)42{m{^*~-.*@@-.*+3<},,72or 48+}if}%w/n*

Online demos:

Test Case 1: link

Test Case 2: link

\$\endgroup\$
5
  • \$\begingroup\$ !!{a}{b}if uses one character more than necessary. '*' can be replaced with 42 because you're putting it in an array and then stringifying the array. Similarly you can use ASCII codes for the other output characters and save a character with or to handle the special case. \$\endgroup\$ Commented Jun 27, 2012 at 9:28
  • \$\begingroup\$ @PeterTaylor Wow, !!{a}{b}if was really stupid indeed. :) It's funny what high-level mistakes you can do while concentrated on details. I cannot figure out what you meant by using or. \$\endgroup\$ Commented Jun 27, 2012 at 11:16
  • \$\begingroup\$ Indeed! Coming back to a problem after time helps too. When I wrote a couple of code dissections for my GolfScript blog I spotted considerable improvements. With respect to my last suggestion, after ,, you have a number. You want to convert it to the corresponding string (or ASCII code) unless it's 0, in which case you want x. The ASCII codes for digits are sequential and run from 48. x is ASCII 120, which is 72+48. So you can do 72or 48+ and save a character over the string-based approach. \$\endgroup\$ Commented Jun 27, 2012 at 11:47
  • \$\begingroup\$ @PeterTaylor Great! Before you answered I managed to reduce that part to .48 120if+, but your or trick is two chars shorter. \$\endgroup\$ Commented Jun 27, 2012 at 11:57
  • \$\begingroup\$ @w0lf Gah! Just when I think I've got the lead back! \$\endgroup\$
    – Gareth
    Commented Jun 28, 2012 at 13:22
10
\$\begingroup\$

J, 124 116 112 101 87 86 85 84 83 82 79 76 75 72 68 characters

'0x'charsub|:1":3 3(+/@,+9*4&{@,);._3[1(}.x)}0$~2+>{.x=._2<\".1!:1[1

Found what I was looking for - a way to get rid of the spaces (1":) - and finally I'm competitive. Now I just need to figure out the empty set of mines problem.

Takes input from the keyboard.

Edit

New version makes use of a side effect of 1": - numbers larger than 9 are replaced by *.

\$\endgroup\$
6
  • \$\begingroup\$ I've noticed two things: 1. It prints spaces instead of 0, not x; 2. Fails if the set of mines is empty (ex: 10 10 - should print an empty 10x10 board, but returns |length error) \$\endgroup\$ Commented Jun 27, 2012 at 13:10
  • \$\begingroup\$ But othwerwise it works, so +1. \$\endgroup\$ Commented Jun 27, 2012 at 13:21
  • \$\begingroup\$ @w0lf Ah, I was still thinking of the first draft of the question - in that version x just represented a space. I didn't notice that it had changed. Hmm, never thought that the set of mines would be empty...I'll have to work on that. \$\endgroup\$
    – Gareth
    Commented Jun 27, 2012 at 13:27
  • \$\begingroup\$ now I see that the question has been edited. I had not seen the old revision. :) \$\endgroup\$ Commented Jun 27, 2012 at 14:13
  • \$\begingroup\$ @w0lf Thanks. I found a couple of good rearrangements that helped get rid of some unnecessary brackets. I can see one space I could remove, but I suspect I'm pretty much at my limit. And there's still the empty mines list problem... :-) \$\endgroup\$
    – Gareth
    Commented Jun 28, 2012 at 14:03
6
\$\begingroup\$

brainfuck, 1001 896 bytes

,[>,]-[<]>>++[<[<+<+>>-]<[>+<-]>[>]>[>>[>>>>]>]++[-<+]-[<]<++[>>[>]>[>>[>>>>]>]+<++[-<+]-[<]<-]>>>-]>[>]>[>>[>>>>]<<<->>>>]+[-<+]-[<]>>[[>]>--<<[<]>>[[>]+[->+]+>>[>>>>]>--<+[-<+]-[<]>>-]>[>]+[->+]+>>--<+[-<+]-[<]<[>>[>]+[->+]+>>>>--<+[-<+]-[<]<-]>>[>]+[->+]+>++[-<+]-[<]>>]>[+>>[>>>>]>]<<<<<[<<<<]>>-<+[-<+]>>>>[>>>>]>[-[--<<<<<[<<<<]>>>>--[>>>>]>>>[>>>>]>>>--<+[-<+]++>>>>>>[>[<--<<<[-[>>>>>>+<<<<<+<-]>+<]>[<+>-]>>>>+++[<<<+[-<+]->[-[+[->+]->>>+<<<<+[-<+]->>+<-]>+<]>[<+>-]+[->+]->>-[<<<+[-<+]+>>>>-->+[->+]->>[<<<+>>>-]]<<<[>>>+<<<-]>>>]<<<+[-<+]+<<<<-->+[->+]->>>>>[-[<<+>>>+<-]>+<]>[<+>-]<<<<+++[+[->+]->[-[<<+[-<+]->>>++[->+]->>+<-]>+<]>[<+>-]<<<+[-<+]->>-[+[->+]+>>>>--<+[-<+]->>[<<<+>>>-]]<<<[>>>+<<<-]>>>]+[->+]+<<<<--<+[-<+]->-[>>[-]<<++++++[>++++++<-]>.[-]+<<<]<[>>>[<++++++[>++++++++<-]>.[-]<]<<<[<++++++++[<+++++++++++>-]<.[-]>]<]>>>>+<<++>]>[<+>-]>>]->+[->+]++[-<+]++++++++++.[-]]>]

Try it online! or try the old version with integer input

One day of programming and three days of bugfixing ^^

This uses a few parts of my Game Of Life code. Instead of counting living cells, this counts bombs. Since input as codepoints is allowed by the general rules, this uses them instead of "readable" integers.

[
Data: colCount, rowCount, {BombCoordinates}, -1 (start of arrays/"soa"), 0, {RowData}
BombCoordinates: bombCol, bombRow
RowData: rowFlag, 0, {CellData}, 0
CellData: cellFlag, cellState, temp, bombCount

rowFlag: 0=EOF, 1=inactive (all cells inactive), 2=active
cellFlag: -1=marker for finding cell (cell to be counted or current cell), 0=EOF, 1=normal
cellState: 0=inactive, 1=normal, 2=bomb
temp: helper to exit if-statements
bombCount: count of neighbor cells that contain bombs
inactive cells or rows will not be printed. They are only used for an easier counting algorithm.
]

#### input values as codepoints ####
,[>,]

#### setup two dimensional array ####
-                   set soa
[<]>>               go to rowCount
++                  add two inactive rows
[                   for each row
  <[<+<+>>-]          copy colCount two times to the next left cells
  <[>+<-]             move one of the copies back to the original cell
  >[>]>[>>[>>>>]>]    go to new row position
  +                   set rowFlag (only 1 while initialization)
  +[-<+]-[<]<         go to copy of colCount
  ++                  add two inactive cells per row
  [                   for each col
    >>[>]>[>>[>>>>]>]   go to new cell position
    +<+                 set cellFlag and cellState = normal
    +[-<+]-[<]<         return to copy of colCount
    -                   decrement
  ]
  >>>-                decrement rowCount
]

#### setup active/inactive flags of cells ####
>[>]>[              for each row
  >>[>>>>]<<<-        set last cell inactive
  >>>>                go to next row
]

#### mark the bombs ####
+[-<+]-[<]>>        go to bombRow
[                   while there are bombRow values left
  [>]>--              set rowFlag of first row = neg 1 (as a marker)
  <<[<]>>             return to bombRow
  [                   for each bombRow
    [>]+[->+]           find first marker after soa
    +                   set rowFlag = 1
    >>[>>>>]>           go to next rowFlag
    --                  make a marker of it
    <+[-<+]-[<]>>       return to bombRow
    -                   decrement
  ]
  >[>]+[->+]          go to selected rowFlag
  +                   set rowFlag = 1
  >>--                set cellFlag of first cell = marker
  <+[-<+]-[<]<        go to bombCol
  [                   for each bombCol
    >>[>]+[->+]         find first marker after soa
    +                   set cellState = 1
    >>>>                go to next cellState
    --                  set it neg 1 (as a marker)
    <+[-<+]-[<]<        return to bombCol
    -                   decrement
  ]
  >>[>]+[->+]         find first marker after soa
  +                   set cellFlag = normal
  >+                  set cellState = bomb
  +[-<+]-[<]>>        go to next bombRow
]

#### setup active/inactive flags of rows ####
>[                  for each row
  +                   set rowFlag = 2 (active)
  >>[>>>>]>           go to next rowFlag
]
<<<<<[<<<<]>>-      set rowFlag of last row = 1 (inactive)

#### count bombs in neighborhood ####
<+[-<+]>>>>[>>>>]>  go to second row
[                   for each row
  -[                  if active
    --                  set it neg 1 (marker)
    <<<<<[<<<<]>>>>     go to cellFlag of first cell in previous row
    --                  set it neg 1 (marker)
    [>>>>]>>>[>>>>]>>>  go to cellFlag of first cell in next row
    --                  set it neg 1 (marker)
    <+[-<+]             return to rowFlag
    ++                  set rowFlag = 2 (active)

    >> >>>>[            for each cell (starting with second)
      >[                  if active
        <--                 set cellFlag = neg 1 (marker)

        # check if cell to the left is a bomb
        < <<                go to cellState of previous cell
        [                   if active
          -[                  if bomb
            >> >>>>+            increment bombCount
            <<<< <              go back to checked cell
            +                   set temp = 1
            <-                  set cellState = 0 to exit if
          ]
          >+<                 increment temp
        ]
        >[<+>-]             restore cellState

        # check if cells on top are bombs
        > >>>               go to temp of current cell
        +++[                do three times
          <<<+[-<+]-          go to next marker to the left
          >[                  if active
            -[                  if bomb
              +[->+]-             return to current cell
              >>>+                increment bombCount
              <<<<+[-<+]->        return to counted cell
              >+                  set temp = 1
              <-                  set cellState = 0 to exit if
            ]
            >+<                 increment temp
          ]
          >[<+>-]             restore cellState
          +[->+]-             go to current cell
          >>-                 decrement temp
          [                   if temp != 0
            <<<+[-<+]           go to marked cell
            +                   set cellFlag = normal
            >>>>--              set cellFlag of next cell = marker
            >+[->+]->>          return to currentCell temp
            [<<<+>>>-]          store value of temp in previous cell bombCount (to exit if)
          ]
          <<<[>>>+<<<-]>>>    restore temp value
        ]
        <<<+[-<+]           go to marked cell
        +                   set cellFlag = normal
        <<<<--              set previous cellFlag = marker
        >+[->+]-            return to current cell

        # check if cell to the right is a bomb
        >>> >>              go to cellState of next cell
        [                   if active
          -[                  if bomb
            <<+                 increment bombCount
            >>>                 go back to checked cell
            +                   set temp = 1
            <-                  set cellState = 0 to exit if
          ]
          >+<                 increment temp
        ]
        >[<+>-]             restore cellState

        # check if cells below are bombs
        <<< <               go to currentCell temp
        +++[                do three times
          +[->+]-         go to next marker to the right
          >[              if active
            -[              if bomb
              <<+[-<+]-       return to current cell
              >>>+            increment bombCount
              +[->+]->        return to counted cell
              >+              set temp = 1
              <-              set cellState = 0 to exit if
            ]
            >+<             increment temp
          ]
          >[<+>-]         restore cellState
          <<<+[-<+]-      go to current cell
          >>-             decrement temp
          [               if temp != 0
            +[->+]          go to marked cell
            +               set cellFlag = normal
            >>>>--          set cellFlag of next cell = marker
            <+[-<+]->>      return to currentCell temp
            [<<<+>>>-]      store value of temp in previous cell bombCount (to exit if)
          ]
          <<<[>>>+<<<-]>>>restore temp value
        ]
        +[->+]          go to marked cell
        +               set cellFlag = normal
        <<<<--          set previous cellFlag = marker
        <+[-<+]-        return to current cell

        # print
        >-[             if bomb
          >>[-]<<         delete bombCount
          ++++++[>++++++<-]>.print "*"
          [-]+            set temp = 1
          <<<             use previous cell bombCount as exitIf
        ]
        <[              else
          >>>[            if bombCount != 0
            <++++++[>++++++++<-]add 48 to get ascii number
            >.              print
            [-]             set number = 0 (for use as exitIf from next cell)
            <               go to temp for exit if
          ]
          <<<[            else
            <++++++++[<+++++++++++>-]<.print "X"
            [-]             delete value (for use as exitIf from next cell)
            >               go to exitIf
          ]
          <               go to exitElse
        ]
        > >>>+          increment temp
        <<++>           set cellFlag = normal
      ]
      >[<+>-]         restore cellState
      >>              go to cellFlag of next cell
    ]
    -               set marker
    >+[->+]         go to next marker
    +               set cellFlag = normal
    +[-<+]          return to marker
    +++++ +++++.[-] print newline
  ]
  >               go to next row
]
\$\endgroup\$
5
+50
\$\begingroup\$

APL (Dyalog Unicode), 59 57 54 bytes

With a more flexible input format this could be 39 bytes

{⍉{5⌷,⍵:'*'⋄×r←+/,⍵:⍕r⋄'x'}⌺3 3⊢1@(1↓⍵)⊢0⍴⍨⊃⍵}⊢⊂⍨2|⍳∘≢

Try it online!

The whole structure is a train, first ⊢⊂⍨2|⍳∘≢ splits the input into pairs, then the large dfn is called on the list of pairs:

0⍴⍨⊃⍵ Create a matrix of 0's where the dimensions are given by the first pair.

1↓⍵ all but the first pair
1@(...) at those indices place 1's in the matrix.

{ ... }⌺3 3 apply the left function on each 3×3 neighborhood (padded with zeros):

5⌷,⍵ If the value at index 5 of the flattened neighborhood (the center) is 1, return '*'
×r←+/,⍵ If the sum of the neighborhood is positive, return it as a string ⍕r
Otherwise return 'x'

transpose the matrix because the order of axis is different in APL and the challenge.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ The rigidness of input specs on these old questions is frustrating. The new norms are so much better. \$\endgroup\$
    – Jonah
    Commented Aug 7, 2021 at 3:21
3
\$\begingroup\$

VBA - 298 chars

Sub m(x,y,ParamArray a())
On Error Resume Next:ReDim b(x,y):For i=0 To (UBound(a)-1) Step 2:c=a(i):d=a(i+1):b(c,d)="*":For e=c-1 To c+1:For f=d-1 To d+1:v=b(e,f):If v<>"*" Then b(e,f)=v+1
Next:Next:Next:For f=1 To y:For e=1 To x:v=b(e,f):s=s & IIf(v<>"",v,"x")
Next:s=s & vbCr:Next:MsgBox s
End Sub

Skipping over errors with On Error Resume Next saved me some characters, but this still isn't nearly as good as some of the other answers. :-/

\$\endgroup\$
3
\$\begingroup\$

C++, 230 chars

#import<iostream>
int*p,n,m,x,y,i,j,k,a[999][999];main(){for(std::cin>>m>>n;std::cin>>y>>x;)for(i=2;~i--;)for(j=2;~j--;*p+=i|j&&~*p?:~*p)p=a[x+i]+y+j;for(;k<n*m;std::cout<<char(x?~x?x+48:42:120)<<(j<m)+"\n")x=a[k/m+1][j=k++%m+1];}

-11 bytes thanks to ceilingcat

-15 bytes thanks again to ceilingcat. Truly bigbrain

-14 bytes thanks to ceilingcat and I

-8 bytes thanks to ceilingcat and I

Try it online

\$\endgroup\$
0
3
\$\begingroup\$

Vyxal, 42 bytes

⌈⌊2ẇḣ$2+Þm$R(n1ÞȦ)2(3vl∩)ƛƛf4ǔṫß×∑\x$∨}vṅ⁋

Try it Online! (would be 28ish with looser I/O)

⌈⌊                                         # Parse integers from input
  2ẇ                                       # Group into pairs
    ḣ                                      # Remove the first pair (dimensions)
     $2+                                   # Add 2 to each
        Þm                                 # Create a matrix of 0s with those dimensions
          $R(    )                         # Over each remaining coordinate pair (with x and y swapped)
               ÞȦ                          # Place in the matrix
              1                            # A 1
             n                             # At those coordinates
                  2(    )                  # Twice
                    3vl                    # Get all sliding windows of length 3 of each
                       ∩                   # Transpose
                         ƛƛ           }
                           f               # Flatten into a 9-element array
                            4ǔ             # Rotate so the centre (current cell) is at the end
                              ṫ            # Extract the last element (current cell)
                               ß×          # If that is truthy, push a mine
                                 ∑         # Sum to get number of nearby mines
                                  \x$∨     # If 0, replace with x
                                       vṅ⁋ # Concatenate each and join by newlines
\$\endgroup\$
3
\$\begingroup\$

05AB1E, 50 bytes

#2ôć¬UPL<s<íXδβ©såXô2Fø0δ.ø}2Fø€ü3}OOJJ'*®ǝ0'x:Xô»

Try it online or verify both test cases.

Explanation:

05AB1E lacks multi-dimensional index builtins and uses 0-based indexing, so we mostly work with the flattened list and lower all indices by 1 (before converting it back to a matrix to calculate the amount of surrounding mines per cell).

#              # Split the (implicit) input-string on spaces
 2ô            # Split it into parts of size 2
   ć           # Extract head; pop and push remainder-list and first pair
    ¬          # Get the first item of this first pair (without popping)
     U         # Pop and store it in variable `X`
    P          # Take the product of this first pair
     L<        # Pop and push a list in the range [0,value)
    s          # Swap so the list of pairs is at the top again
     <         # Decrease each inner value by 1 to make things 0-based
      í        # Reverse each inner pair, to reverse column,row to row,column
        δ      # Map over each reversed and lowered pair:
       X β     #  Convert it from base-`X` to an integer,
               # (which are all flattened 0-based indices of the mines)
          ©    # Store this list in variable `®` (without popping)
           s   # Swap so the [0,value)-ranged list is at the top
            å  # Check for each value whether its in the indices-list,
               # resulting in a list of 0s and 1s, with 1s at the mine-positions
Xô             # Split it into `X`-sized parts to a matrix
  2Fø0δ.ø}     # Add a border of 0s around the matrix:
  2F     }     #  Loop 2 times:
    ø          #   Zip/transpose; swapping rows/columns
      δ        #   Map over each inner list:
     0 .ø      #    Surround it with a leading/trailing 0
  2Fø€ü3}      # Convert it to a matrix of overlapping 3x3 blocks:
  2F    }      #  Loop 2 times again:
    ø          #   Zip/transpose; swapping rows/columns
     €         #   Map over each inner list:
      ü3       #    Convert it to a list of overlapping triplets
  OO           # Sum each inner 3x3 block
    JJ         # Join all these digits together to a single string
      '*®ǝ    '# Replace the digit at the `®`-indices with "*"s
      0'x:    '# Replace all 0s with "x"s
      Xô       # Split it into `X`-sized parts again to a list of rows
        »      # Join it by newlines
               # (after which the result is output implicitly)
\$\endgroup\$
4
  • \$\begingroup\$ time to golf my answer again \$\endgroup\$
    – pacman256
    Commented Jan 31 at 14:40
  • 2
    \$\begingroup\$ The mines in the first test case don't get placed correctly (should be in a diagonal line, not a vertical line). \$\endgroup\$
    – DLosc
    Commented Jan 31 at 17:23
  • \$\begingroup\$ @DLosc Woops.. Thanks for noticing! Should be fixed now. \$\endgroup\$ Commented Feb 1 at 8:03
  • 1
    \$\begingroup\$ It is, but I think you replaced the wrong link. ;) \$\endgroup\$
    – DLosc
    Commented Feb 1 at 20:53
2
\$\begingroup\$

Mathematica - 247 chars

s[q_] :=
  Module[{d, r},
    d = ToExpression@Partition[Cases[Characters@q, Except@" "], 2];
    r = Rest@d;
    StringJoin @@@ 
    ReplacePart[
    Table[ToString@
       Count[ChessboardDistance[{i, j}, #] & /@ Reverse /@ r, 1], {i,d[[1, 2]]}, 
       {j, d[[1, 1]]}] /. {"0" -> "x"}, # -> "*" & /@ Reverse /@ r] // TableForm]

Examples:

s@"5 5 1 3 3 5 2 4"
s@"3 4 3 1 1 4 2 3 3 2"

Output:

output

ChessboardDistance computes how far each cell is from a mine, where 1 corresponds to "next to a mine". The Count of 1's yields the cell's number. Then mines (*) are inserted into array.

\$\endgroup\$
2
  • \$\begingroup\$ David, nice to see another Mathematica user here. I'll see if I can beat this! :-) \$\endgroup\$
    – Mr.Wizard
    Commented Jun 28, 2012 at 12:13
  • \$\begingroup\$ @Mr.Wizard I'll be interested in seeing your solution. Feel free to improve on mine if you like. \$\endgroup\$
    – DavidC
    Commented Jun 28, 2012 at 13:46
2
\$\begingroup\$

Mathematica, 140 139 137

Grid[(ListConvolve[BoxMatrix@1,#,2,0]/. 0->x)(1-#)/. 0->"*"]&@Transpose@SparseArray[{##2}->1,#]&@@#~Partition~2&@@#~ImportString~"Table"&

Writing that in a more readable form:

"5 5 1 3 3 5 2 4"

ImportString[%, "Table"][[1]] ~Partition~ 2

Transpose @ SparseArray[{##2} -> 1, #]& @@ %

ListConvolve[BoxMatrix@1, %, 2, 0]

(% /. 0 -> x) (1 - %%) /. 0 -> "*" // Grid
\$\endgroup\$
5
  • \$\begingroup\$ Elegant! I confess I cannot understand how ListCorrelate[BoxMatrix@1, %, 2, 0] does its magic. \$\endgroup\$
    – DavidC
    Commented Jun 28, 2012 at 14:44
  • 1
    \$\begingroup\$ @David I'm glad you (implicitly) asked as that's my favorite part. ListCorrelate effectively overlays the kernel (BoxMatrix@1) at each position in the grid, multiplies, and gives the sum. (ping me in mma chat if you would like an illustration) -- Your comment reminds me that ListConvolve should work here too as it is a kind of mirror image of ListCorrelate and my kernel is symmetric. That will save me a character. :-) \$\endgroup\$
    – Mr.Wizard
    Commented Jun 28, 2012 at 22:31
  • \$\begingroup\$ Your code incorrectly generates a mine at (5,5). "5 5" gives the dimensions of the grid. \$\endgroup\$
    – DavidC
    Commented Feb 7, 2013 at 1:20
  • \$\begingroup\$ @David Thanks. You're right, but it's only in the white-space version; I somehow lost the 2 in ##2. I'll fix it now. ps: How did you come to notice this after so long? \$\endgroup\$
    – Mr.Wizard
    Commented Feb 7, 2013 at 3:12
  • \$\begingroup\$ Another minesweeper question, codegolf.stackexchange.com/questions/10635/…, recently appeared and I decided to give your solution another look-through. \$\endgroup\$
    – DavidC
    Commented Feb 7, 2013 at 12:34
2
\$\begingroup\$

Vyxal 3 j, 37 bytes

2ẆVḤ\ðYY$v•ÞẠ:Þȯᵛƛ•C]ZᵗZᵛᵛ₳•c[•]0'xr“

Try it Online! -12 from Using reduce lambdas on zipped list instead of the weird index method. -1 because i didnt need a map lambda at the end

\$\endgroup\$
1
\$\begingroup\$

Python, 192 182 180 chars

I could save some if the input was comma-separated. Then the first line would be d=input() and the length 171 chars.
Having the mine coordinates 0-based rather than 1-based would also help. It cost me 8 chars to overcome.

d=map(int,raw_input().split())
m=zip(d[2::2],d[3::2])
for y in range(d[1]):print"".join((str(sum(abs(a-x-1)|abs(b-y-1)<2for a,b in m)or'x')+'*')[(x+1,y+1)in m]for x in range(d[0]))

Ungolfed version:

d=map(int,raw_input().split())          # Read whitespace terminated numbers into a list of numbers
xsize,ysize = d[:2]                     # The first two numbers are the board size
mines=zip(d[2::2],d[3::2])              # Convert items 3,4,5,6... to pairs (3,4),(5,6) representine mine coordinates

def dist(point,mine):                   # Distance between point (0-based coordinates) and mine (1-based coordinates)
    dx = abs(mine[0]-(point[0]+1))
    dy = abs(mine[1]-(point[1]+1))
    return dx | dy                      # Should be max(dx,dy), but this is close enough. Wrong for d>=2, but returns >=2 in this case.

for y in range(ysize):                  # Print lines one by one
    line_chars = [
        (str(
            sum(dist((x,y),(a,b))<2 for a,b in mines)   # Number of neighboring mines
            or 'x'                                  # 'x' instead of 0
        )
        +'*')                                       # For a single neighbor, we get "1*"
        [(x+1,y+1)in mines]                         # If a mine, get the '*', else the neighbor number
        for x in range(xsize)
    ]
    print "".join(line_chars)
\$\endgroup\$
1
\$\begingroup\$

Scala, 280 chars

val n=readLine split" "map{_.toInt}
val b=Array.fill(n(1),n(0))(0)
n drop 2 sliding(2,2)foreach{case Array(x,y)=>b(y-1)(x-1)=9
for{i<-(x-2 max 0)to(x min n(0)-1);j<-(y-2 max 0)to(y min n(1)-1)}b(j)(i)+=1}
b.map{r=>println(r.map{case 0=>"x"case x if x>8=>"*"case x=>""+x}mkString)}
\$\endgroup\$
1
\$\begingroup\$

Haskell, 155 bytes

main=interact$f.map read.words
f(x:y:a)=unlines[["x12345678*"!!min((i,j)#a)9|i<-[1..x]]|j<-[1..y]]
p@(a,b)#(x:y:z)=div 9(9^max(abs$a-x)(abs$b-y))+p#z
_#_=0

Try it online!

\$\endgroup\$
0
\$\begingroup\$

C++ - 454 chars

This is worse than my VBA answer, which probably means I don't know what I'm doing in C++. However, I am trying to build on what I know of C++, so here it is. If anyone has any suggestions for improvement, I'd be grateful to hear them!

#define Z for(int i=
#define Y for(int j=
#define X d[i][j]
#define W Z 0;i<x;i++){
#define V Y 0;j<y;j++){
#define U cout<<
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
int main(){using namespace std;int x,y,a,b;cin>>y>>x;string c[x][y];int d[x][y];W V X=0;}}while(cin>>b>>a){c[--a][--b]="*";Z a-1;i<=a+1;i++){Y b-1;j<=b+1;j++){if(x>i&&i>=0&&y>j&&j>=0){X=X+1;}}}}W V if(c[i][j]!="*"){if(X>0){U X;}else{U"x";}}else{U"*";}}U endl;}return 0;}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ you don't need to return 0. And you can #include<cstdio>,#include<cstdlib>. You can even delete these two includes!. What's more, using name..... is too long, you can use std::cin, std::cout, std::string instead. \$\endgroup\$
    – Ray
    Commented Feb 15, 2013 at 18:23
  • \$\begingroup\$ @Ray Aye, you're right about the namespace... It's been a while since I put this together, but I'm thinking I had more std:: calls that would have made it more worth it (I think one more string would have done it). Thanks for the info about the #include lines as well. I'm no C++ expert. ;-) \$\endgroup\$
    – Gaffi
    Commented Feb 15, 2013 at 19:10
0
\$\begingroup\$

C# (691 Chars)

using System;namespace M{class P{static char C(char[][] g,int r,int c){int n=0;for(int i=r-1;i<=r+1;i++){if(i<0||i>=g.Length)continue;for(int j=c-1;j<=c+1;j++){if((j<0||j>=g[0].Length)||(i==r&&j==c))continue;if(g[i][j]=='*')n++;}}return n==0?'x':(char)(n+48);}static char[][] G(int[] p){char[][] r=new char[p[1]][];for(int i=0;i<r.Length;i++)r[i]=new char[p[0]];for(int i=2;i<p.Length;){r[p[i+1]-1][p[i]-1]='*';i+=2;}for(int i=0;i<r.Length;i++)for(int j=0; j<r[0].Length;j++)if(r[i][j]!='*')r[i][j]=C(r,i,j);for(int i=0;i<r.Length;i++){for(int j=0;j<r[0].Length;j++)Console.Write(r[i][j]);Console.WriteLine();}return r;}static void Main(string[] args){G(new int[]{3,4,3,1,1,4,2,3,3,2});}}}

Non-golfed Version:

using System;
namespace M
{
    class P
    {
        static char C(char[][] g, int r, int c)
        {
            int n = 0;
            for (int i = r - 1; i <= r + 1; i++)
            {
                if (i < 0 || i >= g.Length) continue;
                for (int j = c - 1; j <= c + 1; j++)
                {
                    if ((j < 0 || j >= g[0].Length) || (i == r && j == c)) continue;
                    if (g[i][j] == '*') n++;
                }
            }
            return n == 0 ? 'x' : (char)(n + 48);
        }

        static char[][] G(int[] p)
        {
            char[][] r = new char[p[1]][];
            for (int i = 0; i < r.Length; i++)
                r[i] = new char[p[0]];
            for (int i = 2; i < p.Length; )
            {
                r[p[i + 1] - 1][p[i] - 1] = '*';
                i += 2;
            }
            for (int i = 0; i < r.Length; i++)
                for (int j = 0; j < r[0].Length; j++)
                    if (r[i][j] != '*') r[i][j] = C(r, i, j);
            for (int i = 0; i < r.Length; i++)
            {
                for (int j = 0; j < r[0].Length; j++)
                    Console.Write(r[i][j]);
                Console.WriteLine();
            } return r;
        } 
        static void Main(string[] args) 
        { 
            G(new int[] { 3, 4, 3, 1, 1, 4, 2, 3, 3, 2 }); 
        }
    }
}
\$\endgroup\$
0
\$\begingroup\$

K, 175

f:{g::(y;x)#(x*y)#"x";{.[`g;x;:;"*"]}@'-1+|:'(_(#z)%2;2)#z;{if[~"0"~z;$["x"=g .(x;y);.[`g;(x;y);:;z];]]}.'i,'$s:+/'{"*"=g . x}''{,/((x-1)+!3),\:/:(y-1)+!3}.'i:,/(!x),\:/:!y;g}

.

k)f[5;5;1 3 3 5 2 4]
"xxxxx"
"11xxx"
"*21xx"
"2*21x"
"12*1x"
k)f[3;4;3 1 1 4 2 3 3 2]
"x2*"
"13*"
"2*2"
"*21"
\$\endgroup\$
-1
\$\begingroup\$

ECMAScript 2019 (Modern Javascript) - 116 bytes

m.map((r,i)=>r.map((c,j)=>c=='X'?c:[,...m].splice(i,3).map(r=>[,...r].splice(j,3)).flat().filter(v=>v=='X').length))

ungolfed version

m.map(
  (r,i) => r.map(
    (c,j) => c=='X' ? c :
      [,...m].splice(i,3).map(r=>[,...r].splice(j,3)).flat().filter(v=>v=='X').length
  )
)

this solution doesn't strictly adhere to the input/output format but demonstrates a succinct algorithm.

example: https://gist.github.com/missinglink/ee02084cfb523665e8c9d34c24f01537

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.