day 16, but with a lot of pain
This commit is contained in:
185
Cargo.lock
generated
185
Cargo.lock
generated
@@ -6,9 +6,12 @@ version = 3
|
|||||||
name = "aoc2022"
|
name = "aoc2022"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bitvec",
|
||||||
"itertools",
|
"itertools",
|
||||||
"nom",
|
"nom",
|
||||||
"num",
|
"num",
|
||||||
|
"petgraph",
|
||||||
|
"rayon",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -17,12 +20,110 @@ 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 = "bitvec"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
||||||
|
dependencies = [
|
||||||
|
"funty",
|
||||||
|
"radium",
|
||||||
|
"tap",
|
||||||
|
"wyz",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixedbitset"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "funty"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.10.5"
|
version = "0.10.5"
|
||||||
@@ -32,12 +133,27 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.138"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -129,3 +245,72 @@ checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "petgraph"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143"
|
||||||
|
dependencies = [
|
||||||
|
"fixedbitset",
|
||||||
|
"indexmap",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "radium"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tap"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wyz"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
||||||
|
dependencies = [
|
||||||
|
"tap",
|
||||||
|
]
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bitvec = "1.0.1"
|
||||||
itertools = "0.10.5"
|
itertools = "0.10.5"
|
||||||
nom = "7.1.1"
|
nom = "7.1.1"
|
||||||
num = "0.4.0"
|
num = "0.4.0"
|
||||||
|
petgraph = "0.6.2"
|
||||||
|
rayon = "1.6.1"
|
||||||
|
|||||||
55
inputs/day16.txt
Normal file
55
inputs/day16.txt
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
Valve NA has flow rate=0; tunnels lead to valves MU, PH
|
||||||
|
Valve NW has flow rate=0; tunnels lead to valves KB, MH
|
||||||
|
Valve MR has flow rate=0; tunnels lead to valves GC, FI
|
||||||
|
Valve XD has flow rate=0; tunnels lead to valves UN, CN
|
||||||
|
Valve HK has flow rate=0; tunnels lead to valves AA, IF
|
||||||
|
Valve JL has flow rate=0; tunnels lead to valves IF, WB
|
||||||
|
Valve RQ has flow rate=13; tunnels lead to valves BL, DJ
|
||||||
|
Valve AB has flow rate=0; tunnels lead to valves BO, RU
|
||||||
|
Valve PE has flow rate=0; tunnels lead to valves AZ, IF
|
||||||
|
Valve QF has flow rate=0; tunnels lead to valves TD, AZ
|
||||||
|
Valve BA has flow rate=0; tunnels lead to valves RF, GU
|
||||||
|
Valve SY has flow rate=0; tunnels lead to valves MH, MU
|
||||||
|
Valve NT has flow rate=0; tunnels lead to valves DJ, UN
|
||||||
|
Valve GU has flow rate=21; tunnels lead to valves VJ, BA, YP
|
||||||
|
Valve AZ has flow rate=12; tunnels lead to valves QF, PI, AS, PE
|
||||||
|
Valve WQ has flow rate=23; tunnels lead to valves VJ, UM, CN
|
||||||
|
Valve DR has flow rate=0; tunnels lead to valves GA, CQ
|
||||||
|
Valve UM has flow rate=0; tunnels lead to valves IE, WQ
|
||||||
|
Valve XI has flow rate=0; tunnels lead to valves IE, IF
|
||||||
|
Valve SS has flow rate=0; tunnels lead to valves CQ, MH
|
||||||
|
Valve IE has flow rate=22; tunnels lead to valves YP, UM, XI, XA
|
||||||
|
Valve BT has flow rate=24; tunnels lead to valves KB, BL, GA
|
||||||
|
Valve GA has flow rate=0; tunnels lead to valves DR, BT
|
||||||
|
Valve AR has flow rate=0; tunnels lead to valves IF, FI
|
||||||
|
Valve DJ has flow rate=0; tunnels lead to valves RQ, NT
|
||||||
|
Valve PI has flow rate=0; tunnels lead to valves FI, AZ
|
||||||
|
Valve WB has flow rate=0; tunnels lead to valves TD, JL
|
||||||
|
Valve OQ has flow rate=0; tunnels lead to valves ME, TD
|
||||||
|
Valve RU has flow rate=19; tunnel leads to valve AB
|
||||||
|
Valve IF has flow rate=7; tunnels lead to valves AR, JL, HK, PE, XI
|
||||||
|
Valve BO has flow rate=0; tunnels lead to valves ME, AB
|
||||||
|
Valve CN has flow rate=0; tunnels lead to valves WQ, XD
|
||||||
|
Valve HH has flow rate=0; tunnels lead to valves AA, FS
|
||||||
|
Valve AS has flow rate=0; tunnels lead to valves AA, AZ
|
||||||
|
Valve FS has flow rate=0; tunnels lead to valves HH, MH
|
||||||
|
Valve PQ has flow rate=0; tunnels lead to valves TD, AA
|
||||||
|
Valve AA has flow rate=0; tunnels lead to valves HH, CO, AS, HK, PQ
|
||||||
|
Valve ME has flow rate=18; tunnels lead to valves OQ, BO, PH
|
||||||
|
Valve RF has flow rate=0; tunnels lead to valves UN, BA
|
||||||
|
Valve MH has flow rate=8; tunnels lead to valves FS, NW, SS, SY
|
||||||
|
Valve YP has flow rate=0; tunnels lead to valves IE, GU
|
||||||
|
Valve FI has flow rate=11; tunnels lead to valves PI, MR, AR, CO, DI
|
||||||
|
Valve UU has flow rate=0; tunnels lead to valves CQ, MU
|
||||||
|
Valve CO has flow rate=0; tunnels lead to valves AA, FI
|
||||||
|
Valve TD has flow rate=16; tunnels lead to valves QF, GC, OQ, WB, PQ
|
||||||
|
Valve MU has flow rate=15; tunnels lead to valves SY, UU, NA
|
||||||
|
Valve BL has flow rate=0; tunnels lead to valves BT, RQ
|
||||||
|
Valve PH has flow rate=0; tunnels lead to valves ME, NA
|
||||||
|
Valve XA has flow rate=0; tunnels lead to valves IE, DI
|
||||||
|
Valve GC has flow rate=0; tunnels lead to valves TD, MR
|
||||||
|
Valve KB has flow rate=0; tunnels lead to valves BT, NW
|
||||||
|
Valve DI has flow rate=0; tunnels lead to valves XA, FI
|
||||||
|
Valve CQ has flow rate=9; tunnels lead to valves UU, DR, SS
|
||||||
|
Valve VJ has flow rate=0; tunnels lead to valves WQ, GU
|
||||||
|
Valve UN has flow rate=20; tunnels lead to valves NT, XD, RF
|
||||||
8
src/bin/day16_1.rs
Normal file
8
src/bin/day16_1.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use aoc2022::day16::process_part_1;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let file = fs::read_to_string("./inputs/day16.txt").unwrap();
|
||||||
|
println!("{}", process_part_1(&file));
|
||||||
|
}
|
||||||
8
src/bin/day16_2.rs
Normal file
8
src/bin/day16_2.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use aoc2022::day16::process_part_2;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let file = fs::read_to_string("./inputs/day16.txt").unwrap();
|
||||||
|
println!("{}", process_part_2(&file));
|
||||||
|
}
|
||||||
189
src/day16.rs
Normal file
189
src/day16.rs
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use bitvec::prelude::BitArray;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use nom::branch::alt;
|
||||||
|
use nom::bytes::complete::{tag, take};
|
||||||
|
use nom::character::complete;
|
||||||
|
use nom::character::complete::newline;
|
||||||
|
use nom::multi::separated_list1;
|
||||||
|
use nom::sequence::preceded;
|
||||||
|
use nom::IResult;
|
||||||
|
use petgraph::algo::floyd_warshall;
|
||||||
|
use petgraph::prelude::{NodeIndex, UnGraph};
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
|
pub fn process_part_1(input: &str) -> usize {
|
||||||
|
let data = parse_input(input).unwrap().1;
|
||||||
|
let distances = floyd_warshall(&data.graph, |_| 1).unwrap();
|
||||||
|
let targets = data.targets();
|
||||||
|
max_released(
|
||||||
|
&data.graph,
|
||||||
|
&distances,
|
||||||
|
data.start,
|
||||||
|
30,
|
||||||
|
&targets,
|
||||||
|
BitArray::ZERO,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_part_2(input: &str) -> usize {
|
||||||
|
let data = parse_input(input).unwrap().1;
|
||||||
|
let distances = floyd_warshall(&data.graph, |_| 1).unwrap();
|
||||||
|
let targets = data.targets();
|
||||||
|
|
||||||
|
// Split targets about evenly. Human takes (i) nodes, leaving (|targets| - i) nodes for the elephant
|
||||||
|
(1..=targets.len() / 2)
|
||||||
|
.into_par_iter()
|
||||||
|
.flat_map(|n| targets.iter().copied().combinations(n).collect_vec())
|
||||||
|
.map(|human_nodes| {
|
||||||
|
let elephant_nodes = targets
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.filter(|n| !human_nodes.contains(n))
|
||||||
|
.collect();
|
||||||
|
let max_human = max_released(
|
||||||
|
&data.graph,
|
||||||
|
&distances,
|
||||||
|
data.start,
|
||||||
|
26,
|
||||||
|
&human_nodes,
|
||||||
|
BitArray::ZERO,
|
||||||
|
);
|
||||||
|
let max_elephant = max_released(
|
||||||
|
&data.graph,
|
||||||
|
&distances,
|
||||||
|
data.start,
|
||||||
|
26,
|
||||||
|
&elephant_nodes,
|
||||||
|
BitArray::ZERO,
|
||||||
|
);
|
||||||
|
|
||||||
|
max_human + max_elephant
|
||||||
|
})
|
||||||
|
.max()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_released(
|
||||||
|
graph: &UnGraph<usize, u8>,
|
||||||
|
distances: &HashMap<(NodeIndex, NodeIndex), i32>,
|
||||||
|
start: NodeIndex,
|
||||||
|
remaining_time: usize,
|
||||||
|
targets: &Vec<NodeIndex>,
|
||||||
|
opened: BitArray<u64>,
|
||||||
|
) -> usize {
|
||||||
|
let mut max = 0;
|
||||||
|
// If we are out of time, or if we have opened all valves
|
||||||
|
if remaining_time == 0 || opened.count_ones() == targets.len() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for &valve in targets.iter().filter(|&n| !opened[n.index()]) {
|
||||||
|
let distance = distances[&(start, valve)].unsigned_abs() as usize;
|
||||||
|
if remaining_time <= distance {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut opened = opened;
|
||||||
|
opened.set(valve.index(), true);
|
||||||
|
|
||||||
|
let next_time_remaining = remaining_time.saturating_sub(distance).saturating_sub(1);
|
||||||
|
let next_released = max_released(
|
||||||
|
graph,
|
||||||
|
distances,
|
||||||
|
valve,
|
||||||
|
next_time_remaining,
|
||||||
|
targets,
|
||||||
|
opened,
|
||||||
|
);
|
||||||
|
let flow = *graph.node_weight(valve).unwrap() * next_time_remaining;
|
||||||
|
if flow + next_released > max {
|
||||||
|
max = flow + next_released;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
max
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Data {
|
||||||
|
graph: UnGraph<usize, u8>,
|
||||||
|
start: NodeIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Data {
|
||||||
|
fn targets(&self) -> Vec<NodeIndex> {
|
||||||
|
self.graph
|
||||||
|
.node_indices()
|
||||||
|
.filter(|&n| *self.graph.node_weight(n).unwrap() > 0)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(input: &str) -> IResult<&str, Data> {
|
||||||
|
let (input, parsed_valves) = separated_list1(newline, parse_line)(input)?;
|
||||||
|
let mut graph = UnGraph::new_undirected();
|
||||||
|
let mut valves = HashMap::new();
|
||||||
|
let mut valves_by_index = HashMap::new();
|
||||||
|
|
||||||
|
// generate graph nodes
|
||||||
|
for valve in &parsed_valves {
|
||||||
|
let node = graph.add_node(valve.1);
|
||||||
|
valves.insert(valve.0, node);
|
||||||
|
valves_by_index.insert(node, valve.0);
|
||||||
|
}
|
||||||
|
// generate graph edges
|
||||||
|
for valve in &parsed_valves {
|
||||||
|
let valve_node = valves.get(valve.0).unwrap();
|
||||||
|
|
||||||
|
for &neighbor in &valve.2 {
|
||||||
|
let neighbor_node = valves.get(neighbor).unwrap();
|
||||||
|
graph.add_edge(*valve_node, *neighbor_node, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = *valves.get("AA").unwrap();
|
||||||
|
|
||||||
|
Ok((input, Data { graph, start }))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_line(input: &str) -> IResult<&str, (&str, usize, Vec<&str>)> {
|
||||||
|
let (input, valve_name) = preceded(tag("Valve "), take(2usize))(input)?;
|
||||||
|
let (input, flow) = preceded(tag(" has flow rate="), complete::u32)(input)?;
|
||||||
|
let (input, neighbors) = preceded(
|
||||||
|
alt((
|
||||||
|
tag("; tunnels lead to valves "),
|
||||||
|
tag("; tunnel leads to valve "),
|
||||||
|
)),
|
||||||
|
separated_list1(tag(", "), take(2usize)),
|
||||||
|
)(input)?;
|
||||||
|
|
||||||
|
Ok((input, (valve_name, flow as usize, neighbors)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT: &str = "Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
|
||||||
|
Valve BB has flow rate=13; tunnels lead to valves CC, AA
|
||||||
|
Valve CC has flow rate=2; tunnels lead to valves DD, BB
|
||||||
|
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
|
||||||
|
Valve EE has flow rate=3; tunnels lead to valves FF, DD
|
||||||
|
Valve FF has flow rate=0; tunnels lead to valves EE, GG
|
||||||
|
Valve GG has flow rate=0; tunnels lead to valves FF, HH
|
||||||
|
Valve HH has flow rate=22; tunnel leads to valve GG
|
||||||
|
Valve II has flow rate=0; tunnels lead to valves AA, JJ
|
||||||
|
Valve JJ has flow rate=21; tunnel leads to valve II";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day1() {
|
||||||
|
assert_eq!(process_part_1(INPUT), 1651);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day2() {
|
||||||
|
assert_eq!(process_part_2(INPUT), 1707);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,3 +16,4 @@ pub mod day12;
|
|||||||
pub mod day13;
|
pub mod day13;
|
||||||
pub mod day14;
|
pub mod day14;
|
||||||
pub mod day15;
|
pub mod day15;
|
||||||
|
pub mod day16;
|
||||||
|
|||||||
Reference in New Issue
Block a user