generated from janezicmatej/aoc-template
solution: day 12
This commit is contained in:
parent
000002301f
commit
0000024016
|
@ -0,0 +1,6 @@
|
||||||
|
???.### 1,1,3
|
||||||
|
.??..??...?##. 1,1,3
|
||||||
|
?#?#?#?#?#?#?#? 1,3,1,6
|
||||||
|
????.#...#... 4,1,1
|
||||||
|
????.######..#####. 1,6,5
|
||||||
|
?###???????? 3,2,1
|
|
@ -0,0 +1,114 @@
|
||||||
|
use std::{collections::HashMap, iter::once};
|
||||||
|
|
||||||
|
fn is_valid(sequence: &[char], ptr: usize, group: usize) -> bool {
|
||||||
|
let edges_front = *once(&'.').chain(sequence.iter()).nth(ptr).unwrap() != '#';
|
||||||
|
let edges_back = *sequence.iter().chain(once(&'.')).nth(ptr + group).unwrap() != '#';
|
||||||
|
|
||||||
|
let filled = sequence
|
||||||
|
.iter()
|
||||||
|
.chain(once(&'.').cycle())
|
||||||
|
.skip(ptr)
|
||||||
|
.take(group)
|
||||||
|
.all(|x| *x != '.');
|
||||||
|
|
||||||
|
edges_front && edges_back && filled
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count(
|
||||||
|
memo: &mut HashMap<(usize, usize), usize>,
|
||||||
|
sequence: &[char],
|
||||||
|
groups: &[usize],
|
||||||
|
ptr: usize,
|
||||||
|
) -> usize {
|
||||||
|
match groups.split_first() {
|
||||||
|
None => !sequence.iter().skip(ptr).any(|c| *c == '#') as usize,
|
||||||
|
Some((group, r_groups)) => {
|
||||||
|
let remaining = r_groups.iter().sum();
|
||||||
|
let mut total = 0;
|
||||||
|
|
||||||
|
for idx in ptr..(sequence.len() - group - remaining + 1) {
|
||||||
|
if is_valid(sequence, idx, *group) {
|
||||||
|
let next = idx + *group + 1;
|
||||||
|
match memo.get(&(remaining, next)) {
|
||||||
|
Some(m) => total += m,
|
||||||
|
None => {
|
||||||
|
let count = count(memo, sequence, r_groups, next);
|
||||||
|
memo.insert((remaining, next), count);
|
||||||
|
total += count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sequence[idx] == '#' {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_line(line: &str) -> (Vec<char>, Vec<usize>) {
|
||||||
|
let (str_seq, str_grp) = line.split_once(' ').unwrap();
|
||||||
|
let sequence = str_seq.chars().collect();
|
||||||
|
let groups = str_grp.split(',').filter_map(|x| x.parse().ok()).collect();
|
||||||
|
|
||||||
|
(sequence, groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unfold(sequence: Vec<char>, groups: Vec<usize>, n: usize) -> (Vec<char>, Vec<usize>) {
|
||||||
|
let seq_len = sequence.len();
|
||||||
|
let grp_len = groups.len();
|
||||||
|
|
||||||
|
let new_sequence = sequence
|
||||||
|
.into_iter()
|
||||||
|
.chain(once('?'))
|
||||||
|
.cycle()
|
||||||
|
.take(seq_len * n + n - 1)
|
||||||
|
.collect();
|
||||||
|
let new_groups = groups.into_iter().cycle().take(grp_len * n).collect();
|
||||||
|
|
||||||
|
(new_sequence, new_groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_one(input: &str) -> Option<usize> {
|
||||||
|
Some(
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.map(parse_line)
|
||||||
|
.map(|(sequence, groups)| count(&mut HashMap::new(), &sequence, &groups, 0))
|
||||||
|
.sum(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_two(input: &str) -> Option<usize> {
|
||||||
|
Some(
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.map(parse_line)
|
||||||
|
.map(|(sequence, groups)| unfold(sequence, groups, 5))
|
||||||
|
.map(|(sequence, groups)| count(&mut HashMap::new(), &sequence, &groups, 0))
|
||||||
|
.sum(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
aoc::solution!(12);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_part_one() {
|
||||||
|
assert_eq!(
|
||||||
|
part_one(&aoc::template::read_file("examples", 12)),
|
||||||
|
Some(21)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_part_two() {
|
||||||
|
assert_eq!(
|
||||||
|
part_two(&aoc::template::read_file("examples", 12)),
|
||||||
|
Some(525152)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue