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 day2;
|
||||
mod day1;
|
||||
|
Loading…
Reference in New Issue
Block a user