Compare commits
No commits in common. "37293ab29e5abf1451cec7a85652bff5eee324a7" and "f82eaa9490c5a9f3ecbe7ac86342042d5df39cba" have entirely different histories.
37293ab29e
...
f82eaa9490
4 changed files with 0 additions and 265 deletions
|
@ -1,2 +0,0 @@
|
||||||
2068
|
|
||||||
2158894777814
|
|
|
@ -1,102 +0,0 @@
|
||||||
KFFNFNNBCNOBCNPFVKCP
|
|
||||||
|
|
||||||
PB -> F
|
|
||||||
KC -> F
|
|
||||||
OB -> H
|
|
||||||
HV -> N
|
|
||||||
FS -> S
|
|
||||||
CK -> K
|
|
||||||
CC -> V
|
|
||||||
HF -> K
|
|
||||||
VP -> C
|
|
||||||
CP -> S
|
|
||||||
HO -> N
|
|
||||||
OS -> N
|
|
||||||
HS -> O
|
|
||||||
HB -> F
|
|
||||||
OH -> V
|
|
||||||
PP -> B
|
|
||||||
BS -> N
|
|
||||||
VS -> F
|
|
||||||
CN -> B
|
|
||||||
KB -> O
|
|
||||||
KH -> B
|
|
||||||
SS -> K
|
|
||||||
NS -> B
|
|
||||||
BP -> V
|
|
||||||
FB -> S
|
|
||||||
PV -> O
|
|
||||||
NB -> S
|
|
||||||
FC -> F
|
|
||||||
VB -> P
|
|
||||||
PC -> O
|
|
||||||
VF -> K
|
|
||||||
BV -> K
|
|
||||||
OO -> B
|
|
||||||
PN -> N
|
|
||||||
NH -> H
|
|
||||||
SP -> B
|
|
||||||
KF -> O
|
|
||||||
BN -> F
|
|
||||||
OF -> C
|
|
||||||
VV -> H
|
|
||||||
BB -> P
|
|
||||||
KN -> H
|
|
||||||
PO -> C
|
|
||||||
BH -> O
|
|
||||||
HC -> B
|
|
||||||
VO -> O
|
|
||||||
FV -> B
|
|
||||||
PK -> V
|
|
||||||
KO -> H
|
|
||||||
BK -> V
|
|
||||||
SC -> S
|
|
||||||
KV -> B
|
|
||||||
OV -> S
|
|
||||||
HK -> F
|
|
||||||
NP -> V
|
|
||||||
VH -> P
|
|
||||||
OK -> S
|
|
||||||
SO -> C
|
|
||||||
PF -> C
|
|
||||||
SH -> N
|
|
||||||
FP -> V
|
|
||||||
CS -> C
|
|
||||||
HH -> O
|
|
||||||
KK -> P
|
|
||||||
BF -> S
|
|
||||||
NN -> O
|
|
||||||
OC -> C
|
|
||||||
CB -> O
|
|
||||||
BO -> V
|
|
||||||
ON -> F
|
|
||||||
BC -> P
|
|
||||||
NO -> N
|
|
||||||
KS -> H
|
|
||||||
FF -> V
|
|
||||||
FN -> V
|
|
||||||
HP -> N
|
|
||||||
VC -> F
|
|
||||||
OP -> K
|
|
||||||
VN -> S
|
|
||||||
NV -> F
|
|
||||||
SV -> F
|
|
||||||
FO -> V
|
|
||||||
PS -> H
|
|
||||||
VK -> O
|
|
||||||
PH -> P
|
|
||||||
NF -> N
|
|
||||||
KP -> S
|
|
||||||
CF -> S
|
|
||||||
FK -> P
|
|
||||||
FH -> F
|
|
||||||
CO -> H
|
|
||||||
SN -> B
|
|
||||||
NC -> H
|
|
||||||
SK -> P
|
|
||||||
CV -> P
|
|
||||||
CH -> H
|
|
||||||
HN -> N
|
|
||||||
SB -> H
|
|
||||||
NK -> B
|
|
||||||
SF -> H
|
|
|
@ -1,9 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "day14_rs"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
nom = "7.1.0"
|
|
|
@ -1,152 +0,0 @@
|
||||||
#![warn(clippy::pedantic)]
|
|
||||||
use nom::{
|
|
||||||
bytes::complete::{tag, take_till},
|
|
||||||
character::complete::{anychar, newline},
|
|
||||||
combinator::recognize,
|
|
||||||
multi::many1,
|
|
||||||
sequence::{pair, separated_pair, terminated},
|
|
||||||
};
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::io::{stdin, Read};
|
|
||||||
use std::ops::Add;
|
|
||||||
|
|
||||||
type Input<'a> = &'a str;
|
|
||||||
type IResult<'a, T> = nom::IResult<Input<'a>, T>;
|
|
||||||
|
|
||||||
type Rule = ((char, char), char);
|
|
||||||
|
|
||||||
fn rule(i: Input) -> IResult<Rule> {
|
|
||||||
separated_pair(pair(anychar, anychar), tag(" -> "), anychar)(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_input(i: Input) -> IResult<(&str, Vec<Rule>)> {
|
|
||||||
separated_pair(
|
|
||||||
terminated(recognize(take_till(|c| c == '\n')), newline),
|
|
||||||
newline,
|
|
||||||
many1(terminated(rule, newline)),
|
|
||||||
)(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
struct Counter<T> {
|
|
||||||
counts: BTreeMap<T, usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord> Counter<T> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
counts: BTreeMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, el: T) {
|
|
||||||
*self.counts.entry(el).or_insert(0) += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn most_common(&self) -> Option<(&T, usize)> {
|
|
||||||
self.counts
|
|
||||||
.iter()
|
|
||||||
.map(|(el, count)| (el, *count))
|
|
||||||
.max_by_key(|&(_, count)| count)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn least_common(&self) -> Option<(&T, usize)> {
|
|
||||||
self.counts
|
|
||||||
.iter()
|
|
||||||
.map(|(el, count)| (el, *count))
|
|
||||||
.min_by_key(|&(_, count)| count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord> FromIterator<T> for Counter<T> {
|
|
||||||
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
|
||||||
let mut counts = Self::new();
|
|
||||||
for el in iter {
|
|
||||||
counts.push(el);
|
|
||||||
}
|
|
||||||
counts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord + Copy> Add<&Counter<T>> for Counter<T> {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn add(mut self, other: &Self) -> Self {
|
|
||||||
for (el, count) in &other.counts {
|
|
||||||
*self.counts.entry(*el).or_insert(0) += count;
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord> Add for Counter<T> {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn add(mut self, other: Self) -> Self {
|
|
||||||
for (el, count) in other.counts {
|
|
||||||
*self.counts.entry(el).or_insert(0) += count;
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
struct LetterCounter {
|
|
||||||
rules: BTreeMap<(char, char), char>,
|
|
||||||
counts: BTreeMap<(char, char, usize), Counter<char>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LetterCounter {
|
|
||||||
pub fn new(rules: BTreeMap<(char, char), char>) -> Self {
|
|
||||||
let mut counts = BTreeMap::new();
|
|
||||||
for &(left, right) in rules.keys() {
|
|
||||||
counts.insert((left, right, 0), Counter::from_iter([left]));
|
|
||||||
}
|
|
||||||
Self { rules, counts }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_counts_right_exclusive(
|
|
||||||
&mut self,
|
|
||||||
left: char,
|
|
||||||
right: char,
|
|
||||||
depth: usize,
|
|
||||||
) -> &Counter<char> {
|
|
||||||
#[allow(clippy::map_entry)] // lifetimes don't work out
|
|
||||||
if !self.counts.contains_key(&(left, right, depth)) {
|
|
||||||
let middle = self.rules[&(left, right)];
|
|
||||||
let counts_left = self
|
|
||||||
.get_counts_right_exclusive(left, middle, depth - 1)
|
|
||||||
.clone();
|
|
||||||
let counts_right = self.get_counts_right_exclusive(middle, right, depth - 1);
|
|
||||||
let counts = counts_left + counts_right;
|
|
||||||
self.counts.insert((left, right, depth), counts);
|
|
||||||
}
|
|
||||||
&self.counts[&(left, right, depth)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut input = String::new();
|
|
||||||
stdin().lock().read_to_string(&mut input).unwrap();
|
|
||||||
|
|
||||||
let (input, rules) = parse_input(&input).unwrap().1;
|
|
||||||
|
|
||||||
let rules: BTreeMap<_, _> = rules.into_iter().collect();
|
|
||||||
let chars: Vec<_> = input.chars().collect();
|
|
||||||
|
|
||||||
let mut counter = LetterCounter::new(rules);
|
|
||||||
|
|
||||||
let mut run = |steps| {
|
|
||||||
let mut totals = chars.windows(2).fold(Counter::new(), |counts, x| {
|
|
||||||
counts + counter.get_counts_right_exclusive(x[0], x[1], steps)
|
|
||||||
});
|
|
||||||
totals.push(*chars.last().unwrap());
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"{:?}",
|
|
||||||
totals.most_common().unwrap().1 - totals.least_common().unwrap().1
|
|
||||||
);
|
|
||||||
};
|
|
||||||
run(10);
|
|
||||||
run(40);
|
|
||||||
}
|
|
Loading…
Reference in a new issue