Skip to content

Instantly share code, notes, and snippets.

@elmendalerenda
Created August 27, 2017 11:03
Show Gist options
  • Save elmendalerenda/156edc41e2ba42d0c24e540286399e18 to your computer and use it in GitHub Desktop.
Save elmendalerenda/156edc41e2ba42d0c24e540286399e18 to your computer and use it in GitHub Desktop.
require "minitest/autorun"
class TestMine < Minitest::Test
def test_1
field = '*'
expected_result = '*'
assert_equal expected_result, minesweeper(1, 1, field)
end
def test_2
field = '.*.'
expected_result = '1*1'
assert_equal expected_result, minesweeper(1, 3, field)
end
def test_3
field = "...\n.*."
expected_result = "111\n1*1"
assert_equal expected_result, minesweeper(2, 3, field)
end
def test_4
field = "...\n...\n..*"
expected_result = "000\n011\n01*"
assert_equal expected_result, minesweeper(3, 3, field)
end
def test_5
field = "*..\n..*"
expected_result = "*21\n12*"
assert_equal expected_result, minesweeper(2, 3, field)
end
def test_6
field = "*..\n..*\n..."
expected_result = "*21\n12*\n011"
assert_equal expected_result, minesweeper(3, 3, field)
end
def test_7
field = "*..\n*.."
expected_result = "*20\n*20"
assert_equal expected_result, minesweeper(2, 3, field)
end
end
MINE = '*'
NO_MINE = '.'
MINE_HINT = '*'
HINT = '1'
NO_HINT = '0'
ROW_SEPARATOR = "\n"
def minesweeper(rows, cols, field)
hint_maps = each_mine(field) do |mine_pos|
create_hint_map(field, mine_pos, rows, cols)
end
merge_maps(hint_maps)
end
def each_mine(field, &block)
mine_pos = -1
mines_count = 1..field.count(MINE)
mines_count.map do
mine_pos = field.index(MINE, mine_pos + 1)
yield(mine_pos)
end
end
def create_hint_map(field, mine_pos, rows, cols)
hint_map = create_empty_hint_map_with_border(field, cols)
mine_pos_with_border = add_border_offset(mine_pos, cols)
add_hints(hint_map, mine_pos_with_border, cols)
remove_border(hint_map, rows, cols)
end
def merge_maps(maps)
maps.reduce do |merged, map|
merge(merged, map)
end
end
def remove_border(hint_map, rows, cols)
border_per_row = 2
hint_map_without_upper_border = hint_map[cols+border_per_row .. -1]
(0..rows-1).map { |row|
start = row * cols + row * border_per_row + 1
hint_map_without_upper_border[start, cols]
}.join(ROW_SEPARATOR)
end
def create_empty_hint_map_with_border(field, cols)
empty_row = NO_HINT * (cols + 2)
left_right_border = /$|^/
hint_map = field.gsub(left_right_border, NO_HINT)
hint_map = hint_map.tr(NO_MINE, NO_HINT)
hint_map = hint_map.tr(ROW_SEPARATOR, '')
empty_row + hint_map + empty_row
end
def add_hints(hint_map, pos, cols)
add_hint(hint_map, pos - cols - 1)
add_hint(hint_map, pos - cols - 2)
add_hint(hint_map, pos - cols - 3)
add_hint(hint_map, pos + cols + 1)
add_hint(hint_map, pos + cols + 2)
add_hint(hint_map, pos + cols + 3)
add_hint(hint_map, pos - 1)
add_hint(hint_map, pos + 1)
end
def merge(a_field, another_field)
[a_field.chars, another_field.chars].transpose.map do |cell|
cell.reduce do |sum, value|
begin
(Integer(value) + Integer(sum)).to_s
rescue
value
end
end
end.join
end
def add_border_offset(pos, cols)
separator_per_line = ROW_SEPARATOR.length
upper_border = cols + 2
cols_with_separator = cols + separator_per_line
offset = upper_border + separator_per_line + (pos / cols_with_separator)
pos + offset
end
def add_hint(hint_map, pos)
valid_hint_pos = hint_map[pos] == NO_HINT
if(valid_hint_pos)
hint_map[pos] = HINT
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment