Add 2024 day 13
Diff
Cargo.lock | 9 ++++++++-
Cargo.toml | 5 +++++
README | 4 ++--
2024/13.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 113 insertions(+), 3 deletions(-)
@@ -1,11 +1,18 @@
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",
@@ -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
@@ -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 |
@@ -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::<i64>());
}
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::<i64>()
);
}
#[derive(Debug, Copy, Clone)]
pub struct Coords {
x: i64,
y: i64,
}
#[derive(Debug, Clone)]
pub struct Input {
buttons: Vec<Coords>,
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<Input>> {
separated_list1(tag("\n"), parse_block)(s)
}