Day 14 + cleanup
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Julius 2021-12-14 12:20:03 +01:00
parent 7710d82945
commit 3a00251b3c
Signed by: j00lz
GPG key ID: AF241B0AA237BBA2
6 changed files with 266 additions and 15 deletions

102
input/day14 Normal file
View file

@ -0,0 +1,102 @@
OHFNNCKCVOBHSSHONBNF
SV -> O
KP -> H
FP -> B
VP -> V
KN -> S
KS -> O
SB -> K
BS -> K
OF -> O
ON -> S
VS -> F
CK -> C
FB -> K
CH -> K
HS -> H
PO -> F
NP -> N
FH -> C
FO -> O
FF -> C
CO -> K
NB -> V
PP -> S
BB -> N
HH -> B
KK -> H
OP -> K
OS -> V
KV -> F
VH -> F
OB -> S
CN -> H
SF -> K
SN -> P
NF -> H
HB -> V
VC -> S
PS -> P
NK -> B
CV -> P
BC -> S
NH -> K
FN -> P
SH -> F
FK -> P
CS -> O
VV -> H
OC -> F
CC -> N
HK -> N
FS -> P
VF -> B
SS -> V
PV -> V
BF -> V
OV -> C
HO -> F
NC -> F
BN -> F
HC -> N
KO -> P
KH -> F
BV -> S
SK -> F
SC -> F
VN -> V
VB -> V
BH -> O
CP -> K
PK -> K
PB -> K
FV -> S
HN -> K
PH -> B
VK -> B
PC -> H
BO -> H
SP -> V
NS -> B
OH -> N
KC -> H
HV -> F
HF -> B
HP -> S
CB -> P
PN -> S
BK -> K
PF -> N
SO -> P
CF -> B
VO -> C
OO -> K
FC -> F
NV -> F
OK -> K
NN -> O
NO -> O
BP -> O
KB -> O
KF -> O

View file

@ -69,10 +69,8 @@ fn do_flash(mut hm: &mut FlashMap, mut flashing: &mut Vec<(i32, i32)>, mut flash
for yn in (y - 1)..=(y + 1) { for yn in (y - 1)..=(y + 1) {
if let Some(e) = hm.get_mut(&(xn, yn)) { if let Some(e) = hm.get_mut(&(xn, yn)) {
*e += 1; *e += 1;
if *e > 9 { if *e > 9 && !flashed.contains(&(xn, yn)) && !flashing.contains(&(xn, yn)) {
if !flashed.contains(&(xn, yn)) && !flashing.contains(&(xn, yn)) { flashing.push((xn, yn))
flashing.push((xn, yn))
}
} }
} }
} }

View file

@ -13,11 +13,11 @@ impl Day for Day12 {
let second = z[1]; let second = z[1];
{ {
let first_cave = caves.entry(first.to_string()).or_insert(Cave::new(first.into())); let first_cave = caves.entry(first.to_string()).or_insert_with(|| Cave::new(first.into()));
first_cave.add_connection(second); first_cave.add_connection(second);
} }
{ {
let second_cave = caves.entry(second.to_string()).or_insert(Cave::new(second.into())); let second_cave = caves.entry(second.to_string()).or_insert_with(|| Cave::new(second.into()));
second_cave.add_connection(first); second_cave.add_connection(first);
} }
} }
@ -35,6 +35,7 @@ impl Day for Day12 {
Ok(format!("{}", self.search("start", &m, false))) Ok(format!("{}", self.search("start", &m, false)))
} }
} }
#[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone)] #[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
enum CaveType { enum CaveType {
Large, Large,
@ -55,7 +56,7 @@ impl Cave {
} }
fn new(cave_name: String) -> Self { fn new(cave_name: String) -> Self {
let cave_type = if cave_name.chars().nth(0).unwrap().is_uppercase() { let cave_type = if cave_name.chars().next().unwrap().is_uppercase() {
CaveType::Large CaveType::Large
} else { } else {
CaveType::Small CaveType::Small
@ -70,10 +71,8 @@ impl Cave {
impl Day12 { impl Day12 {
fn search(&self, cur: &str, had: &HashMap<String, i32>, part1: bool) -> i32 { fn search(&self, cur: &str, had: &HashMap<String, i32>, part1: bool) -> i32 {
let mut had = had.clone(); let mut had = had.clone();
if had.values().any(|&i| i > 1) || part1 { if (had.values().any(|&i| i > 1) || part1) && had.contains_key(cur) {
if had.contains_key(cur) { return 0;
return 0;
}
} }
if cur == "start" && had.contains_key("start") { if cur == "start" && had.contains_key("start") {
return 0; return 0;
@ -86,7 +85,7 @@ impl Day12 {
let e = had.entry(cur.into()).or_insert(0); let e = had.entry(cur.into()).or_insert(0);
*e += 1; *e += 1;
} }
return n.connections.iter().map(|c| self.search(c, &mut had, part1)).sum::<i32>(); return n.connections.iter().map(|c| self.search(c, &had, part1)).sum::<i32>();
} }
} }

View file

@ -17,7 +17,7 @@ impl FromStr for Fold {
type Err = (); type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
let r = s.rsplit(' ').nth(0).ok_or_else(|| ())?; let r = s.rsplit(' ').next().ok_or(())?;
let z = r.split('=').collect::<Vec<_>>(); let z = r.split('=').collect::<Vec<_>>();
match z[0] { match z[0] {
"x" => Ok(Fold::X(z[1].parse().map_err(|_| ())?)), "x" => Ok(Fold::X(z[1].parse().map_err(|_| ())?)),
@ -31,7 +31,7 @@ impl FromStr for Fold {
impl Day for Day13 { impl Day for Day13 {
fn init(content: String) -> anyhow::Result<Self> { fn init(content: String) -> anyhow::Result<Self> {
let l = content.lines(); let l = content.lines();
let points = l.clone().take_while(|&x| x != "").map(|st| st.split(',') let points = l.clone().take_while(|&x| !x.is_empty()).map(|st| st.split(',')
.map(str::parse).flatten().collect::<Vec<i32>>()).map(|v| (v[0], v[1])).collect::<HashSet<_>>(); .map(str::parse).flatten().collect::<Vec<i32>>()).map(|v| (v[0], v[1])).collect::<HashSet<_>>();
Ok(Self { Ok(Self {

149
src/day14.rs Normal file
View file

@ -0,0 +1,149 @@
use std::collections::HashMap;
use crate::Day;
type ReplacementMap = HashMap<String, Vec<String>>;
pub struct Day14 {
start: HashMap<String, u64>,
end: char,
replacements: ReplacementMap,
}
impl Day for Day14 {
fn init(content: String) -> anyhow::Result<Self> {
let mut line_iter = content.lines().peekable();
let input: Vec<char> = line_iter.next().unwrap().chars().collect();
let mut start = HashMap::new();
for i in 0..input.len() - 1 {
let pair = format!("{}{}", input[i], input[i + 1]);
let count = start.entry(pair).or_insert(0);
*count += 1;
}
line_iter.next();
let mut replacements = HashMap::new();
for line in line_iter {
let cap = line.split(" -> ").collect::<Vec<_>>();
let pair = cap[0].to_string();
let output = cap[1].to_string().chars().next().unwrap();
replacements.insert(
pair.clone(),
vec![
format!("{}{}", pair.chars().next().unwrap(), output),
format!("{}{}", output, pair.chars().nth(1).unwrap()),
],
);
}
Ok(Self {
start,
replacements,
end: *input.last().unwrap(),
})
}
fn part1(&self) -> anyhow::Result<String> {
Ok(format!("{}", self.iterate(10)))
}
fn part2(&self) -> anyhow::Result<String> {
Ok(format!("{}", self.iterate(40)))
}
}
impl Day14 {
fn iterate(&self, amount: u64) -> u64 {
let mut s = self.start.clone();
for _ in 0..amount {
s = do_pain(&s, &self.replacements);
}
let mut counts: HashMap<char, u64> = HashMap::new();
for (st, b) in s {
{
let e = counts.entry(st.chars().next().unwrap()).or_insert(0);
*e += b;
}
}
{
let e = counts.entry(self.end).or_insert(0);
*e += 1;
}
let mut min = u64::MAX;
let mut max = 0;
for &count in counts.values() {
min = min.min(count);
max = max.max(count);
}
max - min
}
}
fn do_pain(input: &HashMap<String, u64>, map: &ReplacementMap) -> HashMap<String, u64> {
let mut output_map = HashMap::new();
for (pair, &count) in input {
let new_pairs = map.get(pair).unwrap();
for new_pair in new_pairs {
let output_count = output_map.entry(new_pair.to_string()).or_insert(0);
*output_count += count;
}
}
output_map
}
#[cfg(test)]
mod tests {
use crate::day14::Day14;
use crate::day::Day;
const INPUT: &str = r"NNCB
CH -> B
HH -> N
CB -> H
NH -> C
HB -> C
HC -> B
HN -> C
NN -> C
BH -> H
NC -> B
NB -> B
BN -> B
BB -> N
BC -> B
CC -> N
CN -> C";
#[test]
fn part1_test() -> anyhow::Result<()> {
let d = Day14::init(INPUT.to_string())?;
assert_eq!("1588", d.part1()?);
Ok(())
}
#[test]
fn part2_test() -> anyhow::Result<()> {
let d = Day14::init(INPUT.to_string())?;
assert_eq!("2188189693529", d.part2()?);
Ok(())
}
#[test]
fn part1_real() -> anyhow::Result<()> {
let d = Day14::init(crate::load_input("14")?)?;
assert_eq!("2590", d.part1()?);
Ok(())
}
#[test]
fn part2_real() -> anyhow::Result<()> {
let d = Day14::init(crate::load_input("14")?)?;
assert_eq!("2875665202438", d.part2()?);
Ok(())
}
}

View file

@ -16,6 +16,7 @@ use crate::day10::Day10;
use crate::day11::Day11; use crate::day11::Day11;
use crate::day12::Day12; use crate::day12::Day12;
use crate::day13::Day13; use crate::day13::Day13;
use crate::day14::Day14;
mod day; mod day;
mod day01; mod day01;
@ -31,6 +32,7 @@ mod day10;
mod day11; mod day11;
mod day12; mod day12;
mod day13; mod day13;
mod day14;
fn load_input(day: &str) -> Result<String> { fn load_input(day: &str) -> Result<String> {
read_to_string(format!("./input/day{}", day)).map_err(|x| x.into()) read_to_string(format!("./input/day{}", day)).map_err(|x| x.into())
@ -78,7 +80,8 @@ fn main() -> anyhow::Result<()> {
Box::new(Day10::init(load_input("10")?)?), Box::new(Day10::init(load_input("10")?)?),
Box::new(Day11::init(load_input("11")?)?), Box::new(Day11::init(load_input("11")?)?),
Box::new(Day12::init(load_input("12")?)?), Box::new(Day12::init(load_input("12")?)?),
Box::new(Day13::init(load_input("13")?)?),]; Box::new(Day13::init(load_input("13")?)?),
Box::new(Day14::init(load_input("14")?)?),];
let _verbosity = matches.occurrences_of("v"); let _verbosity = matches.occurrences_of("v");
if matches.is_present("all") { if matches.is_present("all") {