day 14
This commit is contained in:
parent
0f6f5cfc76
commit
33e9af89be
83
2021/src/day14.rs
Normal file
83
2021/src/day14.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use color_eyre::eyre;
|
||||
|
||||
use crate::lib::{IterExt, Counter};
|
||||
|
||||
|
||||
type Pairs = Counter<(char, char)>;
|
||||
type Rules = HashMap<(char, char), char>;
|
||||
|
||||
|
||||
fn load(data: &str) -> eyre::Result<(Pairs, Rules)> {
|
||||
let mut lines = data.lines();
|
||||
let template = lines.next().unwrap().to_string();
|
||||
let mut pairs = Counter::new();
|
||||
for i in 1..template.len() {
|
||||
let a = template.as_bytes()[i - 1] as char;
|
||||
let b = template.as_bytes()[i] as char;
|
||||
pairs.inc((a, b));
|
||||
}
|
||||
lines.next();
|
||||
|
||||
let mut rules = HashMap::new();
|
||||
for line in &mut lines {
|
||||
let (pair_s, tgt_s) = line.split(" -> ").take_pair()?;
|
||||
let pair = pair_s.chars().take_pair()?;
|
||||
let tgt = tgt_s.chars().next().unwrap();
|
||||
rules.insert(pair, tgt);
|
||||
}
|
||||
|
||||
Ok((pairs, rules))
|
||||
}
|
||||
|
||||
|
||||
fn expand(src: &Pairs, rules: &Rules) -> Pairs {
|
||||
let mut dst = Counter::new();
|
||||
for (&(a, b), count) in src.iter() {
|
||||
if let Some(&tween) = rules.get(&(a, b)) {
|
||||
dst.inc_by((a, tween), count);
|
||||
dst.inc_by((tween, b), count);
|
||||
}
|
||||
}
|
||||
dst
|
||||
}
|
||||
|
||||
|
||||
fn score(pairs: &Pairs) -> usize {
|
||||
// "score" is defined as the number of occurences of the most common
|
||||
// character minus the number of occurrences of the least common
|
||||
let mut firsts = Counter::new();
|
||||
let mut lasts = Counter::new();
|
||||
for (pair, count) in pairs.iter() {
|
||||
let (a, b) = *pair;
|
||||
firsts.inc_by(a, count);
|
||||
lasts.inc_by(b, count);
|
||||
}
|
||||
|
||||
// the count of a given character is the number of times it appears
|
||||
// in either first or last place of a pair, whichever is greater
|
||||
let mut counts = Counter::new();
|
||||
for (c, count) in firsts.iter().chain(lasts.iter()) {
|
||||
if count > counts.get(c) {
|
||||
counts.set(*c, count);
|
||||
}
|
||||
}
|
||||
|
||||
let max = counts.iter().map(|(_c, n)| n).max().unwrap();
|
||||
let min = counts.iter().map(|(_c, n)| n).min().unwrap();
|
||||
max - min
|
||||
}
|
||||
|
||||
|
||||
pub fn run(data: &str) -> eyre::Result<(usize, usize)> {
|
||||
let (mut pairs, rules) = load(data)?;
|
||||
|
||||
for _i in 0..10 {pairs = expand(&pairs, &rules);}
|
||||
let one = score(&pairs);
|
||||
|
||||
for _i in 0..30 {pairs = expand(&pairs, &rules);}
|
||||
let two = score(&pairs);
|
||||
|
||||
Ok((one, two))
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
use std::io::Read;
|
||||
use std::collections::VecDeque;
|
||||
use std::str::FromStr;
|
||||
use std::fs::File;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fs::File;
|
||||
use std::hash::Hash;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::str::FromStr;
|
||||
|
||||
use color_eyre::{eyre};
|
||||
use eyre::eyre;
|
||||
@ -264,3 +266,54 @@ impl<T: Display> Display for Vec2<T> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Counter<K> {
|
||||
data: HashMap<K, usize>
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<K> Counter<K>
|
||||
where K: Eq + Hash,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Counter {data: HashMap::<K, usize>::new()}
|
||||
}
|
||||
|
||||
pub fn inc(&mut self, key: K) {
|
||||
let v = self.data.entry(key).or_insert(0);
|
||||
*v += 1;
|
||||
}
|
||||
|
||||
pub fn inc_by(&mut self, key: K, increment: usize) {
|
||||
let v = self.data.entry(key).or_insert(0);
|
||||
*v += increment;
|
||||
}
|
||||
|
||||
pub fn dec(&mut self, key: K) {
|
||||
let v = self.data.entry(key).or_insert(0);
|
||||
if *v > 0 {
|
||||
*v -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dec_by(&mut self, key: K, decrement: usize) {
|
||||
let v = self.data.entry(key).or_insert(0);
|
||||
if *v >= decrement {
|
||||
*v -= decrement;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&mut self, key: &K) -> usize {
|
||||
*self.data.get(key).unwrap_or(&0)
|
||||
}
|
||||
|
||||
pub fn set(&mut self, key: K, value: usize) {
|
||||
self.data.insert(key, value);
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item =(&'_ K, usize)> {
|
||||
self.data.iter().map(|(k, v)| (k, *v))
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ use color_eyre::eyre;
|
||||
|
||||
mod lib;
|
||||
use lib::load;
|
||||
mod day13;
|
||||
mod day14;
|
||||
|
||||
|
||||
fn main() -> eyre::Result<()> {
|
||||
let data = load("data/13.txt")?;
|
||||
let data = load("data/14.txt")?;
|
||||
|
||||
let start = Instant::now();
|
||||
let (one, two) = day13::run(&data)?;
|
||||
let (one, two) = day14::run(&data)?;
|
||||
let (dur, unit) = format_ns(start.elapsed().as_nanos());
|
||||
|
||||
let precision = 2.0 - dur.log10().floor();
|
||||
|
Loading…
x
Reference in New Issue
Block a user