diff --git a/exercise-book/src/green-yellow-game.md b/exercise-book/src/green-yellow-game.md index 5787081..66fa4b8 100644 --- a/exercise-book/src/green-yellow-game.md +++ b/exercise-book/src/green-yellow-game.md @@ -111,6 +111,22 @@ fn a_bit_of_everything() { "🟩⬜🟨🟨" ); } + +#[test] +fn two_in_guess_one_in_secret() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 3], &[3, 9, 9, 9]), + "⬜⬜🟨⬜" + ); +} + +#[test] +fn two_in_secret_one_in_guess() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 4], &[3, 3, 9, 9]), + "⬜⬜🟨⬜" + ); +} ``` ## Knowledge @@ -199,6 +215,8 @@ Let's do this by copying the input, so we can make it mutable, and mark off any Add `rand = "0.8"` to your Cargo.toml, and make a random number generator with `rand::thread_rng()` (Random Number Generator). You will also have to `use rand::Rng;` to bring the trait into scope. +(A built-in [random number generator](https://github.com/rust-lang/rust/issues/130703) is proposed for the Standard Library but is still nightly only as of October 2024). + Call `your_rng.gen_range()` in a loop.
diff --git a/exercise-solutions/green-yellow/src/bin/complete.rs b/exercise-solutions/green-yellow/src/bin/complete.rs index 2782554..5ed411d 100644 --- a/exercise-solutions/green-yellow/src/bin/complete.rs +++ b/exercise-solutions/green-yellow/src/bin/complete.rs @@ -4,21 +4,34 @@ use rand::Rng; fn calc_green_and_yellow(guess: &[u8; 4], secret: &[u8; 4]) -> String { let mut result = ["⬜"; 4]; - let mut guess = guess.clone(); - let mut secret = secret.clone(); + let mut secret_handled = [false; 4]; for i in 0..guess.len() { if guess[i] == secret[i] { + // that's a match result[i] = "🟩"; - secret[i] = 0; - guess[i] = 0; + // don't match this secret digit again + secret_handled[i] = true; } } - for i in 0..guess.len() { - for j in 0..secret.len() { - if guess[i] == secret[j] && secret[j] != 0 && guess[i] != 0 { - result[i] = "🟨"; + 'guess: for g_idx in 0..guess.len() { + // only process guess digits we haven't already dealt with + if result[g_idx] == "🟩" { + continue; + } + for s_idx in 0..secret.len() { + // only process secret digits we haven't already dealt with + if secret_handled[s_idx] { + continue; + } + if guess[g_idx] == secret[s_idx] { + // put a yellow block in for this guess + result[g_idx] = "🟨"; + // never match this secret digit again + secret_handled[s_idx] = true; + // stop comparing this guessed digit to any other secret digits + continue 'guess; } } } @@ -147,3 +160,19 @@ fn a_bit_of_everything() { "🟩⬜🟨🟨" ); } + +#[test] +fn two_in_guess_one_in_secret() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 3], &[3, 9, 9, 9]), + "⬜⬜🟨⬜" + ); +} + +#[test] +fn two_in_secret_one_in_guess() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 4], &[3, 3, 9, 9]), + "⬜⬜🟨⬜" + ); +} diff --git a/exercise-solutions/green-yellow/src/bin/step4.rs b/exercise-solutions/green-yellow/src/bin/step4.rs index 66af63c..158eac0 100644 --- a/exercise-solutions/green-yellow/src/bin/step4.rs +++ b/exercise-solutions/green-yellow/src/bin/step4.rs @@ -2,21 +2,34 @@ fn calc_green_and_yellow(guess: &[u8; 4], secret: &[u8; 4]) -> String { let mut result = ["⬜"; 4]; - let mut guess = *guess; - let mut secret = *secret; + let mut secret_handled = [false; 4]; for i in 0..guess.len() { if guess[i] == secret[i] { + // that's a match result[i] = "🟩"; - secret[i] = 0; - guess[i] = 0; + // don't match this secret digit again + secret_handled[i] = true; } } - for i in 0..guess.len() { - for j in 0..secret.len() { - if guess[i] == secret[j] && secret[j] != 0 && guess[i] != 0 { - result[i] = "🟨"; + 'guess: for g_idx in 0..guess.len() { + // only process guess digits we haven't already dealt with + if result[g_idx] == "🟩" { + continue; + } + for s_idx in 0..secret.len() { + // only process secret digits we haven't already dealt with + if secret_handled[s_idx] { + continue; + } + if guess[g_idx] == secret[s_idx] { + // put a yellow block in for this guess + result[g_idx] = "🟨"; + // never match this secret digit again + secret_handled[s_idx] = true; + // stop comparing this guessed digit to any other secret digits + continue 'guess; } } } @@ -99,3 +112,19 @@ fn a_bit_of_everything() { "🟩⬜🟨🟨" ); } + +#[test] +fn two_in_guess_one_in_secret() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 3], &[3, 9, 9, 9]), + "⬜⬜🟨⬜" + ); +} + +#[test] +fn two_in_secret_one_in_guess() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 4], &[3, 3, 9, 9]), + "⬜⬜🟨⬜" + ); +} diff --git a/exercise-solutions/green-yellow/src/bin/step5.rs b/exercise-solutions/green-yellow/src/bin/step5.rs index 6d345df..57d8d7f 100644 --- a/exercise-solutions/green-yellow/src/bin/step5.rs +++ b/exercise-solutions/green-yellow/src/bin/step5.rs @@ -4,21 +4,34 @@ use rand::Rng; fn calc_green_and_yellow(guess: &[u8; 4], secret: &[u8; 4]) -> String { let mut result = ["⬜"; 4]; - let mut guess = *guess; - let mut secret = *secret; + let mut secret_handled = [false; 4]; for i in 0..guess.len() { if guess[i] == secret[i] { + // that's a match result[i] = "🟩"; - secret[i] = 0; - guess[i] = 0; + // don't match this secret digit again + secret_handled[i] = true; } } - for i in 0..guess.len() { - for j in 0..secret.len() { - if guess[i] == secret[j] && secret[j] != 0 && guess[i] != 0 { - result[i] = "🟨"; + 'guess: for g_idx in 0..guess.len() { + // only process guess digits we haven't already dealt with + if result[g_idx] == "🟩" { + continue; + } + for s_idx in 0..secret.len() { + // only process secret digits we haven't already dealt with + if secret_handled[s_idx] { + continue; + } + if guess[g_idx] == secret[s_idx] { + // put a yellow block in for this guess + result[g_idx] = "🟨"; + // never match this secret digit again + secret_handled[s_idx] = true; + // stop comparing this guessed digit to any other secret digits + continue 'guess; } } } @@ -108,3 +121,19 @@ fn a_bit_of_everything() { "🟩⬜🟨🟨" ); } + +#[test] +fn two_in_guess_one_in_secret() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 3], &[3, 9, 9, 9]), + "⬜⬜🟨⬜" + ); +} + +#[test] +fn two_in_secret_one_in_guess() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 4], &[3, 3, 9, 9]), + "⬜⬜🟨⬜" + ); +} diff --git a/exercise-solutions/green-yellow/src/bin/step6.rs b/exercise-solutions/green-yellow/src/bin/step6.rs index 80fca99..62ce74f 100644 --- a/exercise-solutions/green-yellow/src/bin/step6.rs +++ b/exercise-solutions/green-yellow/src/bin/step6.rs @@ -5,28 +5,40 @@ use rand::Rng; #[allow(unused)] fn calc_green_and_yellow(guess: &[u8; 4], secret: &[u8; 4]) -> String { let mut result = ["⬜"; 4]; - let mut guess = *guess; - let mut secret = *secret; + let mut secret_handled = [false; 4]; for i in 0..guess.len() { if guess[i] == secret[i] { + // that's a match result[i] = "🟩"; - secret[i] = 0; - guess[i] = 0; + // don't match this secret digit again + secret_handled[i] = true; } } - for i in 0..guess.len() { - for j in 0..secret.len() { - if guess[i] == secret[j] && secret[j] != 0 && guess[i] != 0 { - result[i] = "🟨"; + 'guess: for g_idx in 0..guess.len() { + // only process guess digits we haven't already dealt with + if result[g_idx] == "🟩" { + continue; + } + for s_idx in 0..secret.len() { + // only process secret digits we haven't already dealt with + if secret_handled[s_idx] { + continue; + } + if guess[g_idx] == secret[s_idx] { + // put a yellow block in for this guess + result[g_idx] = "🟨"; + // never match this secret digit again + secret_handled[s_idx] = true; + // stop comparing this guessed digit to any other secret digits + continue 'guess; } } } result.join("") } - fn main() { let mut rng = rand::thread_rng(); let stdin = std::io::stdin(); @@ -143,3 +155,19 @@ fn a_bit_of_everything() { "🟩⬜🟨🟨" ); } + +#[test] +fn two_in_guess_one_in_secret() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 3], &[3, 9, 9, 9]), + "⬜⬜🟨⬜" + ); +} + +#[test] +fn two_in_secret_one_in_guess() { + assert_eq!( + &calc_green_and_yellow(&[1, 2, 3, 4], &[3, 3, 9, 9]), + "⬜⬜🟨⬜" + ); +}