Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 2024/11/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
10 changes: 2 additions & 8 deletions 2024/11/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ name = "y2024d11"
version = "0.1.0"
edition = "2024"

[[bin]]
name = "y2024d11"
path = "src/11.rs"

[dependencies]
bag.workspace = true
derive_more = { workspace = true, features = ["deref"] }
parse-display.workspace = true
parse-display-with.workspace = true
anyhow = "1.0.100"
itertools.workspace = true
1 change: 1 addition & 0 deletions 2024/11/data/example1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0 1 10 99 999
File renamed without changes.
File renamed without changes.
73 changes: 0 additions & 73 deletions 2024/11/src/11.rs

This file was deleted.

8 changes: 8 additions & 0 deletions 2024/11/src/data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[cfg(test)]
pub const EXAMPLE1: &'static str = include_str!("../data/example1");

#[cfg(test)]
pub const EXAMPLE2: &'static str = include_str!("../data/example2");

#[allow(unused)]
pub const INPUT: &'static str = include_str!("../data/input");
11 changes: 11 additions & 0 deletions 2024/11/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
mod data;
mod part1;
mod part2;
mod puzzle;
mod stone;

fn main() {
use data::INPUT;
println!("Part 1: {}", part1::run(INPUT));
println!("Part 2: {}", part2::run(INPUT));
}
44 changes: 44 additions & 0 deletions 2024/11/src/part1/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::*;
use puzzle::Puzzle;
use stone::Stone;

type Stones = Vec<Stone>;

pub fn blink(stones: &Stones) -> Stones {
stones.into_iter().flat_map(Stone::blink).collect()
}

pub fn run(input: &str) -> usize {
let puzzle: Puzzle = input.parse().expect("parse failed");
let mut stones = puzzle.0;
for _ in 0..25 {
stones = blink(&stones);
}
stones.len()
}

#[cfg(test)]
mod test {
use super::*;
use anyhow::Result;
use data::EXAMPLE1;
use data::EXAMPLE2;

#[test]
fn test_blink() -> Result<()> {
let puzzle: Puzzle = EXAMPLE1.parse()?;
assert_eq!(
blink(&puzzle.0),
[1, 2024, 1, 0, 9, 9, 2021976]
.into_iter()
.map(Stone)
.collect::<Stones>()
);
Ok(())
}

#[test]
fn test1() {
assert_eq!(run(EXAMPLE2), 55312);
}
}
48 changes: 48 additions & 0 deletions 2024/11/src/part2/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use crate::*;
use itertools::Itertools;
use puzzle::Puzzle;
use std::collections::HashMap;
use stone::Stone;

type Stones = HashMap<Stone, usize>;

fn blink(stones: &Stones) -> Stones {
stones
.iter()
.flat_map(|(&stone, &count)| stone.blink().into_iter().map(move |stone| (stone, count)))
.into_grouping_map()
.sum()
}

pub fn run(input: &str) -> usize {
let puzzle: Puzzle = input.parse().expect("parse failed");
let mut stones: Stones = puzzle.0.iter().map(|&stone| (stone, 1usize)).collect();
for _ in 0..75 {
stones = blink(&stones);
}
stones.into_iter().map(|(_, count)| count).sum()
}

#[cfg(test)]
mod test {
use super::*;
use anyhow::Result;
use data::EXAMPLE1;

#[test]
fn test_blink() -> Result<()> {
let puzzle: Puzzle = EXAMPLE1.parse()?;
let stones: Stones = puzzle.0.iter().copied().counts();
assert_eq!(
blink(&stones),
Stones::from([
(Stone(1), 2),
(Stone(2024), 1),
(Stone(0), 1),
(Stone(9), 2),
(Stone(2021976), 1)
])
);
Ok(())
}
}
19 changes: 19 additions & 0 deletions 2024/11/src/puzzle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use crate::*;
use anyhow::Result;
use std::str::FromStr;
use stone::Stone;

#[derive(Debug)]
pub struct Puzzle(pub Vec<Stone>);

impl FromStr for Puzzle {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self> {
Ok(Puzzle(
s.split(' ')
.map(|s| Ok(Stone(s.parse()?)))
.collect::<Result<_>>()?,
))
}
}
25 changes: 25 additions & 0 deletions 2024/11/src/stone.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Stone(pub u64);

impl Stone {
pub fn blink(&self) -> Vec<Self> {
match self.0 {
0 => vec![Stone(1)],
n @ (10..100) => vec![Stone(n / 10), Stone(n % 10)],
n @ (1000..10000) => vec![Stone(n / 100), Stone(n % 100)],
n @ (100000..1000000) => vec![Stone(n / 1000), Stone(n % 1000)],
n @ (10000000..100000000) => vec![Stone(n / 10000), Stone(n % 10000)],
n @ (1000000000..10000000000) => vec![Stone(n / 100000), Stone(n % 100000)],
n @ (100000000000..1000000000000) => vec![Stone(n / 1000000), Stone(n % 1000000)],
n @ (10000000000000..100000000000000) => vec![Stone(n / 10000000), Stone(n % 10000000)],
n @ (1000000000000000..10000000000000000) => {
vec![Stone(n / 100000000), Stone(n % 100000000)]
}
n @ (100000000000000000..1000000000000000000) => {
vec![Stone(n / 1000000000), Stone(n % 1000000000)]
}
n @ (10000000000000000000..) => vec![Stone(n / 10000000000), Stone(n % 10000000000)],
n => vec![Stone(n * 2024)],
}
}
}
18 changes: 8 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.