From 465a50488f41195855d3b14edc0ac5ed1f2a0592 Mon Sep 17 00:00:00 2001 From: Charles Date: Sun, 8 Dec 2024 21:56:18 -0800 Subject: [PATCH] add: all junk --- Cargo.lock | 32 ++++++++++ Cargo.toml | 1 + src/bin/d6p1.rs | 80 +++++++++++++++++++++---- src/bin/d7p1.rs | 150 +++++++++++++++++++++++++++++++++++++++++++++++ src/bin/d7p1.txt | 9 +++ 5 files changed, 260 insertions(+), 12 deletions(-) create mode 100644 src/bin/d7p1.rs create mode 100644 src/bin/d7p1.txt diff --git a/Cargo.lock b/Cargo.lock index a45f174..393e58d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ name = "advent-of-code-2024" version = "0.1.0" dependencies = [ "regex", + "threadpool", ] [[package]] @@ -18,12 +19,34 @@ dependencies = [ "memchr", ] +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "libc" +version = "0.2.167" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "regex" version = "1.11.1" @@ -52,3 +75,12 @@ name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] diff --git a/Cargo.toml b/Cargo.toml index 3f298fa..ab85ac5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" [dependencies] regex = "1.11.1" +threadpool = "1.8.1" diff --git a/src/bin/d6p1.rs b/src/bin/d6p1.rs index f51a429..79c02a9 100644 --- a/src/bin/d6p1.rs +++ b/src/bin/d6p1.rs @@ -23,44 +23,78 @@ fn solve(lines: Vec) -> SResult<(usize, usize)> { } } - let (count, paths) = walk(&map, start_position, cur_icon, &vels).unwrap(); + let mut real = RealPath { path: Vec::new() }; + let mut seen_with_direction_reuse: HashSet<(Pair, usize)> = HashSet::new(); + let mut seen_with_direction: HashSet<(Pair, usize)> = HashSet::new(); + walk( + &map, + start_position, + cur_icon, + &vels, + &seen_with_direction, + &mut seen_with_direction_reuse, + &mut real, + ) + .unwrap(); // Try placing problems let mut blocks: HashSet = HashSet::new(); - for path in paths.iter() { + let mut seen = HashSet::with_capacity(real.path.len()); + seen.insert(start_position); + for path in real.path.into_iter() { + seen.insert(path.0); let next = match next(path.0, vels[path.1].1, map.len()) { Some(n) => n, - None => continue, + None => { + continue; + } }; + // We've already been here, so couldn't have placed a block here. + if seen.contains(&next) { + continue; + } let o = map[next.0][next.1]; if o == '#' { continue; } map[next.0][next.1] = '#'; - if let None = walk(&map, start_position, cur_icon, &vels) { + if let None = walk( + &map, + path.0, + path.1, + &vels, + &seen_with_direction, + &mut seen_with_direction_reuse, + &mut FakePath {}, + ) { blocks.insert(next); } map[next.0][next.1] = o; + seen_with_direction.insert(path); } - Ok((count, blocks.len())) + Ok((seen.len(), blocks.len())) } // Returns the number of covered squares if the path ends; else, None. -fn walk( +fn walk( map: &[Vec], mut cur_position: Pair, mut cur_icon: usize, vels: &[(char, Pair)], -) -> Option<(usize, HashSet<(Pair, usize)>)> { - let mut seen_cells: HashSet = HashSet::new(); - let mut seen_with_direction: HashSet<(Pair, usize)> = HashSet::new(); + initial_seen_with_direction: &HashSet<(Pair, usize)>, + seen_with_direction: &mut HashSet<(Pair, usize)>, + pather: &mut P, +) -> Option<()> { + seen_with_direction.clear(); loop { - if seen_with_direction.contains(&(cur_position, cur_icon)) { + if seen_with_direction.contains(&(cur_position, cur_icon)) + || initial_seen_with_direction.contains(&(cur_position, cur_icon)) + { return None; } - seen_cells.insert(cur_position); seen_with_direction.insert((cur_position, cur_icon)); + pather.record((cur_position, cur_icon)); if let Some(next) = next(cur_position, vels[cur_icon].1, map.len()) { if map[next.0][next.1] == '#' { cur_icon = (cur_icon + 1) % vels.len(); @@ -71,7 +105,29 @@ fn walk( break; } } - Some((seen_cells.len(), seen_with_direction)) + Some(()) +} + +trait Pather { + fn record(&mut self, _: (Pair, usize)); +} + +struct RealPath { + path: Vec<(Pair, usize)>, +} + +impl Pather for RealPath { + fn record(&mut self, p: (Pair, usize)) { + self.path.push(p); + } +} + +struct FakePath {} + +impl Pather for FakePath { + fn record(&mut self, _: (Pair, usize)) { + // do nothing + } } #[cfg(test)] diff --git a/src/bin/d7p1.rs b/src/bin/d7p1.rs new file mode 100644 index 0000000..b322685 --- /dev/null +++ b/src/bin/d7p1.rs @@ -0,0 +1,150 @@ +use std::{collections::HashSet, str::Chars}; + +use advent_of_code_2024::{make_main, next, Pair, SResult}; + +make_main!(); + +fn solve(lines: Vec) -> SResult<(usize, usize)> { + let mut total = 0; + for line in lines { + let (_, (target, trip)) = parse_problem(&line).unwrap(); + for opt in trip.make_opts() { + if opt.eval() == target { + total += target; + } + } + } + Ok((total as usize, 0)) +} + +type PResult<'a, S> = Result<(&'a str, S), &'static str>; + +#[derive(PartialEq, Clone)] +struct Triple { + left: Op, + right: Op, + oper: Oper, +} + +impl Triple { + fn make_opts(&self) -> Vec { + if self.oper != Oper::UNKNOWN { + return vec![self.clone()]; + } + let mut ret = vec!(); + for oper in [Oper::ADD, Oper::MUL] { + for left in self.left.make_opts() { + for right in self.right.make_opts() { + ret.push(Triple{left: left.clone(), right, oper}); + } + } + } + ret + } + + fn eval(&self) -> i64 { + match self.oper { + Oper::MUL => self.left.eval() * self.right.eval(), + Oper::ADD => self.left.eval() + self.right.eval(), + Oper::UNKNOWN => unimplemented!(), + } + } +} + +#[derive(PartialEq, Clone)] +enum Op { + Const(i64), + Triple(Box), +} + +impl Op { + fn make_opts(&self) -> Vec { + match self { + Op::Const(x) => vec![Op::Const(*x)], + Op::Triple(t) => { + let mut ret = vec!(); + for triple in t.make_opts() { + ret.push(Op::Triple(Box::new(triple))); + } + ret + } + } + } + + fn eval(&self) -> i64 { + match self { + Op::Const(x) => *x, + Op::Triple(t) => t.eval(), + } + } +} + +#[derive(PartialEq, Clone, Copy)] +enum Oper { + UNKNOWN, + ADD, + MUL, +} + +fn parse_problem(s: &str) -> PResult<(i64, Triple)> { + let (s, target) = take_int(s)?; + let (s, _) = take_one(s)?; + let (s, triple) = parse_triple(s)?; + Ok((s, (target.eval(), triple))) +} + +fn take_one(s: &str) -> PResult { + let c = s.chars().next().ok_or("missing char")?; + Ok((s, c)) +} + +fn take_ws(s: &str) -> PResult<()> { + let mut chars = s,chars(); + let mut i = 0; + + Ok((s.split_at(i), ())) +} + +fn parse_triple(s: &str) -> PResult { + let (s, _) = take_ws(s)?; + let (s, left) = take_int(s)?; + let (s, _) = take_ws(s)?; + let oper = Oper::UNKNOWN; + let (s, _) = take_ws(s)?; + let (s, right) = match parse_triple(s) { + Ok((s, triple)) => (s, Op::Triple(Box::new(triple))), + Err(_) => take_int(s)?, + }; + let (s, _) = take_ws(s)?; + + Ok((s, Triple{left, right, oper})) +} + +fn take_int(s: &str) -> PResult { + let mut total = 0; + let mut i = 0; + let mut chars = s.chars(); + while let Some(c) = chars.by_ref().peekable().next_if(|c| c.is_digit(10)) { + total = total * 10 + c.to_digit(10).unwrap(); + i += 1; + } + if i == 0 { + panic!("here"); + Err("no digits") + } else { + Ok((chars.as_str(), Op::Const(total as i64))) + } +} + +#[cfg(test)] +mod tests { + use advent_of_code_2024::input; + + use super::*; + #[test] + fn sample_input() { + let strings: Vec = input!("d7p1.txt"); + let got = solve(strings).unwrap(); + assert_eq!(got, (3749, 0)); + } +} diff --git a/src/bin/d7p1.txt b/src/bin/d7p1.txt new file mode 100644 index 0000000..87b8b25 --- /dev/null +++ b/src/bin/d7p1.txt @@ -0,0 +1,9 @@ +190: 10 19 +3267: 81 40 27 +83: 17 5 +156: 15 6 +7290: 6 8 6 15 +161011: 16 10 13 +192: 17 8 14 +21037: 9 7 18 13 +292: 11 6 16 20 \ No newline at end of file