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::io::Read;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::str::FromStr;
|
use std::collections::HashMap;
|
||||||
use std::fs::File;
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::fs::File;
|
||||||
|
use std::hash::Hash;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use color_eyre::{eyre};
|
use color_eyre::{eyre};
|
||||||
use eyre::eyre;
|
use eyre::eyre;
|
||||||
@ -264,3 +266,54 @@ impl<T: Display> Display for Vec2<T> {
|
|||||||
Ok(())
|
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;
|
mod lib;
|
||||||
use lib::load;
|
use lib::load;
|
||||||
mod day13;
|
mod day14;
|
||||||
|
|
||||||
|
|
||||||
fn main() -> eyre::Result<()> {
|
fn main() -> eyre::Result<()> {
|
||||||
let data = load("data/13.txt")?;
|
let data = load("data/14.txt")?;
|
||||||
|
|
||||||
let start = Instant::now();
|
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 (dur, unit) = format_ns(start.elapsed().as_nanos());
|
||||||
|
|
||||||
let precision = 2.0 - dur.log10().floor();
|
let precision = 2.0 - dur.log10().floor();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user