Solve day 12 part 2
This commit is contained in:
parent
d194e892af
commit
d04d193f4c
3 changed files with 242 additions and 47 deletions
180
Cargo.lock
generated
180
Cargo.lock
generated
|
@ -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",
|
||||||
|
]
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue