This commit is contained in:
Joseph Montanaro 2021-12-29 13:51:59 -08:00
parent 0f6f5cfc76
commit 33e9af89be
3 changed files with 141 additions and 5 deletions

83
2021/src/day14.rs Normal file
View 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))
}

View File

@ -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))
}
}

View File

@ -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();