1
0
Fork 0

Solve day 12 part 2

This commit is contained in:
Lars Martens 2023-12-19 23:53:54 +01:00
parent d194e892af
commit d04d193f4c
Signed by: haselkern
GPG key ID: B5CF1F363C179AD4
3 changed files with 242 additions and 47 deletions

180
Cargo.lock generated
View file

@ -2,6 +2,18 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "ahash"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.1.2" version = "1.1.2"
@ -11,6 +23,12 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "allocator-api2"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.75" version = "1.0.75"
@ -22,6 +40,7 @@ name = "aoc2023"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cached",
"indicatif", "indicatif",
"itertools", "itertools",
"rayon", "rayon",
@ -36,6 +55,39 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "cached"
version = "0.46.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7c8c50262271cdf5abc979a5f76515c234e764fa025d1ba4862c0f0bcda0e95"
dependencies = [
"ahash",
"cached_proc_macro",
"cached_proc_macro_types",
"hashbrown",
"instant",
"once_cell",
"thiserror",
]
[[package]]
name = "cached_proc_macro"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c878c71c2821aa2058722038a59a67583a4240524687c6028571c9b395ded61f"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "cached_proc_macro_types"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -88,6 +140,41 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "darling"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 1.0.109",
]
[[package]]
name = "darling_macro"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
dependencies = [
"darling_core",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.9.0" version = "1.9.0"
@ -100,6 +187,28 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
dependencies = [
"ahash",
"allocator-api2",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "indicatif" name = "indicatif"
version = "0.17.7" version = "0.17.7"
@ -171,6 +280,12 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "portable-atomic" name = "portable-atomic"
version = "1.5.1" version = "1.5.1"
@ -273,7 +388,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.39",
] ]
[[package]] [[package]]
@ -287,6 +402,23 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.39" version = "2.0.39"
@ -298,6 +430,26 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "thiserror"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.12"
@ -310,6 +462,12 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.45.0" version = "0.45.0"
@ -375,3 +533,23 @@ name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "zerocopy"
version = "0.7.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
]

View file

@ -5,6 +5,7 @@ edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.75" anyhow = "1.0.75"
cached = "0.46.1"
indicatif = { version = "0.17.7", features = ["rayon"] } indicatif = { version = "0.17.7", features = ["rayon"] }
itertools = "0.12.0" itertools = "0.12.0"
rayon = "1.8.0" rayon = "1.8.0"

View file

@ -1,12 +1,14 @@
use aoc2023::*; use aoc2023::*;
use std::collections::VecDeque; use cached::proc_macro::cached;
use itertools::Itertools;
use std::{collections::VecDeque, fmt::Debug, iter};
const INPUT: &str = include_str!("../../input/12"); const INPUT: &str = include_str!("../../input/12");
fn main() { fn main() {
assert_example!(part1, "12-test", 21); assert_example!(part1, "12-test", 21);
println!("Part 1: {}", part1(INPUT)); println!("Part 1: {}", part1(INPUT));
assert_example!(part2, "12-test", 0); assert_example!(part2, "12-test", 525152);
println!("Part 2: {}", part2(INPUT)); println!("Part 2: {}", part2(INPUT));
} }
@ -14,15 +16,20 @@ fn part1(input: &str) -> usize {
input input
.lines() .lines()
.map(Row::parse) .map(Row::parse)
.map(Row::possible_arrangements) .map(possible_arrangements)
.sum() .sum()
} }
fn part2(input: &str) -> usize { fn part2(input: &str) -> usize {
0 input
.lines()
.map(Row::parse)
.map(Row::unfold)
.map(possible_arrangements)
.sum()
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug, Eq, PartialEq, Hash)]
struct Row { struct Row {
springs: VecDeque<Spring>, springs: VecDeque<Spring>,
groups: VecDeque<usize>, groups: VecDeque<usize>,
@ -36,11 +43,22 @@ impl Row {
Self { springs, groups } Self { springs, groups }
} }
fn possible_arrangements(mut self) -> usize { fn unfold(self) -> Self {
let springs = iter::repeat(self.springs).take(5);
let springs = Itertools::intersperse(springs, [Spring::Unknown].into())
.flatten()
.collect();
let groups = iter::repeat(self.groups).take(5).flatten().collect();
Self { springs, groups }
}
}
#[cached]
fn possible_arrangements(mut row: Row) -> usize {
// Pop all operational springs on the front and then get the first different one. // Pop all operational springs on the front and then get the first different one.
let first = loop { let first = loop {
match self.springs.pop_front() { match row.springs.pop_front() {
None => return if self.groups.is_empty() { 1 } else { 0 }, None => return if row.groups.is_empty() { 1 } else { 0 },
Some(Spring::Operational) => continue, Some(Spring::Operational) => continue,
Some(Spring::Broken) => break InterestingSpring::Broken, Some(Spring::Broken) => break InterestingSpring::Broken,
Some(Spring::Unknown) => break InterestingSpring::Unknown, Some(Spring::Unknown) => break InterestingSpring::Unknown,
@ -50,7 +68,7 @@ impl Row {
match first { match first {
InterestingSpring::Broken => { InterestingSpring::Broken => {
// A broken spring requires a run that matches the group. // A broken spring requires a run that matches the group.
let Some(mut group) = self.groups.pop_front() else { let Some(mut group) = row.groups.pop_front() else {
// There was a broken spring but no group // There was a broken spring but no group
return 0; return 0;
}; };
@ -60,27 +78,25 @@ impl Row {
// Pop all required springs or return if impossible. // Pop all required springs or return if impossible.
loop { loop {
match self.springs.pop_front() { match row.springs.pop_front() {
None if group > 0 => return 0, None if group > 0 => return 0,
None if group == 0 => break, None => break,
Some(Spring::Broken | Spring::Unknown) if group > 0 => group -= 1, Some(Spring::Broken | Spring::Unknown) if group > 0 => group -= 1,
Some(Spring::Broken) if group == 0 => return 0, Some(Spring::Broken) => return 0,
Some(Spring::Operational) if group > 0 => return 0, Some(Spring::Operational) if group > 0 => return 0,
Some(Spring::Operational | Spring::Unknown) => break, Some(Spring::Operational | Spring::Unknown) => break,
other => panic!("group detection weird case {other:?}, group={group}"),
} }
} }
self.possible_arrangements() possible_arrangements(row)
} }
InterestingSpring::Unknown => { InterestingSpring::Unknown => {
// We don't know what kind of spring is here, recursively try both options. // We don't know what kind of spring is here, recursively try both options.
let mut a = self.clone(); let mut a = row.clone();
let mut b = self; let mut b = row;
a.springs.push_front(Spring::Broken); a.springs.push_front(Spring::Broken);
b.springs.push_front(Spring::Operational); b.springs.push_front(Spring::Operational);
a.possible_arrangements() + b.possible_arrangements() possible_arrangements(a) + possible_arrangements(b)
}
} }
} }
} }
@ -91,7 +107,7 @@ enum InterestingSpring {
Unknown, Unknown,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
enum Spring { enum Spring {
Broken, Broken,
Unknown, Unknown,