mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-27 05:40:32 +01:00
Compare commits
3 Commits
84110350ff
...
1f9915e79d
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f9915e79d | |||
| 96c411126c | |||
| 9aad6fe511 |
@@ -10,6 +10,7 @@ ahash = "0.8.2"
|
||||
anyhow = "1.0.66"
|
||||
clap = { version = "4.0.19", features = ["derive"] }
|
||||
itertools = "0.10.5"
|
||||
ndarray = "0.15.6"
|
||||
nom = "7.1.1"
|
||||
strength_reduce = "0.2.4"
|
||||
|
||||
|
||||
50
2022/inputs/16.txt
Normal file
50
2022/inputs/16.txt
Normal file
@@ -0,0 +1,50 @@
|
||||
Valve QJ has flow rate=11; tunnels lead to valves HB, GL
|
||||
Valve VZ has flow rate=10; tunnel leads to valve NE
|
||||
Valve TX has flow rate=19; tunnels lead to valves MG, OQ, HM
|
||||
Valve ZI has flow rate=5; tunnels lead to valves BY, ON, RU, LF, JR
|
||||
Valve IH has flow rate=0; tunnels lead to valves YB, QS
|
||||
Valve QS has flow rate=22; tunnel leads to valve IH
|
||||
Valve QB has flow rate=0; tunnels lead to valves QX, ES
|
||||
Valve NX has flow rate=0; tunnels lead to valves UH, OP
|
||||
Valve PJ has flow rate=0; tunnels lead to valves OC, UH
|
||||
Valve OR has flow rate=6; tunnels lead to valves QH, BH, HB, JD
|
||||
Valve OC has flow rate=7; tunnels lead to valves IZ, JR, TA, ZH, PJ
|
||||
Valve UC has flow rate=0; tunnels lead to valves AA, BY
|
||||
Valve QX has flow rate=0; tunnels lead to valves AA, QB
|
||||
Valve IZ has flow rate=0; tunnels lead to valves OC, SX
|
||||
Valve AG has flow rate=13; tunnels lead to valves NW, GL, SM
|
||||
Valve ON has flow rate=0; tunnels lead to valves MO, ZI
|
||||
Valve XT has flow rate=18; tunnels lead to valves QZ, PG
|
||||
Valve AX has flow rate=0; tunnels lead to valves UH, MO
|
||||
Valve JD has flow rate=0; tunnels lead to valves OR, SM
|
||||
Valve HM has flow rate=0; tunnels lead to valves TX, QH
|
||||
Valve LF has flow rate=0; tunnels lead to valves ZI, UH
|
||||
Valve QH has flow rate=0; tunnels lead to valves OR, HM
|
||||
Valve RT has flow rate=21; tunnel leads to valve PG
|
||||
Valve NE has flow rate=0; tunnels lead to valves VZ, TA
|
||||
Valve OQ has flow rate=0; tunnels lead to valves TX, GE
|
||||
Valve AA has flow rate=0; tunnels lead to valves QZ, UC, OP, QX, EH
|
||||
Valve UH has flow rate=17; tunnels lead to valves PJ, NX, AX, LF
|
||||
Valve GE has flow rate=0; tunnels lead to valves YB, OQ
|
||||
Valve EH has flow rate=0; tunnels lead to valves AA, MO
|
||||
Valve MG has flow rate=0; tunnels lead to valves TX, NW
|
||||
Valve YB has flow rate=20; tunnels lead to valves IH, GE, XG
|
||||
Valve MO has flow rate=15; tunnels lead to valves EH, ON, AX, ZH, CB
|
||||
Valve JR has flow rate=0; tunnels lead to valves ZI, OC
|
||||
Valve GL has flow rate=0; tunnels lead to valves AG, QJ
|
||||
Valve SM has flow rate=0; tunnels lead to valves JD, AG
|
||||
Valve HB has flow rate=0; tunnels lead to valves OR, QJ
|
||||
Valve TA has flow rate=0; tunnels lead to valves OC, NE
|
||||
Valve PG has flow rate=0; tunnels lead to valves RT, XT
|
||||
Valve XG has flow rate=0; tunnels lead to valves CB, YB
|
||||
Valve ES has flow rate=9; tunnels lead to valves QB, FL
|
||||
Valve BH has flow rate=0; tunnels lead to valves RU, OR
|
||||
Valve FL has flow rate=0; tunnels lead to valves SX, ES
|
||||
Valve CB has flow rate=0; tunnels lead to valves MO, XG
|
||||
Valve QZ has flow rate=0; tunnels lead to valves AA, XT
|
||||
Valve BY has flow rate=0; tunnels lead to valves UC, ZI
|
||||
Valve ZH has flow rate=0; tunnels lead to valves MO, OC
|
||||
Valve OP has flow rate=0; tunnels lead to valves NX, AA
|
||||
Valve NW has flow rate=0; tunnels lead to valves MG, AG
|
||||
Valve RU has flow rate=0; tunnels lead to valves ZI, BH
|
||||
Valve SX has flow rate=16; tunnels lead to valves IZ, FL
|
||||
@@ -1,9 +1,166 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use ahash::AHashMap;
|
||||
use anyhow::Result;
|
||||
use ndarray::Array2;
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete::alpha1;
|
||||
use nom::character::complete::newline;
|
||||
use nom::combinator::into;
|
||||
use nom::multi::many1;
|
||||
use nom::multi::separated_list1;
|
||||
use nom::sequence::preceded;
|
||||
use nom::sequence::terminated;
|
||||
use nom::sequence::tuple;
|
||||
use nom::IResult;
|
||||
|
||||
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||
anyhow::bail!("not implemented")
|
||||
use crate::common::parse_input;
|
||||
|
||||
type ParsedValve<'a> = (&'a [u8], u16, Vec<&'a [u8]>);
|
||||
|
||||
type ParsedNetwork<'a> = Vec<ParsedValve<'a>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SimpleNetwork {
|
||||
valves: Vec<SimpleValve>,
|
||||
start: usize,
|
||||
useful: usize,
|
||||
}
|
||||
|
||||
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||
anyhow::bail!("not implemented")
|
||||
impl Deref for SimpleNetwork {
|
||||
type Target = [SimpleValve];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.valves
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SimpleValve {
|
||||
connected: Vec<usize>,
|
||||
flow: u16,
|
||||
}
|
||||
|
||||
impl From<ParsedNetwork<'_>> for SimpleNetwork {
|
||||
fn from(mut parsed: ParsedNetwork) -> Self {
|
||||
// Make sure the positive numbers are in the front
|
||||
parsed.sort_by(|a, b| b.1.cmp(&a.1));
|
||||
|
||||
let mapping: AHashMap<_, _> = parsed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, (name, _, _))| (*name, index))
|
||||
.collect();
|
||||
|
||||
let useful = parsed.iter().filter(|(_, flow, _)| *flow > 0).count();
|
||||
|
||||
Self {
|
||||
valves: parsed
|
||||
.into_iter()
|
||||
.map(|(_, flow, connected)| {
|
||||
let connected = connected.into_iter().map(|name| mapping[&name]).collect();
|
||||
|
||||
SimpleValve { flow, connected }
|
||||
})
|
||||
.collect(),
|
||||
start: mapping[&b"AA"[..]],
|
||||
useful,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_network(input: &[u8]) -> IResult<&[u8], ParsedNetwork> {
|
||||
let parse_network = terminated(
|
||||
tuple((
|
||||
// Parse the name of the valve
|
||||
preceded(tag("Valve "), alpha1),
|
||||
// Parse the flow of the valve
|
||||
preceded(tag(" has flow rate="), nom::character::complete::u16),
|
||||
// Parse the connections
|
||||
preceded(
|
||||
// Did you really have to distinguish plural
|
||||
alt((
|
||||
tag("; tunnels lead to valves "),
|
||||
tag("; tunnel leads to valve "),
|
||||
)),
|
||||
separated_list1(tag(", "), alpha1),
|
||||
),
|
||||
)),
|
||||
newline,
|
||||
);
|
||||
|
||||
many1(parse_network)(input)
|
||||
}
|
||||
|
||||
pub fn part1(input: &[u8]) -> Result<String> {
|
||||
let network: SimpleNetwork = parse_input(input, into(parse_network))?;
|
||||
|
||||
let (valves_available, dp) = run_optimization(&network, 30);
|
||||
|
||||
Ok(dp[(network.start, valves_available)].to_string())
|
||||
}
|
||||
|
||||
fn run_optimization(network: &SimpleNetwork, time: usize) -> (usize, Array2<u16>) {
|
||||
let valves_available = (1 << network.useful) - 1;
|
||||
let mut cur = Array2::zeros((network.len(), valves_available + 1));
|
||||
let mut prev = cur.clone();
|
||||
|
||||
for time_remaining in 1..time {
|
||||
for pos in 0..network.len() {
|
||||
let bit = 1 << pos;
|
||||
for open_valves in 0..=valves_available {
|
||||
let optimal = if (bit & open_valves) != 0 && time_remaining > 2 {
|
||||
prev[(pos, open_valves - bit)] + time_remaining as u16 * network[pos].flow
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
cur[(pos, open_valves)] = network[pos]
|
||||
.connected
|
||||
.iter()
|
||||
.map(|&other| prev[(other, open_valves)])
|
||||
.fold(optimal, Ord::max);
|
||||
}
|
||||
}
|
||||
|
||||
std::mem::swap(&mut prev, &mut cur);
|
||||
}
|
||||
(valves_available, prev)
|
||||
}
|
||||
|
||||
pub fn part2(input: &[u8]) -> Result<String> {
|
||||
let network: SimpleNetwork = parse_input(input, into(parse_network))?;
|
||||
|
||||
let (valves_available, dp) = run_optimization(&network, 26);
|
||||
|
||||
// Find the minimum of all combinations of your work/elephant's work
|
||||
let best = (0..=valves_available)
|
||||
.map(|my_valves| {
|
||||
let elephant_valves = valves_available - my_valves;
|
||||
|
||||
dp[(network.start, my_valves)] + dp[(network.start, elephant_valves)]
|
||||
})
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
// Guesses: 1802 (too low)
|
||||
Ok(best.to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const SAMPLE: &[u8] = include_bytes!("samples/16.txt");
|
||||
|
||||
#[test]
|
||||
fn sample_part1() {
|
||||
assert_eq!(part1(SAMPLE).unwrap(), "1651");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample_part2() {
|
||||
assert_eq!(part2(SAMPLE).unwrap(), "1707");
|
||||
}
|
||||
}
|
||||
|
||||
10
2022/src/samples/16.txt
Normal file
10
2022/src/samples/16.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
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
|
||||
Reference in New Issue
Block a user