Advertisement
nairby

Day 14 Code

Dec 14th, 2021 (edited)
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 3.49 KB | None | 0 0
  1. use std::env;
  2. use std::io::{self};
  3. use std::collections::HashMap;
  4.  
  5. extern crate regex;
  6. use regex::Regex;
  7.  
  8. extern crate itertools;
  9. use itertools::Itertools;
  10.  
  11. const PART1_STEPS: usize = 10;
  12. const PART2_STEPS: usize = 40;
  13. const DEBUG: bool = false;
  14.  
  15. // Part 1 (naive solution)
  16. fn part1(poly: &String, rules: &HashMap<(char,char),char>) -> usize {
  17.     let mut poly = poly.to_string();
  18.     let mut diff = 0;
  19.     for step in 0..PART1_STEPS {
  20.         if DEBUG { println!("After step {}: {}", &step, &poly); }
  21.        
  22.         // Build new polymer
  23.         let mut poly_new = String::new();
  24.         for (l,r) in poly.chars().tuple_windows() {
  25.             let rule = rules.get(&(l,r)).unwrap();
  26.             poly_new.push_str(&format!("{}{}",l,rule));
  27.         }
  28.         poly_new.push_str(&format!("{}",poly.chars().last().unwrap()));
  29.         poly = poly_new.clone();
  30.  
  31.         // Calculate metric
  32.         let mut char_counts: HashMap<char,usize> = HashMap::new();
  33.         for ch in poly_new.chars() {
  34.             *char_counts.entry(ch).or_insert(0) += 1;
  35.         }
  36.         let most = char_counts.iter().map(|(_,v)| v).max().unwrap();
  37.         let least = char_counts.iter().map(|(_,v)| v).min().unwrap();
  38.         diff = most - least;
  39.     }
  40.     diff
  41. }
  42.  
  43. // Part 2 (character counting)
  44. fn part2(poly: &str, rules: &HashMap<(char,char),char>) -> usize {
  45.  
  46.     // Build initial counts of each letter and pair of letters
  47.     let mut pair_counts: HashMap<(char,char),usize> = HashMap::new();
  48.     let mut char_counts: HashMap<char,usize> = HashMap::new();
  49.     for (l,r) in poly.chars().tuple_windows() {
  50.         *pair_counts.entry((l,r)).or_insert(0) += 1;
  51.     }
  52.     for ch in poly.chars() {
  53.         *char_counts.entry(ch).or_insert(0) += 1;
  54.     }
  55.  
  56.     // Fold polymer
  57.     for _ in 0..PART2_STEPS {
  58.         let pairs_before = pair_counts.clone();
  59.         pair_counts.clear();
  60.         for (pair,count) in pairs_before.iter() {
  61.             let insert = rules.get(&pair).unwrap();
  62.             char_counts.entry(*insert).and_modify(|e| *e += count).or_insert(*count);
  63.             pair_counts.entry((pair.0,*insert)).and_modify(|e| *e += count).or_insert(*count);
  64.             pair_counts.entry((*insert,pair.1)).and_modify(|e| *e += count).or_insert(*count);
  65.         }
  66.     }
  67.     let most = char_counts.iter().map(|(_,v)| v).max().unwrap();
  68.     let least = char_counts.iter().map(|(_,v)| v).min().unwrap();
  69.     most - least
  70. }
  71.  
  72. fn solve(input: &str) -> io::Result<()> {
  73.     // Input
  74.     let input_str = std::fs::read_to_string(input).unwrap();
  75.     let input_str = input_str.trim();
  76.     let input: Vec<_> = input_str.split("\n\n").collect();
  77.  
  78.     // Initial polymer
  79.     let poly = input[0].to_string();
  80.  
  81.     // Rules input
  82.     let re = Regex::new(r"(\w)(\w) -> (\w)").unwrap();
  83.     let rules: HashMap<(char,char),char> = input[1].split("\n")
  84.         .map(|line| {
  85.             let matches = re.captures(line).unwrap();
  86.             let left   = matches[1].chars().next().unwrap();
  87.             let right  = matches[2].chars().next().unwrap();
  88.             let insert = matches[3].chars().next().unwrap();
  89.             ((left,right),insert)
  90.         })
  91.         .collect();
  92.  
  93.     // Answers
  94.     let part1 = part1(&poly, &rules);
  95.     let part2 = part2(&poly, &rules);
  96.     println!("Part 1: {}", part1); // 2194
  97.     println!("Part 2: {}", part2); // 2360298895777
  98.  
  99.     Ok(())
  100. }
  101.  
  102. fn main() {
  103.     let args: Vec<String> = env::args().collect();
  104.     let filename = &args[1];
  105.     solve(&filename).unwrap();
  106. }
  107.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement