From e85fe2197b4ee3afe2bd0b8e90fda10ed8edc517 Mon Sep 17 00:00:00 2001 From: mirsella Date: Fri, 15 Dec 2023 07:12:20 +0100 Subject: [PATCH] add day15 --- 2023/Cargo.toml | 2 +- 2023/day15/.gitignore | 19 ++++++++++++++ 2023/day15/Cargo.toml | 11 ++++++++ 2023/day15/build.rs | 28 +++++++++++++++++++++ 2023/day15/src/main.rs | 57 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 2023/day15/.gitignore create mode 100644 2023/day15/Cargo.toml create mode 100644 2023/day15/build.rs create mode 100644 2023/day15/src/main.rs diff --git a/2023/Cargo.toml b/2023/Cargo.toml index 890b19a..db661d1 100644 --- a/2023/Cargo.toml +++ b/2023/Cargo.toml @@ -16,7 +16,7 @@ members = [ "day12", "day13", "day14", - # "day15", + "day15", # "day16", # "day17", # "day18", diff --git a/2023/day15/.gitignore b/2023/day15/.gitignore new file mode 100644 index 0000000..e983cca --- /dev/null +++ b/2023/day15/.gitignore @@ -0,0 +1,19 @@ +input.txt +flamegraph.svg +perf.data* +### Rust +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + diff --git a/2023/day15/Cargo.toml b/2023/day15/Cargo.toml new file mode 100644 index 0000000..c7295ee --- /dev/null +++ b/2023/day15/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "day15" +authors = ["mirsella "] +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +indexmap = "2.1.0" + diff --git a/2023/day15/build.rs b/2023/day15/build.rs new file mode 100644 index 0000000..b6a19a0 --- /dev/null +++ b/2023/day15/build.rs @@ -0,0 +1,28 @@ +use std::fs::File; +use std::io::{self, Read}; +use std::path::PathBuf; +use std::{env, fs}; + +fn replace_in_file(file_path: &PathBuf, old: &str, new: &str) -> io::Result<()> { + let mut contents = String::new(); + File::open(file_path)?.read_to_string(&mut contents)?; + let new_contents = contents.replace(old, new); + if contents != new_contents { + println!("Updating {}", file_path.display()); + fs::write(file_path, new_contents)?; + } + Ok(()) +} + +fn main() -> io::Result<()> { + let pkg_name = env::var("CARGO_PKG_NAME").unwrap(); + replace_in_file( + &"../Cargo.toml".into(), + &format!("# \"{pkg_name}\""), + &format!("\"{pkg_name}\""), + )?; + + replace_in_file(&"./Cargo.toml".into(), "\n[workspace]", "")?; + + Ok(()) +} diff --git a/2023/day15/src/main.rs b/2023/day15/src/main.rs new file mode 100644 index 0000000..77b21cb --- /dev/null +++ b/2023/day15/src/main.rs @@ -0,0 +1,57 @@ +use std::{collections::HashMap, ops::Index}; + +use indexmap::IndexMap; + +fn hash(input: &str) -> usize { + input + .chars() + .fold(0, |acc, c| ((acc + c as usize) * 17) % 256) +} +fn part1(input: &str) -> usize { + input.trim().split(',').map(hash).sum() +} +fn part2(input: &str) -> usize { + let mut boxes = Vec::with_capacity(256); + for _ in 0..256 { + boxes.push(IndexMap::new()) + } + for word in input.trim().split(',') { + let operation = word.find(['=', '-']).unwrap(); + let (lens, value_with_del) = word.split_at(operation); + let value = &value_with_del[1..]; + let h = hash(lens); + if word.chars().nth(operation).unwrap() == '-' { + boxes[h].shift_remove(lens); + } else { + boxes[h].insert(lens, value); + } + } + boxes + .iter() + .enumerate() + .map(|(boxi, h)| { + h.values() + .enumerate() + .map(|(p, value)| (boxi + 1) * (p + 1) * value.parse::().expect(value)) + .sum::() + }) + .sum() +} +fn main() { + let input = include_str!("../input.txt"); + println!("Part 1: {}", part1(input)); + println!("Part 2: {}", part2(input)); +} + +#[cfg(test)] +mod tests { + const INPUT: &str = "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"; + #[test] + fn part1() { + assert_eq!(super::part1(INPUT), 1320); + } + #[test] + fn part2() { + assert_eq!(super::part2(INPUT), 145); + } +}