add day 14
This commit is contained in:
parent
12c10cf056
commit
99ec7923f2
102
input/day14.txt
Normal file
102
input/day14.txt
Normal file
|
@ -0,0 +1,102 @@
|
|||
OOFNFCBHCKBBVNHBNVCP
|
||||
|
||||
PH -> V
|
||||
OK -> S
|
||||
KK -> O
|
||||
BV -> K
|
||||
CV -> S
|
||||
SV -> C
|
||||
CK -> O
|
||||
PC -> F
|
||||
SC -> O
|
||||
KC -> S
|
||||
KF -> N
|
||||
SN -> C
|
||||
SF -> P
|
||||
OS -> O
|
||||
OP -> N
|
||||
FS -> P
|
||||
FV -> N
|
||||
CP -> S
|
||||
VS -> P
|
||||
PB -> P
|
||||
HP -> P
|
||||
PK -> S
|
||||
FC -> F
|
||||
SB -> K
|
||||
NC -> V
|
||||
PP -> B
|
||||
PN -> N
|
||||
VN -> C
|
||||
NV -> O
|
||||
OV -> O
|
||||
BS -> K
|
||||
FP -> V
|
||||
NK -> K
|
||||
PO -> B
|
||||
HF -> H
|
||||
VK -> S
|
||||
ON -> C
|
||||
KH -> F
|
||||
HO -> P
|
||||
OO -> H
|
||||
BC -> V
|
||||
CS -> O
|
||||
OC -> B
|
||||
VB -> N
|
||||
OF -> P
|
||||
FK -> H
|
||||
OH -> H
|
||||
CF -> K
|
||||
CC -> V
|
||||
BK -> O
|
||||
BH -> F
|
||||
VV -> N
|
||||
KS -> V
|
||||
FO -> F
|
||||
SH -> F
|
||||
OB -> O
|
||||
VH -> F
|
||||
HH -> P
|
||||
PF -> C
|
||||
NF -> V
|
||||
VP -> S
|
||||
CN -> V
|
||||
SK -> O
|
||||
FB -> S
|
||||
FN -> S
|
||||
BF -> H
|
||||
FF -> V
|
||||
CB -> P
|
||||
NN -> O
|
||||
VC -> F
|
||||
HK -> F
|
||||
BO -> H
|
||||
KO -> C
|
||||
CH -> N
|
||||
KP -> C
|
||||
HS -> P
|
||||
NP -> O
|
||||
NS -> V
|
||||
NB -> H
|
||||
HN -> O
|
||||
BP -> C
|
||||
VF -> S
|
||||
KN -> P
|
||||
HC -> C
|
||||
PS -> K
|
||||
BB -> O
|
||||
NO -> N
|
||||
NH -> F
|
||||
BN -> F
|
||||
KV -> V
|
||||
SS -> K
|
||||
CO -> H
|
||||
KB -> P
|
||||
FH -> C
|
||||
SP -> C
|
||||
SO -> V
|
||||
PV -> S
|
||||
VO -> O
|
||||
HV -> N
|
||||
HB -> V
|
|
@ -1,2 +1,3 @@
|
|||
pub mod day1;
|
||||
pub mod day14;
|
||||
pub mod day5;
|
||||
|
|
107
src/days/day14.rs
Normal file
107
src/days/day14.rs
Normal file
|
@ -0,0 +1,107 @@
|
|||
#![libaoc::day(14, "../../input/day14.txt")]
|
||||
use std::collections::HashMap;
|
||||
|
||||
use libaoc::miette::{bail, miette, Result};
|
||||
|
||||
fn part1() -> Result<()> {
|
||||
run(10)
|
||||
}
|
||||
|
||||
fn part2() -> Result<()> {
|
||||
run(40)
|
||||
}
|
||||
|
||||
fn run(iters: u8) -> Result<()> {
|
||||
let Input { start, rules } = parse_input()?;
|
||||
let mut solution = [0; 26];
|
||||
solution[start[0] as usize] = 1;
|
||||
|
||||
let mut cache = HashMap::new();
|
||||
for win in start.windows(2) {
|
||||
solution = compute_pair((win[0], win[1]), &rules, iters, &mut cache)
|
||||
.zip(solution)
|
||||
.map(|(a, b)| a + b);
|
||||
}
|
||||
|
||||
let min = solution.iter().filter(|&&n| n != 0).min().unwrap_or(&0);
|
||||
let max = solution.iter().filter(|&&n| n != 0).max().unwrap_or(&0);
|
||||
|
||||
println!("{}", max - min);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
struct CacheKey {
|
||||
left: u8,
|
||||
right: u8,
|
||||
iter: u8,
|
||||
}
|
||||
|
||||
// This big brain algo isn't by me. I found it in someone else's solutions, but fully understood
|
||||
// and rewrote it.
|
||||
fn compute_pair<'cache>(
|
||||
pair: (u8, u8),
|
||||
rules: &HashMap<(u8, u8), u8>,
|
||||
iter: u8,
|
||||
cache: &'cache mut HashMap<CacheKey, [u64; 26]>,
|
||||
) -> &'cache [u64; 26] {
|
||||
let key = CacheKey {
|
||||
left: pair.0,
|
||||
right: pair.1,
|
||||
iter,
|
||||
};
|
||||
|
||||
if !cache.contains_key(&key) {
|
||||
if let (Some(&ins), 1..) = (rules.get(&pair), iter) {
|
||||
let arr_a = *compute_pair((pair.0, ins), rules, iter - 1, cache);
|
||||
let arr_b = *compute_pair((ins, pair.1), rules, iter - 1, cache);
|
||||
let sum = arr_a.zip(arr_b).map(|(a, b)| a + b);
|
||||
cache.insert(key, sum);
|
||||
} else {
|
||||
let mut arr = [0; 26];
|
||||
arr[pair.1 as usize] = 1;
|
||||
cache.insert(key, arr);
|
||||
}
|
||||
}
|
||||
|
||||
&cache[&key]
|
||||
}
|
||||
|
||||
fn char_to_idx(c: char) -> u8 {
|
||||
c as u8 - b'A'
|
||||
}
|
||||
|
||||
struct Input {
|
||||
start: Vec<u8>,
|
||||
rules: HashMap<(u8, u8), u8>,
|
||||
}
|
||||
|
||||
fn parse_input() -> Result<Input> {
|
||||
let mut lines = INPUT.lines();
|
||||
let poly = lines
|
||||
.next()
|
||||
.ok_or_else(|| miette!("input empty"))?
|
||||
.chars()
|
||||
.map(char_to_idx)
|
||||
.collect();
|
||||
|
||||
let mut rules = HashMap::new();
|
||||
|
||||
for line in lines.skip(1) {
|
||||
let mut line = line.chars();
|
||||
let a = line.next();
|
||||
let b = line.next();
|
||||
let c = line.nth(4);
|
||||
|
||||
match (a, b, c) {
|
||||
(Some(a), Some(b), Some(c)) => {
|
||||
rules.insert((char_to_idx(a), char_to_idx(b)), char_to_idx(c));
|
||||
}
|
||||
|
||||
_ => bail!("invalid input"),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Input { start: poly, rules })
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
#![libaoc::day(5, "../../input/day5.txt")]
|
||||
|
||||
use std::cmp::{max, min, Ordering};
|
||||
use std::io::BufRead;
|
||||
use std::cmp::{max, Ordering};
|
||||
|
||||
use libaoc::miette::{miette, IntoDiagnostic, Result};
|
||||
|
||||
|
@ -39,6 +38,8 @@ fn solve(diagonal: bool) -> Result<()> {
|
|||
if x1 == x2 {
|
||||
let (y1, y2) = small_large(y1, y2);
|
||||
|
||||
// this lint would actually make this more ugly
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for y in y1..=y2 {
|
||||
mtx[y][x1] += 1;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#![feature(array_zip)]
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![feature(linked_list_cursors)]
|
||||
#![feature(proc_macro_hygiene)]
|
||||
|
||||
mod days;
|
||||
mod util;
|
||||
|
||||
use days::*;
|
||||
|
||||
fn main() -> libaoc::miette::Result<()> {
|
||||
libaoc::run_days!(
|
||||
day1,
|
||||
day5,
|
||||
)
|
||||
libaoc::run_days!(day1, day5, day14,)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue