Compare commits
2 commits
441e41c30c
...
9d81739f2b
Author | SHA1 | Date | |
---|---|---|---|
Antoine Martin | 9d81739f2b | ||
Antoine Martin | 218d9d5298 |
102
aoc2021/input/day14.txt
Normal file
102
aoc2021/input/day14.txt
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
CKFFSCFSCBCKBPBCSPKP
|
||||||
|
|
||||||
|
NS -> P
|
||||||
|
KV -> B
|
||||||
|
FV -> S
|
||||||
|
BB -> V
|
||||||
|
CF -> O
|
||||||
|
CK -> N
|
||||||
|
BC -> B
|
||||||
|
PV -> N
|
||||||
|
KO -> C
|
||||||
|
CO -> O
|
||||||
|
HP -> P
|
||||||
|
HO -> P
|
||||||
|
OV -> O
|
||||||
|
VO -> C
|
||||||
|
SP -> P
|
||||||
|
BV -> H
|
||||||
|
CB -> F
|
||||||
|
SF -> H
|
||||||
|
ON -> O
|
||||||
|
KK -> V
|
||||||
|
HC -> N
|
||||||
|
FH -> P
|
||||||
|
OO -> P
|
||||||
|
VC -> F
|
||||||
|
VP -> N
|
||||||
|
FO -> F
|
||||||
|
CP -> C
|
||||||
|
SV -> S
|
||||||
|
PF -> O
|
||||||
|
OF -> H
|
||||||
|
BN -> V
|
||||||
|
SC -> V
|
||||||
|
SB -> O
|
||||||
|
NC -> P
|
||||||
|
CN -> K
|
||||||
|
BP -> O
|
||||||
|
PC -> H
|
||||||
|
PS -> C
|
||||||
|
NB -> K
|
||||||
|
VB -> P
|
||||||
|
HS -> V
|
||||||
|
BO -> K
|
||||||
|
NV -> B
|
||||||
|
PK -> K
|
||||||
|
SN -> H
|
||||||
|
OB -> C
|
||||||
|
BK -> S
|
||||||
|
KH -> P
|
||||||
|
BS -> S
|
||||||
|
HV -> O
|
||||||
|
FN -> F
|
||||||
|
FS -> N
|
||||||
|
FP -> F
|
||||||
|
PO -> B
|
||||||
|
NP -> O
|
||||||
|
FF -> H
|
||||||
|
PN -> K
|
||||||
|
HF -> H
|
||||||
|
VK -> K
|
||||||
|
NF -> K
|
||||||
|
PP -> H
|
||||||
|
PH -> B
|
||||||
|
SK -> P
|
||||||
|
HN -> B
|
||||||
|
VS -> V
|
||||||
|
VN -> N
|
||||||
|
KB -> O
|
||||||
|
KC -> O
|
||||||
|
KP -> C
|
||||||
|
OS -> O
|
||||||
|
SO -> O
|
||||||
|
VH -> C
|
||||||
|
OK -> B
|
||||||
|
HH -> B
|
||||||
|
OC -> P
|
||||||
|
CV -> N
|
||||||
|
SH -> O
|
||||||
|
HK -> N
|
||||||
|
NO -> F
|
||||||
|
VF -> S
|
||||||
|
NN -> O
|
||||||
|
FK -> V
|
||||||
|
HB -> O
|
||||||
|
SS -> O
|
||||||
|
FB -> B
|
||||||
|
KS -> O
|
||||||
|
CC -> S
|
||||||
|
KF -> V
|
||||||
|
VV -> S
|
||||||
|
OP -> H
|
||||||
|
KN -> F
|
||||||
|
CS -> H
|
||||||
|
CH -> P
|
||||||
|
BF -> F
|
||||||
|
NH -> O
|
||||||
|
NK -> C
|
||||||
|
OH -> C
|
||||||
|
BH -> O
|
||||||
|
FC -> V
|
||||||
|
PB -> B
|
18
aoc2021/input/day14_provided.txt
Normal file
18
aoc2021/input/day14_provided.txt
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
NNCB
|
||||||
|
|
||||||
|
CH -> B
|
||||||
|
HH -> N
|
||||||
|
CB -> H
|
||||||
|
NH -> C
|
||||||
|
HB -> C
|
||||||
|
HC -> B
|
||||||
|
HN -> C
|
||||||
|
NN -> C
|
||||||
|
BH -> H
|
||||||
|
NC -> B
|
||||||
|
NB -> B
|
||||||
|
BN -> B
|
||||||
|
BB -> N
|
||||||
|
BC -> B
|
||||||
|
CC -> N
|
||||||
|
CN -> C
|
174
aoc2021/src/day14.rs
Normal file
174
aoc2021/src/day14.rs
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
use std::collections::{HashMap, HashSet, LinkedList};
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
|
const INPUT: &str = include_str!("../input/day14.txt");
|
||||||
|
|
||||||
|
pub fn run() -> Result<String> {
|
||||||
|
let mut res = String::with_capacity(128);
|
||||||
|
|
||||||
|
writeln!(res, "part 1: {}", part1(INPUT)?)?;
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> Result<usize> {
|
||||||
|
let (polymer, rules) = input.split_once("\n\n").context("couldn't split input")?;
|
||||||
|
let mut polymer: Polymer = polymer.parse()?;
|
||||||
|
let rules: Rules = rules.parse()?;
|
||||||
|
|
||||||
|
let mut molecule_set = polymer.molecule_set();
|
||||||
|
rules.0.values().for_each(|v| {
|
||||||
|
molecule_set.insert(*v);
|
||||||
|
});
|
||||||
|
|
||||||
|
for _ in 0..10 {
|
||||||
|
polymer.insert_pairs(&rules.0)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let occurrences = polymer.compute_occurrences(&molecule_set);
|
||||||
|
|
||||||
|
let (_, least_common_occurrences) = occurrences
|
||||||
|
.iter()
|
||||||
|
.min_by_key(|(_, occurrences)| occurrences)
|
||||||
|
.unwrap();
|
||||||
|
let (_, most_common_occurrences) = occurrences
|
||||||
|
.iter()
|
||||||
|
.max_by_key(|(_, occurrences)| occurrences)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(most_common_occurrences - least_common_occurrences)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Rules(HashMap<(char, char), char>);
|
||||||
|
|
||||||
|
impl std::str::FromStr for Rules {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self> {
|
||||||
|
Ok(Self(
|
||||||
|
s.lines()
|
||||||
|
.map(str::trim)
|
||||||
|
.map(|l| {
|
||||||
|
let (pair, res) = l.split_once(" -> ").context("couldn't parse rule")?;
|
||||||
|
Ok((
|
||||||
|
(
|
||||||
|
pair.chars().next().context("")?,
|
||||||
|
pair.chars().nth(1).context("")?,
|
||||||
|
),
|
||||||
|
res.chars().next().context("couldn't parse rule")?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.collect::<Result<_>>()?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Polymer {
|
||||||
|
molecules: Option<LinkedList<char>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Polymer {
|
||||||
|
fn insert_pairs(&mut self, rules: &HashMap<(char, char), char>) -> Result<()> {
|
||||||
|
debug_assert!(self.molecules.is_some());
|
||||||
|
|
||||||
|
self.molecules = Some(insert_pairs(
|
||||||
|
std::mem::replace(&mut self.molecules, None).unwrap(),
|
||||||
|
rules,
|
||||||
|
)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_occurrences(&self, molecule_set: &HashSet<char>) -> Vec<(char, usize)> {
|
||||||
|
debug_assert!(self.molecules.is_some());
|
||||||
|
|
||||||
|
let mut res = Vec::new();
|
||||||
|
for molecule in molecule_set {
|
||||||
|
let count = self
|
||||||
|
.molecules
|
||||||
|
.as_ref()
|
||||||
|
.unwrap() // we always have a Some, Option only used for std::mem::replace
|
||||||
|
.iter()
|
||||||
|
.filter(|&m| m == molecule)
|
||||||
|
.count();
|
||||||
|
res.push((*molecule, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn molecule_set(&self) -> HashSet<char> {
|
||||||
|
debug_assert!(self.molecules.is_some());
|
||||||
|
|
||||||
|
self.molecules.as_ref().unwrap().iter().copied().collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for Polymer {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self> {
|
||||||
|
let molecules = s.trim().chars().collect();
|
||||||
|
|
||||||
|
Ok(Polymer {
|
||||||
|
molecules: Some(molecules),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_pairs(
|
||||||
|
molecules: LinkedList<char>,
|
||||||
|
rules: &HashMap<(char, char), char>,
|
||||||
|
) -> Result<LinkedList<char>> {
|
||||||
|
if molecules.len() <= 1 {
|
||||||
|
return Ok(molecules);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut head = molecules;
|
||||||
|
let mut tail = head.split_off(0);
|
||||||
|
|
||||||
|
while tail.len() > 1 {
|
||||||
|
// List length is at least 2
|
||||||
|
let mut iter = tail.iter();
|
||||||
|
let (left, right) = (*iter.next().unwrap(), *iter.next().unwrap());
|
||||||
|
|
||||||
|
let to_insert = *rules
|
||||||
|
.get(&(left, right))
|
||||||
|
.with_context(|| format!("couldn't find rule for pair ({}, {})", left, right))?;
|
||||||
|
|
||||||
|
// tail = left
|
||||||
|
// new_tail = right -> rest
|
||||||
|
let new_tail = tail.split_off(1);
|
||||||
|
|
||||||
|
// head = head -> left
|
||||||
|
head.append(&mut tail);
|
||||||
|
// head = head -> left -> to_insert
|
||||||
|
head.push_back(to_insert);
|
||||||
|
|
||||||
|
// tail = right -> rest
|
||||||
|
tail = new_tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
head.append(&mut tail);
|
||||||
|
|
||||||
|
Ok(head)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const PROVIDED: &str = include_str!("../input/day14_provided.txt");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_provided() {
|
||||||
|
assert_eq!(part1(PROVIDED).unwrap(), 1588);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_real() {
|
||||||
|
assert_eq!(part1(INPUT).unwrap(), 3247);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,3 +13,4 @@ pub mod day10;
|
||||||
pub mod day11;
|
pub mod day11;
|
||||||
pub mod day12;
|
pub mod day12;
|
||||||
pub mod day13;
|
pub mod day13;
|
||||||
|
pub mod day14;
|
||||||
|
|
|
@ -15,6 +15,7 @@ use aoc2021::day10;
|
||||||
use aoc2021::day11;
|
use aoc2021::day11;
|
||||||
use aoc2021::day12;
|
use aoc2021::day12;
|
||||||
use aoc2021::day13;
|
use aoc2021::day13;
|
||||||
|
use aoc2021::day14;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let days: &[DayFunc] = &[
|
let days: &[DayFunc] = &[
|
||||||
|
@ -31,6 +32,7 @@ fn main() -> Result<()> {
|
||||||
day11::run,
|
day11::run,
|
||||||
day12::run,
|
day12::run,
|
||||||
day13::run,
|
day13::run,
|
||||||
|
day14::run,
|
||||||
];
|
];
|
||||||
|
|
||||||
aoc::run(days)
|
aoc::run(days)
|
||||||
|
|
Loading…
Reference in a new issue