Created
December 5, 2023 13:45
-
-
Save typester/c7099571facac2874bfb0f1604507c90 to your computer and use it in GitHub Desktop.
2023 Advent of Code Day 4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::HashMap; | |
use lazy_static::lazy_static; | |
use regex::Regex; | |
const INPUT: &str = "..snip.."; | |
fn main() { | |
let sum: u32 = INPUT.lines() | |
.map(parse_game) | |
.map(|card| { | |
let mut point = 0; | |
for wining_num in card.wining_numbers.iter() { | |
if let Some(_) = card.my_numbers.iter().find(|n| *n == wining_num) { | |
if point == 0 { | |
point = 1; | |
} else { | |
point *= 2; | |
} | |
} | |
} | |
point | |
}).sum(); | |
println!("part1: {}", sum); | |
let mut sum: u32 = 0; | |
let cards: Vec<Card> = INPUT.lines().map(parse_game).collect(); | |
let mut cache: HashMap<usize, u32> = HashMap::new(); | |
for i in 0..cards.len() { | |
sum += count_recurse(&cards, i, &mut cache); | |
} | |
println!("part2: {}", sum); | |
} | |
struct Card { | |
num: u32, | |
wining_numbers: Vec<u32>, | |
my_numbers: Vec<u32>, | |
} | |
impl Card { | |
fn matches(&self) -> u32 { | |
self.wining_numbers.iter().fold(0, |mut acc, w| { | |
if self.my_numbers.iter().find(|n| *n == w).is_some() { | |
acc += 1 | |
} | |
acc | |
}) | |
} | |
} | |
fn parse_game(s: &str) -> Card { | |
lazy_static! { | |
static ref RE_HEAD: Regex = Regex::new(r"(\d+)").unwrap(); | |
static ref RE_NUM: Regex = Regex::new(r"(\d+)").unwrap(); | |
} | |
let (info, numbers) = { | |
let mut iter = s.split(":"); | |
(iter.next().unwrap(), iter.next().unwrap()) | |
}; | |
let game = RE_HEAD.captures(info).unwrap()[1].parse::<u32>().unwrap(); | |
let (wining_numbers, my_numbers) = { | |
let mut iter = numbers.split("|"); | |
let wining_iter = RE_NUM.captures_iter(iter.next().unwrap()); | |
let mynum_iter = RE_NUM.captures_iter(iter.next().unwrap()); | |
let wining_numbers: Vec<u32> = wining_iter.map(|c| { | |
c.get(1).map(|m| m.as_str()).unwrap_or("0").parse::<u32>().unwrap() | |
}).collect(); | |
let my_numbers: Vec<u32> = mynum_iter.map(|c| { | |
c.get(1).map(|m| m.as_str()).unwrap_or("0").parse::<u32>().unwrap() | |
}).collect(); | |
(wining_numbers, my_numbers) | |
}; | |
Card { num: game, wining_numbers, my_numbers } | |
} | |
fn count_recurse(cards: &Vec<Card>, index: usize, cache: &mut HashMap<usize, u32>) -> u32 { | |
if let Some(cached) = cache.get(&index) { | |
return *cached; | |
} | |
if let Some(card) = cards.get(index) { | |
let mut sum: u32 = 1; | |
let matches = card.matches(); | |
if matches > 0 { | |
for n in 1..=matches { | |
sum += count_recurse(cards, index + (n as usize), cache); | |
} | |
} | |
cache.insert(index, sum); | |
return sum; | |
} | |
0 | |
} | |
#[cfg(test)] | |
mod tests { | |
use lazy_static::lazy_static; | |
use regex::Regex; | |
#[test] | |
fn test_re() { | |
lazy_static! { | |
static ref RE_NUM: Regex = Regex::new(r"(\d+)").unwrap(); | |
} | |
let input = "1 22 3"; | |
let mut iter = RE_NUM.captures_iter(input); | |
assert_eq!(iter.next().unwrap().get(1).map(|m| m.as_str()).unwrap_or("0").parse::<u32>().unwrap(), 1); | |
assert_eq!(iter.next().unwrap().get(1).map(|m| m.as_str()).unwrap_or("0").parse::<u32>().unwrap(), 22); | |
assert_eq!(iter.next().unwrap().get(1).map(|m| m.as_str()).unwrap_or("0").parse::<u32>().unwrap(), 3); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment