Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
bd71dfb6bb |
2500
src/input.txt
2500
src/input.txt
File diff suppressed because it is too large
Load Diff
195
src/main.rs
195
src/main.rs
@ -1,196 +1,3 @@
|
||||
// https://adventofcode.com/2022/day/2
|
||||
|
||||
const DATA: &'static str = include_str!("input.txt");
|
||||
|
||||
// I can use unwrap()/expect() as much as I want here, since for AoC the input data is expected to make sense.
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
enum Move
|
||||
{
|
||||
Rock,
|
||||
Paper,
|
||||
Scissors
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Outcome
|
||||
{
|
||||
Loss,
|
||||
Draw,
|
||||
Win
|
||||
}
|
||||
|
||||
impl Outcome
|
||||
{
|
||||
pub fn as_score(&self) -> i32
|
||||
{
|
||||
match self {
|
||||
Self::Loss => 0,
|
||||
Self::Draw => 3,
|
||||
Self::Win => 6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Move
|
||||
{
|
||||
pub fn as_score(&self) -> i32
|
||||
{
|
||||
match self {
|
||||
Self::Rock => 1,
|
||||
Self::Paper => 2,
|
||||
Self::Scissors => 3
|
||||
}
|
||||
}
|
||||
|
||||
pub fn did_win_against(&self, other: &Move) -> Outcome
|
||||
{
|
||||
if self == other { Outcome::Draw }
|
||||
else {
|
||||
match self {
|
||||
Self::Rock => {
|
||||
if *other == Move::Paper { Outcome::Loss }
|
||||
else { Outcome::Win }
|
||||
}
|
||||
|
||||
Self::Paper => {
|
||||
if *other == Move::Scissors { Outcome::Loss }
|
||||
else { Outcome::Win }
|
||||
}
|
||||
|
||||
Self::Scissors => {
|
||||
if *other == Move::Rock { Outcome::Loss }
|
||||
else { Outcome::Win }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_for_outcome(&self, outcome: Outcome) -> Move
|
||||
{
|
||||
if outcome == Outcome::Draw { *self }
|
||||
else {
|
||||
match self {
|
||||
Self::Rock => {
|
||||
if outcome == Outcome::Win { Self::Paper }
|
||||
else { Self::Scissors }
|
||||
}
|
||||
|
||||
Self::Paper => {
|
||||
if outcome == Outcome::Win { Self::Scissors }
|
||||
else { Self::Rock }
|
||||
}
|
||||
|
||||
Self::Scissors => {
|
||||
if outcome == Outcome::Win { Self::Rock }
|
||||
else { Self::Paper }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum MoveParseFailure
|
||||
{
|
||||
InvalidMove,
|
||||
}
|
||||
|
||||
impl FromStr for Move {
|
||||
type Err = MoveParseFailure;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"A" => Ok(Self::Rock),
|
||||
"B" => Ok(Self::Paper),
|
||||
"C" => Ok(Self::Scissors),
|
||||
"X" => Ok(Self::Rock),
|
||||
"Y" => Ok(Self::Paper),
|
||||
"Z" => Ok(Self::Scissors),
|
||||
_ => Err(MoveParseFailure::InvalidMove)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum OutcomeParseFailure
|
||||
{
|
||||
InvalidOutcome,
|
||||
}
|
||||
|
||||
impl FromStr for Outcome {
|
||||
type Err = OutcomeParseFailure;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"X" => Ok(Self::Loss),
|
||||
"Y" => Ok(Self::Draw),
|
||||
"Z" => Ok(Self::Win),
|
||||
_ => Err(OutcomeParseFailure::InvalidOutcome)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn score_for_round(my_move: &Move, other_move: &Move) -> i32
|
||||
{
|
||||
let mut score = my_move.as_score();
|
||||
|
||||
let outcome = my_move.did_win_against(other_move);
|
||||
|
||||
score += outcome.as_score();
|
||||
|
||||
score
|
||||
}
|
||||
|
||||
// Calling nth() on an iterator consumes the returned element, that's why I'm calling nth(0) several times
|
||||
|
||||
fn parse_round_and_get_score_part1(round_str: &str) -> Option<i32>
|
||||
{
|
||||
let mut moves = round_str.split(" ");
|
||||
|
||||
let first_move = moves.nth(0)?; // Opponent's move goes first
|
||||
let second_move = moves.nth(0)?; // My move goes second
|
||||
|
||||
Some(score_for_round(&second_move.parse().expect("Expected a valid move"),
|
||||
&first_move.parse().expect("Expected a valid move")))
|
||||
}
|
||||
|
||||
fn parse_round_and_get_score_part2(round_str: &str) -> Option<i32>
|
||||
{
|
||||
let mut moves = round_str.split(" ");
|
||||
|
||||
let opponent_move_str = moves.nth(0)?; // Opponent's move goes first
|
||||
let expected_outcome_str = moves.nth(0)?; // Expected outcome goes second
|
||||
|
||||
let expected_outcome: Outcome = expected_outcome_str.parse().expect("Expected a valid outcome");
|
||||
let opponent_move: Move = opponent_move_str.parse().expect("Expected a valid move");
|
||||
|
||||
Some(score_for_round(&opponent_move.move_for_outcome(expected_outcome),
|
||||
&opponent_move))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn part1()
|
||||
{
|
||||
let mut score = 0;
|
||||
for slice in DATA.split("\n")
|
||||
{
|
||||
score += parse_round_and_get_score_part1(slice).expect("Input data is not correctly structured");
|
||||
}
|
||||
println!("Your total score is {}", score);
|
||||
}
|
||||
|
||||
fn part2()
|
||||
{
|
||||
let mut score = 0;
|
||||
for slice in DATA.split("\n")
|
||||
{
|
||||
score += parse_round_and_get_score_part2(slice).expect("Input data is not correctly structured");
|
||||
}
|
||||
println!("Your total score is {}", score);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
//part1();
|
||||
part2();
|
||||
println!("Hello, world!");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user