From 4ccdd4610da674e68002eb95f21891cd3dea9e62 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Wed, 25 Dec 2024 14:18:40 +0700 Subject: [PATCH] Add 2024 day 13 --- Cargo.lock | 9 ++++++++- Cargo.toml | 5 +++++ README | 4 ++-- 2024/13.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbe92ee..174e56a 100644 --- a/Cargo.lock +++ a/Cargo.lock @@ -1,11 +1,18 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] name = "aoc2023" version = "0.1.0" dependencies = [ + "anyhow", "arrayvec", "itertools", "nom", diff --git a/Cargo.toml b/Cargo.toml index 254d04e..2867d65 100644 --- a/Cargo.toml +++ a/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "aoc2023" version = "0.1.0" edition = "2021" [dependencies] +anyhow = "1" arrayvec = "0.7" rangemap = "1.4" strum = { version = "0.25", features = ["derive"] } @@ -41,6 +42,10 @@ [[bin]] name = "aoc2024-08" path = "2024/08.rs" + +[[bin]] +name = "aoc2024-13" +path = "2024/13.rs" [profile.release] overflow-checks = true diff --git a/README b/README index 68097cf..8f51829 100644 --- a/README +++ a/README @@ -26,8 +26,8 @@ | 10 | OCaml | | 10 | Haskell | | 11 | OCaml | | 11 | Haskell | | 12 | OCaml | | 12 | Rust | -+---------------------+ | 13 | Haskell | - | 14 | Haskell | +| 13 | Rust | | 13 | Haskell | ++---------------------+ | 14 | Haskell | | 15 | Haskell | | 16 | Haskell | | 17 | Rust | diff --git a/2024/13.rs b/2024/13.rs new file mode 100755 index 0000000..57d472d 100755 --- /dev/null +++ a/2024/13.rs @@ -1,0 +1,98 @@ +use std::io::Read; + +use nom::{ + bytes::complete::tag, + character::complete::{alpha1, digit1}, + combinator::map_parser, + multi::separated_list1, + sequence::{preceded, terminated}, + IResult, +}; + +fn main() -> Result<(), anyhow::Error> { + let mut input = String::new(); + std::io::stdin().read_to_string(&mut input)?; + + let (rest, input) = parse_input(&input).unwrap(); + assert!(rest.is_empty()); + + part1(&input); + part2(&input); + + Ok(()) +} + +fn solve(input: &Input) -> i64 { + let b = (input.prize.y * input.buttons[0].x - input.prize.x * input.buttons[0].y) + / (input.buttons[1].y * input.buttons[0].x - input.buttons[1].x * input.buttons[0].y); + let a = (input.prize.x - b * input.buttons[1].x) / input.buttons[0].x; + + if input.buttons[0].x * a + input.buttons[1].x * b == input.prize.x + && input.buttons[0].y * a + input.buttons[1].y * b == input.prize.y + { + 3 * a + b + } else { + 0 + } +} + +fn part1(input: &[Input]) { + eprintln!("{}", input.iter().map(solve).sum::()); +} + +fn part2(input: &[Input]) { + eprintln!( + "{}", + input + .iter() + .cloned() + .map(|v| Input { + prize: Coords { + x: v.prize.x + 10_000_000_000_000, + y: v.prize.y + 10_000_000_000_000, + }, + ..v + }) + .map(|v| solve(&v)) + .sum::() + ); +} + +#[derive(Debug, Copy, Clone)] +pub struct Coords { + x: i64, + y: i64, +} + +#[derive(Debug, Clone)] +pub struct Input { + buttons: Vec, + prize: Coords, +} + +fn parse_i64(s: &str) -> IResult<&str, i64> { + map_parser(digit1, nom::character::complete::i64)(s) +} + +fn parse_button(s: &str) -> IResult<&str, Coords> { + let (s, _b) = preceded(tag("Button "), alpha1)(s)?; + let (s, x) = preceded(tag(": X+"), parse_i64)(s)?; + let (s, y) = preceded(tag(", Y+"), parse_i64)(s)?; + Ok((s, Coords { x, y })) +} + +fn parse_prize(s: &str) -> IResult<&str, Coords> { + let (s, x) = preceded(tag("Prize: X="), parse_i64)(s)?; + let (s, y) = preceded(tag(", Y="), parse_i64)(s)?; + Ok((s, Coords { x, y })) +} + +fn parse_block(s: &str) -> IResult<&str, Input> { + let (s, buttons) = terminated(separated_list1(tag("\n"), parse_button), tag("\n"))(s)?; + let (s, prize) = terminated(parse_prize, tag("\n"))(s)?; + Ok((s, Input { buttons, prize })) +} + +fn parse_input<'a>(s: &'a str) -> IResult<&'a str, Vec> { + separated_list1(tag("\n"), parse_block)(s) +} -- rgit 0.1.5