Skip to content

Instantly share code, notes, and snippets.

@graffhyrum
Created May 17, 2023 21:01
Show Gist options
  • Select an option

  • Save graffhyrum/655b9750cbcc867292fe8151cc747091 to your computer and use it in GitHub Desktop.

Select an option

Save graffhyrum/655b9750cbcc867292fe8151cc747091 to your computer and use it in GitHub Desktop.
Exercism Rust Minesweeper
pub fn annotate(minefield: &[&str]) -> Vec<String> {
let row_count = minefield.len();
if row_count == 0 {
return vec![];
}
let col_count = minefield[0].len();
if col_count == 0 {
return vec![String::new()];
}
// 2d u8 vector, 0 is space, 9 is a mine, 1-8 is number of mines
let mut two_d_array: Vec<Vec<u8>> = vec![vec![0; col_count]; row_count];
let mut result: Vec<String> = vec![String::new(); row_count];
for (row_index, row) in minefield.iter().enumerate() {
row.as_bytes().iter().enumerate().for_each(|(col_index, cell)| {
if *cell == b'*' {
two_d_array[row_index][col_index] = 9;
// increment all surrounding cells
for i in -1..=1 {
for j in -1..=1 {
if i == 0 && j == 0 {
// ...unless it's the origin
continue;
}
let row = row_index as i32 + i;
let col = col_index as i32 + j;
if row >= 0 && row < row_count as i32 && col >= 0 && col < col_count as i32 {
let cell_val = two_d_array[row as usize][col as usize];
match cell_val {
9 => continue, // don't increment mines
_ => two_d_array[row as usize][col as usize] += 1,
}
}
}
}
}
});
};
result = two_d_array.iter().map(|row| {
row.iter().map(|cell| {
// convert back to char
match cell {
9 => '*',
0 => ' ',
_ => (cell + 48) as char,
}
}).collect()
}).collect();
result
}
enum Option {
Some(i32),
None,
}
enum Result {
Ok(i32),
Err(String),
}
use minesweeper::annotate;
fn remove_annotations(board: &[&str]) -> Vec<String> {
board.iter().map(|r| remove_annotations_in_row(r)).collect()
}
fn remove_annotations_in_row(row: &str) -> String {
row.chars()
.map(|ch| match ch {
'*' => '*',
_ => ' ',
})
.collect()
}
fn run_test(test_case: &[&str]) {
let cleaned = remove_annotations(test_case);
let cleaned_strs = cleaned.iter().map(|r| &r[..]).collect::<Vec<_>>();
let expected = test_case.iter().map(|&r| r.to_string()).collect::<Vec<_>>();
assert_eq!(expected, annotate(&cleaned_strs));
}
#[test]
fn no_rows() {
#[rustfmt::skip]
run_test(&[
]);
}
#[test]
#[ignore]
fn no_columns() {
#[rustfmt::skip]
run_test(&[
"",
]);
}
#[test]
#[ignore]
fn no_mines() {
#[rustfmt::skip]
run_test(&[
" ",
" ",
" ",
]);
}
#[test]
#[ignore]
fn board_with_only_mines() {
#[rustfmt::skip]
run_test(&[
"***",
"***",
"***",
]);
}
#[test]
#[ignore]
fn mine_surrounded_by_spaces() {
#[rustfmt::skip]
run_test(&[
"111",
"1*1",
"111",
]);
}
#[test]
#[ignore]
fn space_surrounded_by_mines() {
#[rustfmt::skip]
run_test(&[
"***",
"*8*",
"***",
]);
}
#[test]
#[ignore]
fn horizontal_line() {
#[rustfmt::skip]
run_test(&[
"1*2*1",
]);
}
#[test]
#[ignore]
fn horizontal_line_mines_at_edges() {
#[rustfmt::skip]
run_test(&[
"*1 1*",
]);
}
#[test]
#[ignore]
fn vertical_line() {
#[rustfmt::skip]
run_test(&[
"1",
"*",
"2",
"*",
"1",
]);
}
#[test]
#[ignore]
fn vertical_line_mines_at_edges() {
#[rustfmt::skip]
run_test(&[
"*",
"1",
" ",
"1",
"*",
]);
}
#[test]
#[ignore]
fn cross() {
#[rustfmt::skip]
run_test(&[
" 2*2 ",
"25*52",
"*****",
"25*52",
" 2*2 ",
]);
}
#[test]
#[ignore]
fn large_board() {
#[rustfmt::skip]
run_test(&[
"1*22*1",
"12*322",
" 123*2",
"112*4*",
"1*22*2",
"111111",
]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment