Count numbers and bombs
Weekly challenge 126 — 16 August 2021
Week 126: 16 Aug 2021
You are given a rectangle with points marked with either x or *. Please consider the x as a land mine. Write a script to print a rectangle with numbers and x as in the Minesweeper game. A number in a square of the minesweeper game indicates the number of mines within the neighbouring squares (usually 8), also implies that there are no bombs on that square.
Example 1: Input: x * * * x * x x x x * * * * * * * * * x * * * * x * x * x * * * * x x * * * * * x * * * x * * * * x Output: x 1 0 1 x 2 x x x x 1 1 0 2 2 4 3 5 5 x 0 0 1 3 x 3 x 2 x 2 1 1 1 x x 4 1 2 2 2 x 1 1 3 x 2 0 0 1 x
I did not submit a solution at the time, but have written this later.
The essence of my solution is:
That sounds easy, but it amounts to quite a few lines of code.
One arguable aspect is that I worked with the cells in a 1-dimensional array with index of
$x + $y * $width
. My reason for doing that is that passing multidimensional arrays as subroutine
arguments is a bit messy in Perl, and the ($x, $y) <-> $j
conversion is cheap.
I have, separately, coded Minesweeper as a game in Perl and Jscript: if you would like a copy drop me an email.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2021-08-16 use utf8; # Week 126 - task 2 - Minesweeper game use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; minesweeper_game('x * * * x * x x x x', '* * * * * * * * * x', '* * * * x * x * x *', '* * * x x * * * * *', 'x * * * x * * * * x'); minesweeper_game('* * x * x', '* x * x *', '* * x x x', 'x x * * *', 'x * x x x', 'x x x * x', '* x x x x'); sub minesweeper_game { my (@input, @cell, $height, $width, $g, $x, $y, $xx, $yy, $c, $j); # preliminaries - build $cell and change all * to 0 $height = @_; for $y (@_) { $cell[$j ++] = $1 while $y =~ m|([^ ])|g; } $width = $j / $height; show_grid('Input:', $height, $width, \@cell); $cell[$_] = $cell[$_] eq '*' ? 0 : 'x' for 0 .. $height * $width - 1; # loop over all cells for $x (0 .. $width - 1) { for $y (0 .. $height - 1) { $j = $x + $y * $width; # skip unless this is a bomb next unless $cell[$j] eq 'x'; # loop over neighbouring cells for ($xx = $x - 1; $xx <= $x + 1; $xx ++) { for ($yy = $y - 1; $yy <= $y + 1; $yy ++) { # check not this cell and not off grid if ($xx != $x || $yy != $y) { if ($xx >= 0 && $xx < $width && $yy >= 0 && $yy < $height) { # add to neighbouring bomb count $j = $xx + $yy * $width; $cell[$j] ++ unless $cell[$j] eq 'x'; } } } } } } show_grid('Output:', $height, $width, \@cell) } sub show_grid { my ($cell, $height, $width, $x, $y, $j, $title); # print grid nicely ($title, $height, $width, $cell) = @_; say $title; for $y (0 .. $height - 1) { for $x (0 .. $width - 1) { print $cell->[$x + $y * $width] . ' '; } say ''; } }
Input: x * * * x * x x x x * * * * * * * * * x * * * * x * x * x * * * * x x * * * * * x * * * x * * * * x Output: x 1 0 1 x 2 x x x x 1 1 0 2 2 4 3 5 5 x 0 0 1 3 x 3 x 2 x 2 1 1 1 x x 4 1 2 2 2 x 1 1 3 x 2 0 0 1 x Input: * * x * x * x * x * * * x x x x x * * * x * x x x x x x * x * x x x x Output: 1 2 x 3 x 1 x 5 x 4 3 4 x x x x x 5 6 4 x 7 x x x x x x 8 x 3 x x x x
Any content of this website which has been created by Peter Campbell Smith is in the public domain