add: all junk

This commit is contained in:
Charles
2024-12-08 21:56:18 -08:00
parent de3f90b516
commit 465a50488f
5 changed files with 260 additions and 12 deletions
Generated
+32
View File
@@ -7,6 +7,7 @@ name = "advent-of-code-2024"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"regex", "regex",
"threadpool",
] ]
[[package]] [[package]]
@@ -18,12 +19,34 @@ dependencies = [
"memchr", "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]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.4" version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 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]] [[package]]
name = "regex" name = "regex"
version = "1.11.1" version = "1.11.1"
@@ -52,3 +75,12 @@ name = "regex-syntax"
version = "0.8.5" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "threadpool"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
dependencies = [
"num_cpus",
]
+1
View File
@@ -5,3 +5,4 @@ edition = "2021"
[dependencies] [dependencies]
regex = "1.11.1" regex = "1.11.1"
threadpool = "1.8.1"
+68 -12
View File
@@ -23,44 +23,78 @@ fn solve(lines: Vec<String>) -> 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 // Try placing problems
let mut blocks: HashSet<Pair> = HashSet::new(); let mut blocks: HashSet<Pair> = 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()) { let next = match next(path.0, vels[path.1].1, map.len()) {
Some(n) => n, 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]; let o = map[next.0][next.1];
if o == '#' { if o == '#' {
continue; continue;
} }
map[next.0][next.1] = '#'; 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); blocks.insert(next);
} }
map[next.0][next.1] = o; 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. // Returns the number of covered squares if the path ends; else, None.
fn walk( fn walk<P: Pather>(
map: &[Vec<char>], map: &[Vec<char>],
mut cur_position: Pair, mut cur_position: Pair,
mut cur_icon: usize, mut cur_icon: usize,
vels: &[(char, Pair<i64>)], vels: &[(char, Pair<i64>)],
) -> Option<(usize, HashSet<(Pair, usize)>)> { initial_seen_with_direction: &HashSet<(Pair, usize)>,
let mut seen_cells: HashSet<Pair> = HashSet::new(); seen_with_direction: &mut HashSet<(Pair, usize)>,
let mut seen_with_direction: HashSet<(Pair, usize)> = HashSet::new(); pather: &mut P,
) -> Option<()> {
seen_with_direction.clear();
loop { 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; return None;
} }
seen_cells.insert(cur_position);
seen_with_direction.insert((cur_position, cur_icon)); 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 let Some(next) = next(cur_position, vels[cur_icon].1, map.len()) {
if map[next.0][next.1] == '#' { if map[next.0][next.1] == '#' {
cur_icon = (cur_icon + 1) % vels.len(); cur_icon = (cur_icon + 1) % vels.len();
@@ -71,7 +105,29 @@ fn walk(
break; 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)] #[cfg(test)]
+150
View File
@@ -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<String>) -> 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<Triple> {
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<Triple>),
}
impl Op {
fn make_opts(&self) -> Vec<Op> {
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<char> {
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<Triple> {
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<Op> {
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<String> = input!("d7p1.txt");
let got = solve(strings).unwrap();
assert_eq!(got, (3749, 0));
}
}
+9
View File
@@ -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