day12
This commit is contained in:
parent
39633cc659
commit
be7ca6666d
155
src/day12.rs
Normal file
155
src/day12.rs
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
|
#[aoc_generator(day12)]
|
||||||
|
fn parse(input: &str) -> Vec<(Vec<Condition>, Vec<usize>)> {
|
||||||
|
let input: Vec<(Vec<Condition>, Vec<usize>)> = input.split('\n')
|
||||||
|
.map(|line| {
|
||||||
|
line.split(' ')
|
||||||
|
.collect_tuple()
|
||||||
|
.unwrap()
|
||||||
|
}).map(|(springs, groups)| {
|
||||||
|
let springs: Vec<Condition> = springs.chars()
|
||||||
|
.map(|char| {
|
||||||
|
char.to_condition()
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
let groups: Vec<_> = groups.split(',')
|
||||||
|
.map(|num| num.parse::<usize>().expect("Failed to parse group len"))
|
||||||
|
.collect();
|
||||||
|
(springs, groups)
|
||||||
|
}).collect();
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn possible_count_cache(springs: &[Condition], groups: &[usize], cache: &mut HashMap<(usize, usize), usize>) -> usize {
|
||||||
|
if let Some(count) = cache.get(&(springs.len(), groups.len())) {
|
||||||
|
return *count;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
if groups.is_empty() {
|
||||||
|
count = if springs.contains(&Condition::Bad) { 0 } else { 1 };
|
||||||
|
cache.insert((springs.len(), groups.len()), count);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..springs.len() {
|
||||||
|
if springs[0..i].contains(&Condition::Bad) || i + groups[0] > springs.len() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if springs[i..i + groups[0]].contains(&Condition::Good) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if groups.len() == 1 {
|
||||||
|
if i + groups[0] == springs.len() {
|
||||||
|
count += 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
count += possible_count_cache(&springs[i + groups[0]..], &[], cache);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if i + groups[0] + 1 > springs.len() {
|
||||||
|
break;
|
||||||
|
} else if springs[i + groups[0]] == Condition::Bad {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
count += possible_count_cache(
|
||||||
|
&springs[i + groups[0] + 1..],
|
||||||
|
&groups[1..],
|
||||||
|
cache,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.insert((springs.len(), groups.len()), count);
|
||||||
|
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn possible_count(springs: &[Condition], groups: &[usize]) -> usize {
|
||||||
|
possible_count_cache(springs, groups, &mut HashMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day12, part1)]
|
||||||
|
fn part1(input: &Vec<(Vec<Condition>, Vec<usize>)>) -> usize {
|
||||||
|
input.iter()
|
||||||
|
.map(|(springs, groups)| possible_count(springs, groups))
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day12, part2)]
|
||||||
|
fn part2(input: &Vec<(Vec<Condition>, Vec<usize>)>) -> usize {
|
||||||
|
input.iter()
|
||||||
|
.map(|(springs, groups)| possible_count(
|
||||||
|
&[
|
||||||
|
&springs[..],
|
||||||
|
slice::from_ref(&Condition::WhoKnows),
|
||||||
|
&springs[..],
|
||||||
|
slice::from_ref(&Condition::WhoKnows),
|
||||||
|
&springs[..],
|
||||||
|
slice::from_ref(&Condition::WhoKnows),
|
||||||
|
&springs[..],
|
||||||
|
slice::from_ref(&Condition::WhoKnows),
|
||||||
|
&springs[..],
|
||||||
|
].concat(),
|
||||||
|
&[
|
||||||
|
&groups[..],
|
||||||
|
&groups[..],
|
||||||
|
&groups[..],
|
||||||
|
&groups[..],
|
||||||
|
&groups[..],
|
||||||
|
].concat()))
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
enum Condition {
|
||||||
|
Good,
|
||||||
|
Bad,
|
||||||
|
WhoKnows
|
||||||
|
}
|
||||||
|
|
||||||
|
trait ConditionConvertable {
|
||||||
|
fn to_condition(self) -> Condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConditionConvertable for char {
|
||||||
|
fn to_condition(self) -> Condition {
|
||||||
|
match self {
|
||||||
|
'.' => Condition::Good,
|
||||||
|
'#' => Condition::Bad,
|
||||||
|
'?' => Condition::WhoKnows,
|
||||||
|
_ => panic!("Invalid spring char AHHH")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const EX: &str = r"???.### 1,1,3
|
||||||
|
.??..??...?##. 1,1,3
|
||||||
|
?#?#?#?#?#?#?#? 1,3,1,6
|
||||||
|
????.#...#... 4,1,1
|
||||||
|
????.######..#####. 1,6,5
|
||||||
|
?###???????? 3,2,1";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_example() {
|
||||||
|
assert_eq!(part1(&parse(EX)), 21);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_example() {
|
||||||
|
assert_eq!(part2(&parse(EX)), 525152);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
mod day12;
|
||||||
mod day4;
|
mod day4;
|
||||||
mod day2;
|
mod day2;
|
||||||
mod day1;
|
mod day1;
|
||||||
|
Loading…
Reference in New Issue
Block a user