aoc-2023/day_12/part_2/src/main.rs
2023-12-13 09:50:27 +01:00

72 lines
3 KiB
Rust

use std::collections::HashMap;
use regex::Regex;
fn cache_key(cur: &String, instructions: &Vec<i32>) -> String {
return format!("{}:{:?}", cur, instructions);
}
// this approach is entirely stolen from github, i just rewrote it in rust
// i'm not in a state to make my braincells operate at the level required for this task
// was enough of a challenge to even get this to work at all because rust is a fucking nuisance with basic tasks
// https://github.com/jsgrosman/advent-code-challenges/blob/main/advent2023/advent12.ts <3
fn count_valid(in_str: &String, instructions: &Vec<i32>, cache: &mut HashMap<String, i64>) -> i64 {
if cache.contains_key(&cache_key(&in_str, &instructions)) {
return *cache.get(&cache_key(&in_str, &instructions)).unwrap();
}
let cur = Regex::new("(^\\.+)|(\\.+$)").unwrap().replace_all(&in_str, "");
let index_q = cur.chars().position(|c| c == '?');
let index_dot = cur.chars().position(|c| c == '.');
let index_hash = cur.chars().position(|c| c == '#');
if instructions.len() == 0 && index_q.is_none() && index_hash.is_none() {
return 1;
} else if instructions.len() == 0 && (index_q.unwrap_or(0) > 0 || index_hash.unwrap_or(0) > 0) {
return 0;
}
if index_q.unwrap_or(cur.len()) < index_dot.unwrap_or(cur.len()) {
let with_hash = cur.replacen("?", "#", 1);
let with_dot = cur.replacen("?", ".", 1);
let val_with_hash = count_valid(&with_hash, instructions, cache);
let val_with_dot = count_valid(&with_dot, instructions, cache);
cache.insert(cache_key(&with_hash, &instructions), val_with_hash);
cache.insert(cache_key(&with_dot, &instructions), val_with_dot);
return val_with_hash + val_with_dot;
} else {
if instructions.len() > 0 && index_dot.unwrap_or(cur.len()) == *instructions.first().unwrap() as usize {
let next_pos = index_dot.unwrap_or(cur.len()) + 1;
return count_valid(&cur.chars().skip(next_pos).collect::<String>(), &instructions[1..].to_vec(), cache);
} else {
return 0;
}
}
}
fn main() {
let input = include_str!("../../input.txt").lines();
let mut result: i64 = 0;
for line in input {
let mut cache: HashMap<String, i64> = HashMap::new();
// i fucking hate rusts lifetime garbage fuck this ownership garbage what is this
let mut parts = line.split(" ");
let field_in = parts.next().unwrap();
let field = format!("{field_in}?{field_in}?{field_in}?{field_in}?{field_in}");
let instructions_in = parts.next().unwrap();
let instructions_str = format!("{instructions_in},{instructions_in},{instructions_in},{instructions_in},{instructions_in}");
let instructions = instructions_str.split(",").map(|i| i.parse::<i32>().unwrap()).collect::<Vec<i32>>();
let res = count_valid(&field, &instructions, &mut cache);
println!("{res} - {field}");
result += res;
}
println!("Result: {result}");
}