Add day 12 part 1

This commit is contained in:
kageru 2021-12-12 12:41:23 +01:00
parent 8ccab04d6f
commit 06c8b775fa
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
3 changed files with 157 additions and 0 deletions

24
2021/inputs/day12 Normal file
View File

@ -0,0 +1,24 @@
yb-start
de-vd
rj-yb
rj-VP
OC-de
MU-de
end-DN
vd-end
WK-vd
rj-de
DN-vd
start-VP
DN-yb
vd-MU
DN-rj
de-VP
yb-OC
start-rj
oa-MU
yb-de
oa-VP
jv-MU
yb-MU
end-OC

124
2021/src/bin/day12.rs Normal file
View File

@ -0,0 +1,124 @@
#![feature(test)]
extern crate test;
use std::collections::{HashMap, HashSet};
use aoc2021::common::*;
use itertools::Itertools;
const DAY: usize = 12;
type Parsed<'a> = HashMap<Node<'a>, Vec<Node<'a>>>;
const EMPTY: Vec<Node<'_>> = Vec::new();
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
enum Node<'a> {
Start,
End,
Small(&'a str),
Big(&'a str),
}
impl<'a> From<&'a str> for Node<'a> {
fn from(s: &'a str) -> Self {
match s {
"start" => Node::Start,
"end" => Node::End,
cave if cave.chars().all(|c| c.is_ascii_uppercase()) => Node::Big(cave),
cave if cave.chars().all(|c| c.is_ascii_lowercase()) => Node::Small(cave),
_ => unreachable!(),
}
}
}
fn parse_input(raw: &str) -> Parsed {
raw.lines()
.map(|l| l.split_once('-').unwrap())
.map(|(from, to)| (Node::from(from), Node::from(to)))
.flat_map(|(a, b)| [(a, b), (b, a)]) // connections always go both ways
.into_group_map()
}
fn part1(parsed: &Parsed) -> usize {
possible_paths(parsed, &Node::Start, HashSet::new())
}
fn possible_paths<'a>(map: &'a Parsed, position: &'a Node<'a>, mut visited: HashSet<&'a Node<'a>>) -> usize {
if position == &Node::End {
return 1;
}
if matches!(position, &Node::Small(_)) {
visited.insert(position);
}
map.get(position)
.unwrap()
.iter()
.filter(|&p| p != &Node::Start)
.filter(|p| !visited.contains(p))
.map(|p| possible_paths(map, p, visited.clone()))
.sum()
}
fn part2(parsed: &Parsed) -> usize {
unimplemented!()
}
fn main() {
let raw = read_file(DAY);
let input = parse_input(&raw);
println!("Part 1: {}", part1(&input));
println!("Part 2: {}", part2(&input));
}
#[cfg(test)]
mod tests {
use super::*;
use aoc2021::*;
const TEST_INPUT: &str = "start-A
start-b
A-c
A-b
b-d
A-end
b-end";
const TEST_INPUT_2: &str = "dc-end
HN-start
start-kj
dc-start
dc-HN
LN-dc
HN-end
kj-sa
kj-HN
kj-dc";
const TEST_INPUT_3: &str = "fs-end
he-DX
fs-he
start-DX
pj-DX
end-zg
zg-sl
zg-pj
pj-he
RW-he
fs-DX
pj-RW
zg-RW
start-pj
he-WI
zg-he
pj-fs
start-RW";
test!(part1() == 10);
test!(with _2: part1() == 19);
test!(with _3: part1() == 226);
test!(part2() == 36);
test!(with _2: part2() == 103);
test!(with _3: part2() == 3509);
bench!(part1() == 4411);
bench!(part2() == 0);
bench_input!(HashMap::len => 13);
}

View File

@ -34,4 +34,13 @@ macro_rules! test {
}
}
};
(with $input: ident: $part: ident $(<$gen: literal>)? ($($param: expr),*) == $expected:expr) => {
paste::paste! {
#[test]
fn [<$part $($gen)? _$input:lower _test>]() {
let input = parse_input([<TEST_INPUT $input>]);
assert_eq!($part $(::<$gen>)? (&input$(, $param)*), $expected);
}
}
};
}