Compare commits

..

1 Commits
day-2 ... main

Author SHA1 Message Date
bd71dfb6bb Update LICENSE
Forgot that the default license provided by Gitea is a template and needs to be filled out *facepalm*
2022-12-03 15:32:23 +01:00
2 changed files with 1 additions and 2694 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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!");
}