From b428a21dca3d2421054f7c118c1b5b1d08ed8c47 Mon Sep 17 00:00:00 2001 From: mirsella Date: Tue, 3 Dec 2024 06:38:57 +0100 Subject: [PATCH] add day3 --- 2024/Cargo.toml | 2 +- 2024/day3/.gitignore | 19 +++++++++++++++ 2024/day3/Cargo.toml | 12 +++++++++ 2024/day3/build.rs | 28 +++++++++++++++++++++ 2024/day3/src/main.rs | 57 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 2024/day3/.gitignore create mode 100644 2024/day3/Cargo.toml create mode 100644 2024/day3/build.rs create mode 100644 2024/day3/src/main.rs diff --git a/2024/Cargo.toml b/2024/Cargo.toml index 093b0cb..c562513 100644 --- a/2024/Cargo.toml +++ b/2024/Cargo.toml @@ -3,7 +3,7 @@ resolver = "2" members = [ "day1", "day2", - # "day3", + "day3", # "day4", # "day5", # "day6", diff --git a/2024/day3/.gitignore b/2024/day3/.gitignore new file mode 100644 index 0000000..e983cca --- /dev/null +++ b/2024/day3/.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/2024/day3/Cargo.toml b/2024/day3/Cargo.toml new file mode 100644 index 0000000..75e1a5a --- /dev/null +++ b/2024/day3/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "day3" +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] +itertools = "0.13.0" +regex = "1.11.1" + diff --git a/2024/day3/build.rs b/2024/day3/build.rs new file mode 100644 index 0000000..b6a19a0 --- /dev/null +++ b/2024/day3/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/2024/day3/src/main.rs b/2024/day3/src/main.rs new file mode 100644 index 0000000..0bd7a0d --- /dev/null +++ b/2024/day3/src/main.rs @@ -0,0 +1,57 @@ +use itertools::Itertools; +use regex::Regex; + +fn part1(input: &str) -> usize { + let regex = Regex::new(r"mul\((\d+),(\d+)\)").unwrap(); + regex + .captures_iter(input) + .map(|c| { + c.extract::<2>() + .1 + .into_iter() + .map(|s| s.parse::().unwrap()) + .fold(0, |acc, v| if acc == 0 { v } else { acc * v }) + }) + .sum() +} +fn part2(input: &str) -> usize { + let regex = Regex::new(r"(mul\((\d+),(\d+)\)|don't\(\)|do\(\))").unwrap(); + let mut acc = 0usize; + let mut enabled = true; + for capture in regex.captures_iter(input) { + let full = capture.get(0).unwrap().as_str(); + if full == "don't()" { + enabled = false + } else if full == "do()" { + enabled = true + } else if full.starts_with("mul") { + if enabled { + acc += capture.get(2).unwrap().as_str().parse::().unwrap() + * capture.get(3).unwrap().as_str().parse::().unwrap() + } + } else { + unreachable!(); + } + } + acc +} +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 = "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"; + #[test] + fn part1() { + assert_eq!(super::part1(INPUT), 161); + } + const INPUT2: &str = + "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"; + #[test] + fn part2() { + assert_eq!(super::part2(INPUT2), 48); + } +}