y2015d19 I should look at the input more
This commit is contained in:
parent
16ed2a8cae
commit
261a2e89c9
45
y2015/resources/19_input.txt
Normal file
45
y2015/resources/19_input.txt
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
Al => ThF
|
||||||
|
Al => ThRnFAr
|
||||||
|
B => BCa
|
||||||
|
B => TiB
|
||||||
|
B => TiRnFAr
|
||||||
|
Ca => CaCa
|
||||||
|
Ca => PB
|
||||||
|
Ca => PRnFAr
|
||||||
|
Ca => SiRnFYFAr
|
||||||
|
Ca => SiRnMgAr
|
||||||
|
Ca => SiTh
|
||||||
|
F => CaF
|
||||||
|
F => PMg
|
||||||
|
F => SiAl
|
||||||
|
H => CRnAlAr
|
||||||
|
H => CRnFYFYFAr
|
||||||
|
H => CRnFYMgAr
|
||||||
|
H => CRnMgYFAr
|
||||||
|
H => HCa
|
||||||
|
H => NRnFYFAr
|
||||||
|
H => NRnMgAr
|
||||||
|
H => NTh
|
||||||
|
H => OB
|
||||||
|
H => ORnFAr
|
||||||
|
Mg => BF
|
||||||
|
Mg => TiMg
|
||||||
|
N => CRnFAr
|
||||||
|
N => HSi
|
||||||
|
O => CRnFYFAr
|
||||||
|
O => CRnMgAr
|
||||||
|
O => HP
|
||||||
|
O => NRnFAr
|
||||||
|
O => OTi
|
||||||
|
P => CaP
|
||||||
|
P => PTi
|
||||||
|
P => SiRnFAr
|
||||||
|
Si => CaSi
|
||||||
|
Th => ThCa
|
||||||
|
Ti => BP
|
||||||
|
Ti => TiTi
|
||||||
|
e => HF
|
||||||
|
e => NAl
|
||||||
|
e => OMg
|
||||||
|
|
||||||
|
CRnCaSiRnBSiRnFArTiBPTiTiBFArPBCaSiThSiRnTiBPBPMgArCaSiRnTiMgArCaSiThCaSiRnFArRnSiRnFArTiTiBFArCaCaSiRnSiThCaCaSiRnMgArFYSiRnFYCaFArSiThCaSiThPBPTiMgArCaPRnSiAlArPBCaCaSiRnFYSiThCaRnFArArCaCaSiRnPBSiRnFArMgYCaCaCaCaSiThCaCaSiAlArCaCaSiRnPBSiAlArBCaCaCaCaSiThCaPBSiThPBPBCaSiRnFYFArSiThCaSiRnFArBCaCaSiRnFYFArSiThCaPBSiThCaSiRnPMgArRnFArPTiBCaPRnFArCaCaCaCaSiRnCaCaSiRnFYFArFArBCaSiThFArThSiThSiRnTiRnPMgArFArCaSiThCaPBCaSiRnBFArCaCaPRnCaCaPMgArSiRnFYFArCaSiThRnPBPMgAr
|
20
y2015/src/bin/d19.rs
Normal file
20
y2015/src/bin/d19.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use y2015::days::d19;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
part1();
|
||||||
|
part2();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1() {
|
||||||
|
let root = env!("CARGO_MANIFEST_DIR");
|
||||||
|
let content = fs::read_to_string(format!("{root}/resources/19_input.txt")).unwrap();
|
||||||
|
println!("{}", d19::process_part1(&content));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2() {
|
||||||
|
let root = env!("CARGO_MANIFEST_DIR");
|
||||||
|
let content = fs::read_to_string(format!("{root}/resources/19_input.txt")).unwrap();
|
||||||
|
println!("{}", d19::process_part2(&content));
|
||||||
|
}
|
110
y2015/src/days/d19.rs
Normal file
110
y2015/src/days/d19.rs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
pub fn process_part1(input: &str) -> u32 {
|
||||||
|
let (replacements_str, molecule) = input.split_once("\n\n").unwrap();
|
||||||
|
let mut replacements = Vec::new();
|
||||||
|
replacements_str.lines().for_each(|line| {
|
||||||
|
let (from, to) = line.split_once(" => ").unwrap();
|
||||||
|
replacements.push((from, to));
|
||||||
|
});
|
||||||
|
let mut possible = HashSet::new();
|
||||||
|
for (from, to) in replacements {
|
||||||
|
molecule.match_indices(from).for_each(|(idx, _)| {
|
||||||
|
let mut new_possible = molecule.to_string();
|
||||||
|
new_possible.replace_range(idx..(idx + from.len()), to);
|
||||||
|
possible.insert(new_possible);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
possible.len() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.reddit.com/r/adventofcode/comments/3xflz8/comment/cy4etju/
|
||||||
|
// broken test
|
||||||
|
//First insight
|
||||||
|
//
|
||||||
|
//There are only two types of productions:
|
||||||
|
//
|
||||||
|
// e => XX and X => XX (X is not Rn, Y, or Ar)
|
||||||
|
//
|
||||||
|
// X => X Rn X Ar | X Rn X Y X Ar | X Rn X Y X Y X Ar
|
||||||
|
//
|
||||||
|
//Second insight
|
||||||
|
//
|
||||||
|
//You can think of Rn Y Ar as the characters ( , ):
|
||||||
|
//
|
||||||
|
//X => X(X) | X(X,X) | X(X,X,X)
|
||||||
|
//
|
||||||
|
//Whenever there are two adjacent "elements" in your "molecule", you apply the first production. This reduces your molecule length by 1 each time.
|
||||||
|
//
|
||||||
|
//And whenever you have T(T) T(T,T) or T(T,T,T) (T is a literal token such as "Mg", i.e. not a nonterminal like "TiTiCaCa"), you apply the second production. This reduces your molecule length by 3, 5, or 7.
|
||||||
|
//Third insight
|
||||||
|
//
|
||||||
|
//Repeatedly applying X => XX until you arrive at a single token takes count(tokens) - 1 steps:
|
||||||
|
//
|
||||||
|
//ABCDE => XCDE => XDE => XE => X
|
||||||
|
//count("ABCDE") = 5
|
||||||
|
//5 - 1 = 4 steps
|
||||||
|
//
|
||||||
|
//Applying X => X(X) is similar to X => XX, except you get the () for free. This can be expressed as count(tokens) - count("(" or ")") - 1.
|
||||||
|
//
|
||||||
|
//A(B(C(D(E)))) => A(B(C(X))) => A(B(X)) => A(X) => X
|
||||||
|
//count("A(B(C(D(E))))") = 13
|
||||||
|
//count("(((())))") = 8
|
||||||
|
//13 - 8 - 1 = 4 steps
|
||||||
|
//
|
||||||
|
//You can generalize to X => X(X,X) by noting that each , reduces the length by two (,X). The new formula is count(tokens) - count("(" or ")") - 2*count(",") - 1.
|
||||||
|
//
|
||||||
|
//A(B(C,D),E(F,G)) => A(B(C,D),X) => A(X,X) => X
|
||||||
|
//count("A(B(C,D),E(F,G))") = 16
|
||||||
|
//count("(()())") = 6
|
||||||
|
//count(",,,") = 3
|
||||||
|
//16 - 6 - 2*3 - 1 = 3 steps
|
||||||
|
//
|
||||||
|
//This final formula works for all of the production types (for X => XX, the (,) counts are zero by definition.)
|
||||||
|
pub fn process_part2(input: &str) -> u32 {
|
||||||
|
let (_replacements_str, molecule) = input.split_once("\n\n").unwrap();
|
||||||
|
// An element is always at least an uppercase character and possibly an additional lowercase
|
||||||
|
// character
|
||||||
|
let total_elements = molecule.chars().filter(|char| char.is_uppercase()).count();
|
||||||
|
let num_rn = molecule.matches("Rn").count();
|
||||||
|
let num_ar = molecule.matches("Ar").count();
|
||||||
|
let num_y = molecule.matches("Y").count();
|
||||||
|
(total_elements - (num_rn + num_ar) - 2 * num_y - 1) as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT1: &str = "H => HO
|
||||||
|
H => OH
|
||||||
|
O => HH
|
||||||
|
e => H
|
||||||
|
e => O
|
||||||
|
|
||||||
|
HOH";
|
||||||
|
|
||||||
|
const INPUT2: &str = "H => HO
|
||||||
|
H => OH
|
||||||
|
O => HH
|
||||||
|
e => H
|
||||||
|
e => O
|
||||||
|
|
||||||
|
HOHOHO";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1() {
|
||||||
|
let result = process_part1(INPUT1);
|
||||||
|
assert_eq!(result, 4);
|
||||||
|
let result = process_part1(INPUT2);
|
||||||
|
assert_eq!(result, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2() {
|
||||||
|
let result = process_part2(INPUT1);
|
||||||
|
assert_eq!(result, 3);
|
||||||
|
let result = process_part2(INPUT2);
|
||||||
|
assert_eq!(result, 6);
|
||||||
|
}
|
||||||
|
}
|
@ -16,3 +16,5 @@ pub mod d6;
|
|||||||
pub mod d7;
|
pub mod d7;
|
||||||
pub mod d8;
|
pub mod d8;
|
||||||
pub mod d9;
|
pub mod d9;
|
||||||
|
|
||||||
|
pub mod d19;
|
||||||
|
Loading…
Reference in New Issue
Block a user