Implement day 2 2022

This commit is contained in:
2022-12-02 09:05:31 +01:00
parent 48594a75e6
commit 256d351f8e
4 changed files with 2624 additions and 5 deletions

View File

@@ -8,7 +8,7 @@ use criterion::BenchmarkId;
use criterion::Criterion;
/// Number of days we have an implementation to benchmark
const DAYS_IMPLEMENTED: u8 = 1;
const DAYS_IMPLEMENTED: u8 = 2;
fn read_input(day: u8) -> Vec<u8> {
let input_path = format!("inputs/{:02}.txt", day);

2500
2022/inputs/02.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,125 @@
use anyhow::Result;
use nom::character::complete::newline;
use nom::combinator::map_res;
use nom::multi::many0;
use nom::sequence::separated_pair;
use nom::sequence::terminated;
use nom::IResult;
pub fn part1(_input: &[u8]) -> Result<String> {
todo!()
use crate::common::parse_input;
#[derive(Copy, Clone, Eq, PartialEq)]
enum Rps {
Rock,
Paper,
Scissors,
}
pub fn part2(_input: &[u8]) -> Result<String> {
todo!()
impl Rps {
/// Score we get by playing this move
fn score(self) -> u32 {
match self {
Rps::Rock => 1,
Rps::Paper => 2,
Rps::Scissors => 3,
}
}
/// Score we get from the result from playing given other
fn score_against(self, other: Self) -> u32 {
match (self, other) {
(a, b) if a == b => 3,
(Rps::Rock, Rps::Paper) | (Rps::Paper, Rps::Scissors) | (Rps::Scissors, Rps::Rock) => 0,
_ => 6,
}
}
/// Score if the result is according to the instruction
fn score_result(self) -> u32 {
match self {
Rps::Rock => 0, // Rock is lose
Rps::Paper => 3, // Paper is draw
Rps::Scissors => 6, // Scissors is win
}
}
/// Move we need to achieve the result indicated by self
fn needed(self, other: Self) -> Self {
match (self, other) {
(Rps::Paper, other) => other,
(Rps::Rock, Rps::Rock) => Rps::Scissors,
(Rps::Rock, Rps::Paper) => Rps::Rock,
(Rps::Rock, Rps::Scissors) => Rps::Paper,
(Rps::Scissors, Rps::Rock) => Rps::Paper,
(Rps::Scissors, Rps::Paper) => Rps::Scissors,
(Rps::Scissors, Rps::Scissors) => Rps::Rock,
}
}
}
impl TryFrom<u8> for Rps {
type Error = anyhow::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
b'A' | b'X' => Ok(Rps::Rock),
b'B' | b'Y' => Ok(Rps::Paper),
b'C' | b'Z' => Ok(Rps::Scissors),
_ => Err(anyhow::anyhow!("Invalid RPS: {value}")),
}
}
}
fn parse_plan(input: &[u8]) -> IResult<&[u8], Vec<(Rps, Rps)>> {
fn parse_rps(input: &[u8]) -> IResult<&[u8], Rps> {
// Note: alpha1 also sort of works but is significantly slower
map_res(nom::bytes::complete::take(1usize), |v: &[u8]| {
Rps::try_from(v[0])
})(input)
}
fn parse_line(input: &[u8]) -> IResult<&[u8], (Rps, Rps)> {
separated_pair(parse_rps, nom::character::complete::char(' '), parse_rps)(input)
}
many0(terminated(parse_line, newline))(input)
}
pub fn part1(input: &[u8]) -> Result<String> {
let plan = parse_input(input, parse_plan)?;
let result: u32 = plan
.into_iter()
.map(|(them, us)| us.score() + us.score_against(them))
.sum();
Ok(result.to_string())
}
pub fn part2(input: &[u8]) -> Result<String> {
let plan = parse_input(input, parse_plan)?;
let result: u32 = plan
.into_iter()
.map(|(them, us)| us.score_result() + us.needed(them).score())
.sum();
Ok(result.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
const SAMPLE: &[u8] = include_bytes!("samples/02.txt");
#[test]
fn sample_part1() {
assert_eq!(part1(SAMPLE).unwrap(), "15")
}
#[test]
fn sample_part2() {
assert_eq!(part2(SAMPLE).unwrap(), "12")
}
}

3
2022/src/samples/02.txt Normal file
View File

@@ -0,0 +1,3 @@
A Y
B X
C Z