From 68fa0587fef7f0badd7b0a3d8660e6294777ea4d Mon Sep 17 00:00:00 2001 From: JonOfUs Date: Tue, 19 Dec 2023 23:09:03 +0100 Subject: [PATCH] d19 --- res/19/example | 17 ++++++ src/days/d19.rs | 157 ++++++++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 6 +- 3 files changed, 172 insertions(+), 8 deletions(-) diff --git a/res/19/example b/res/19/example index e69de29..a08746e 100644 --- a/res/19/example +++ b/res/19/example @@ -0,0 +1,17 @@ +px{a<2006:qkq,m>2090:A,rfg} +pv{a>1716:R,A} +lnx{m>1548:A,A} +rfg{s<537:gd,x>2440:R,A} +qs{s>3448:A,lnx} +qkq{x<1416:A,crn} +crn{x>2662:A,R} +in{s<1351:px,qqz} +qqz{s>2770:qs,m<1801:hdj,R} +gd{a>3333:R,R} +hdj{m>838:A,pv} + +{x=787,m=2655,a=1222,s=2876} +{x=1679,m=44,a=2067,s=496} +{x=2036,m=264,a=79,s=2244} +{x=2461,m=1339,a=466,s=291} +{x=2127,m=1623,a=2188,s=1013} \ No newline at end of file diff --git a/src/days/d19.rs b/src/days/d19.rs index f8328e2..8d8a379 100644 --- a/src/days/d19.rs +++ b/src/days/d19.rs @@ -1,16 +1,163 @@ -use std::fs; +use std::{collections::HashMap, fs}; + +use rayon::prelude::*; +use regex::Regex; pub fn solve() { - let path = "res/19/example"; + let path = "res/19/input"; - let mut _contents = fs::read_to_string(path).expect("I/O error, wrong path?"); + let contents = fs::read_to_string(path).expect("I/O error, wrong path?"); //let contents = BufReader::new(fs::File::open(path).expect("I/O error, wrong path?")); - let result: usize = 0; + let (rules, parts) = contents.split_once("\n\n").unwrap(); + + let rules: HashMap<&str, (Vec<(u8, bool, usize, String)>, String)> = rules + .lines() + .map(|line| { + let (name, rest) = line.split_once("{").unwrap(); + let rest = rest.replace("}", ""); + let mut rules: Vec<&str> = rest.split(",").collect(); + let default = String::from(rules.pop().unwrap()); + let rules: Vec<(u8, bool, usize, String)> = rules + .iter() + .map(|rule| { + let re = Regex::new( + r"^(?P[a-z])(?P[><])(?P\d+):(?P[a-zA-Z]+)$", + ) + .unwrap(); + let captures = re.captures(rule).unwrap(); + let var = captures["var"].to_string(); + let op = captures["op"].to_string(); + let num = captures["num"].parse::().unwrap(); + let target = captures["target"].to_string(); + let var = match var.as_ref() { + "x" => 0, + "m" => 1, + "a" => 2, + _ => 3, + }; + (var, op == String::from(">"), num, target) + }) + .collect(); + (name, (rules, default)) + }) + .collect(); + + let parts: Vec<[usize; 4]> = parts + .lines() + .map(|line| { + let (x, m, a, s) = scan_fmt!( + line, + "{{x={d},m={d},a={d},s={d}}}", + usize, + usize, + usize, + usize + ) + .unwrap(); + [x, m, a, s] + }) + .collect(); + + let result: usize = parts + .par_iter() + .map(|part| { + let mut curr = "in"; + while curr != "A" && curr != "R" { + let rule = &rules[&curr]; + let mut applied = false; + rule.0.iter().for_each(|r| { + if applied { + return; + } + match r.1 { + false => { + // < + if part[r.0 as usize] < r.2 { + curr = r.3.as_ref(); + applied = true; + } + } + true => { + // > + if part[r.0 as usize] > r.2 { + curr = r.3.as_ref(); + applied = true; + } + } + } + }); + + if !applied { + curr = rule.1.as_ref() + } + } + if curr == "A" { + return part.iter().sum(); + } + 0 + }) + .sum(); println!("Result 1: {result}"); - let result: usize = 0; + //let mut ranges: HashMap<&str, Vec<(&str, [(usize,usize);4])>> = HashMap::new(); + let mut ranges: Vec<(&str, [(usize, usize); 4])> = vec![("in", [(1, 4000); 4])]; + let mut accept: Vec<[(usize, usize); 4]> = vec![]; + + while !ranges.is_empty() { + let (curr, mut vals) = ranges.pop().unwrap(); + + if curr == "A" { + accept.push(vals); + continue; + } + if curr == "R" { + continue; + } + + let rule = &rules[&curr]; + rule.0.iter().for_each(|r| { + if vals[r.0 as usize] == (0, 0) { + return; + } + match r.1 { + false => { + // < + if vals[r.0 as usize].0 < r.2 { + let mut new_ranges = vals.clone(); + new_ranges[r.0 as usize].1 = vals[r.0 as usize].1.min(r.2 - 1); + ranges.push((r.3.as_ref(), new_ranges)); + if vals[r.0 as usize].1 < r.2 { + vals[r.0 as usize] = (0, 0) + } else { + vals[r.0 as usize].0 = r.2 + } + } + } + true => { + // > + if vals[r.0 as usize].1 > r.2 { + let mut new_ranges = vals.clone(); + new_ranges[r.0 as usize].0 = vals[r.0 as usize].0.max(r.2 + 1); + ranges.push((r.3.as_ref(), new_ranges)); + if vals[r.0 as usize].0 > r.2 { + vals[r.0 as usize] = (0, 0) + } else { + vals[r.0 as usize].1 = r.2 + } + } + } + } + }); + if vals.iter().any(|p| *p != (0, 0)) { + ranges.push((rule.1.as_ref(), vals)) + } + } + let result: usize = accept + .iter() + .map(|vals| vals.iter().map(|(l, u)| *u - *l + 1).product::()) + .sum(); println!("Result 2: {result}"); } diff --git a/src/main.rs b/src/main.rs index 4d2a7ed..ad48b01 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,8 +5,8 @@ extern crate scan_fmt; use std::time::Instant; fn main() { - days::d17::solve() - //_all_days() + //days::d19::solve() + _all_days() } #[allow(unreachable_code, unused)] @@ -85,11 +85,11 @@ fn _all_days() { days::d18::solve(); time = _print_elapsed(time); - /* println!("\nDay 19"); days::d19::solve(); time = _print_elapsed(time); + /* println!("\nDay 20"); days::d20::solve(); time = _print_elapsed(time);