Implement 2023 day 15 part 1

This commit is contained in:
2023-12-15 08:45:19 +01:00
parent 862ef3840c
commit f898ffd216
2 changed files with 68 additions and 5 deletions

View File

@@ -9,6 +9,7 @@ edition = "2021"
aho-corasick = "1.1.2" aho-corasick = "1.1.2"
anyhow = "1.0.75" anyhow = "1.0.75"
clap = { version = "4.4.8", features = ["derive"] } clap = { version = "4.4.8", features = ["derive"] }
linked-hash-map = "0.5.6"
nom = "7.1.3" nom = "7.1.3"
num-integer = "0.1.45" num-integer = "0.1.45"

View File

@@ -1,3 +1,16 @@
use linked_hash_map::LinkedHashMap;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::bytes::complete::take_till;
use nom::combinator::map;
use nom::multi::separated_list1;
use nom::sequence::separated_pair;
use nom::sequence::terminated;
use nom::IResult;
use crate::common::parse_input;
fn trim(input: &[u8]) -> &[u8] { fn trim(input: &[u8]) -> &[u8] {
let whitespace = input let whitespace = input
.iter() .iter()
@@ -8,10 +21,10 @@ fn trim(input: &[u8]) -> &[u8] {
&input[..(input.len() - whitespace)] &input[..(input.len() - whitespace)]
} }
fn hash(input: &[u8]) -> u32 { fn hash(input: &[u8]) -> u8 {
input input
.iter() .iter()
.fold(0, |cur, &c| ((cur + u32::from(c)) * 17) % 256) .fold(0, |cur, &c| cur.wrapping_add(c).wrapping_mul(17))
} }
pub fn part1(input: &[u8]) -> anyhow::Result<String> { pub fn part1(input: &[u8]) -> anyhow::Result<String> {
@@ -19,13 +32,57 @@ pub fn part1(input: &[u8]) -> anyhow::Result<String> {
Ok(input Ok(input
.split(|&c| c == b',') .split(|&c| c == b',')
.map(hash) .map(|word| u32::from(hash(word)))
.sum::<u32>() .sum::<u32>()
.to_string()) .to_string())
} }
pub fn part2(_input: &[u8]) -> anyhow::Result<String> { enum Command<'a> {
anyhow::bail!("Not implemented") Add(&'a [u8], u32),
Remove(&'a [u8]),
}
fn parse_commands(i: &[u8]) -> IResult<&[u8], Vec<Command>> {
fn is_op(c: u8) -> bool {
c == b'=' || c == b'-'
}
separated_list1(
tag(","),
alt((
map(
separated_pair(take_till(is_op), tag("="), nom::character::complete::u32),
|(a, b)| Command::Add(a, b),
),
map(terminated(take_till(is_op), tag("-")), Command::Remove),
)),
)(i)
}
pub fn part2(input: &[u8]) -> anyhow::Result<String> {
let commands = parse_input(trim(input), parse_commands)?;
let mut boxes = [(); 256].map(|_| LinkedHashMap::new());
for command in &commands {
match command {
Command::Add(identifier, focal_len) => {
*boxes[hash(identifier) as usize]
.entry(*identifier)
.or_default() = *focal_len;
}
Command::Remove(identifier) => {
boxes[hash(identifier) as usize].remove(identifier);
}
}
}
let mut total = 0;
for (i, b) in boxes.iter().enumerate() {
for (slot, &focal_len) in b.values().enumerate() {
total += (i as u32 + 1) * (slot as u32 + 1) * focal_len;
}
}
Ok(total.to_string())
} }
#[cfg(test)] #[cfg(test)]
@@ -43,4 +100,9 @@ mod tests {
fn sample_part1() { fn sample_part1() {
assert_eq!("1320", part1(SAMPLE).unwrap()); assert_eq!("1320", part1(SAMPLE).unwrap());
} }
#[test]
fn sample_part2() {
assert_eq!("145", part2(SAMPLE).unwrap());
}
} }