Closed simonw closed 1 year ago
What would your total score be if everything goes exactly according to your strategy guide?
So loop through every line, figure out who won to get the score, then add a score based on the second letter.
Started with this - I copied it in from my previous day, then used the comments to prompt Copilot to write some code:
use std::fs;
use std::io;
use std::io::BufRead;
fn main() -> io::Result<()> {
let file = fs::File::open("input.txt")?;
let reader = io::BufReader::new(file);
let mut score = 0;
for line in reader.lines() {
let line = line?;
// Line is of form "A B" - split into two variables
let (a, b) = line.split_at(1);
// Print those
println!("{} {}", a, b);
}
Ok(())
}
I prompted:
// Who won? Opponent A beats me Z, B beats me X, C beats me Y
And got back:
let winner = match (opponent, me) {
("A", "Z") | ("B", "X") | ("C", "Y") => "opponent",
("A", "X") | ("B", "Y") | ("C", "Z") => "me",
_ => "draw",
};
I'll rewrite that to use score numbers instead.
It suggested this but I'm not going to use it:
This is better:
Turns out it was splitting it into 'A'
and ' Z'
- note leading space.
Weird, my code is correct against the example data but when I try to run it against the input and submit the result on Avent of Code it says:
That's not the right answer; your answer is too high
Added a comment and now I can see the problem - it's with the => 6
line:
/*
A/X = rock
B/Y = paper
C/Z = scissors
*/
// Who won? Opponent A beats me Z, B beats me X, C beats me Y
let win_score = match (opponent, me) {
("A", "Z") | ("B", "X") | ("C", "Y") => 0,
("A", "X") | ("B", "Y") | ("C", "Z") => 6,
_ => 3,
};
A, X should not result in a win for me (6 points) - it's a draw.
OK, that fixed it - got through to the next question.
Anyway, the second column says how the round needs to end: X means you need to lose, Y means you need to end the round in a draw, and Z means you need to win. Good luck!
So scoring is still the same, but now the second column tells you how many points you got because we assume you played the right item?
Oh I get it, the columns now just say "opponent picked X and you won/lost/tied" so I have to figure out what I must have picked to get that outcome - so I can calculate that extra_score
.
Prompt-generated this to make it easier to follow:
let mut parts = line.split(" ");
let opponent_code = parts.next().unwrap();
let outcome_code = parts.next().unwrap();
/*
A = rock
B = paper
C = scissors
X = I lose
Y = draw
Z = I win
*/
let opponent = match opponent_code {
"A" => "rock",
"B" => "paper",
"C" => "scissors",
_ => "unknown",
};
let outcome = match(outcome_code) {
"X" => "lose",
"Y" => "draw",
"Z" => "win",
_ => "unknown",
};
--> rock-paper-scissors2.rs:40:24
|
40 | let me = match (opponent, outcome) {
| ^^^^^^^^^^^^^^^^^^^ pattern `(&_, _)` not covered
|
= note: the matched value is of type `(&str, &str)`
I pasted that into https://chat.openai.com/
let opponent = match opponent_code {
"A" => "rock",
"B" => "paper",
"C" => "scissors",
_ => "unknown",
};
let outcome = match outcome_code {
"X" => "lose",
"Y" => "draw",
"Z" => "win",
_ => "unknown",
};
// Need to figure out what I picked, based on opponent + outcome
let me = match (opponent, outcome) {
("rock", "win") => "paper",
("rock", "draw") => "rock",
("rock", "lose") => "scissors",
("paper", "win") => "scissors",
("paper", "draw") => "paper",
("paper", "lose") => "rock",
("scissors", "win") => "rock",
("scissors", "draw") => "scissors",
("scissors", "lose") => "paper",
};
--> rock-paper-scissors2.rs:40:24
|
40 | let me = match (opponent, outcome) {
| ^^^^^^^^^^^^^^^^^^^ pattern `(&_, _)` not covered
|
= note: the matched value is of type `(&str, &str)`
It replied:
This code is trying to figure out what move the player made in a game of rock-paper-scissors based on the opponent's move and the outcome of the game. It appears that the code is using a match statement to check different combinations of the opponent's move and the outcome, and then returning the player's move based on those combinations.
However, the code is currently giving an error because there is no case in the match statement that handles the case where both the opponent's move and the outcome are unknown. This can be fixed by adding a _ => "unknown" case at the end of the match statement, which will handle any combination of values that aren't covered by the other cases. This will ensure that the code always returns a valid move, even if the opponent's move and the outcome are not known.
Here is an example of how the code could be modified to fix this error:
let me = match (opponent, outcome) { ("rock", "win") => "paper", ("rock", "draw") => "rock", ("rock", "lose") => "scissors", ("paper", "win") => "scissors", ("paper", "draw") => "paper", ("paper", "lose") => "rock", ("scissors", "win") => "rock", ("scissors", "draw") => "scissors", ("scissors", "lose") => "paper", _ => "unknown", // Add this case to handle unknown combinations };
Tried that, Advent says "That's not the right answer; your answer is too low".
I forgot to add win_score
to the score
.
That passed.
let me = match (opponent, outcome) { ("rock", "win") => "paper", ("rock", "draw") => "rock", ("rock", "lose") => "scissors", ("paper", "win") => "scissors", ("paper", "draw") => "paper", ("paper", "lose") => "rock", ("scissors", "win") => "rock", ("scissors", "draw") => "scissors", ("scissors", "lose") => "paper", _ => "unknown", // Add this case to handle unknown combinations };
Code review: Instead of writing stringly typed code, I would suggest parsing into enums to leverage Rusts type system and get the guarantees it provides, which is one of rusts big advantages. For example like this.
enum Move {
Rock,
Paper,
Scissors,
}
enum Outcome {
Win,
Lose,
Draw,
}
Which will create new types named Move and Outcome that can only hold those alternatives. The AI can probably tell you how to parse the text into those types. This would also have avoided the error since then the rust compiler would have know that there are no other possible options and not needed an "unknown" case. And if you had missed a potential case in the match the compiler would have told you which one, turning that into a compile-time error instead of a runtime error.
Out of curiosity, what rustc version are you running? For a while, the full output of a case like the missing fallback in the match looks like this, which hopefully would have been helpful:
error[E0004]: non-exhaustive patterns: `(&_, _)` not covered
--> src/main.rs:4:11
|
4 | match (a, b) {
| ^^^^^^ pattern `(&_, _)` not covered
|
= note: the matched value is of type `(&str, &str)`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
6 ~ ("c", "d") => {}
7 + (&_, _) => todo!()
|
https://adventofcode.com/2022/day/2
Puzzle input: https://adventofcode.com/2022/day/2/input
e.g.