Pretty much there with Day 12... just need an eternity to let it run :)

This commit is contained in:
Luke Else 2023-12-12 21:02:08 +00:00
parent 4082df6be8
commit 23b27a2a8a
5 changed files with 1073 additions and 9 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
???.### 1,1,3
.??..??...?##. 1,1,3
?#?#?#?#?#?#?#? 1,3,1,6
????.#...#... 4,1,1
????.######..#####. 1,6,5
?###???????? 3,2,1

View File

@ -0,0 +1,6 @@
???.### 1,1,3
.??..??...?##. 1,1,3
?#?#?#?#?#?#?#? 1,3,1,6
????.#...#... 4,1,1
????.######..#####. 1,6,5
?###???????? 3,2,1

View File

@ -19,7 +19,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
Box::new(day09::Day09 {}), Box::new(day09::Day09 {}),
Box::new(day10::Day10 {}), Box::new(day10::Day10 {}),
Box::new(day11::Day11 {}), Box::new(day11::Day11 {}),
// Box::new(day12::Day12 {}), Box::new(day12::Day12 {}),
// Box::new(day13::Day13 {}), // Box::new(day13::Day13 {}),
// Box::new(day14::Day14 {}), // Box::new(day14::Day14 {}),
// Box::new(day15::Day15 {}), // Box::new(day15::Day15 {}),

View File

@ -5,16 +5,47 @@ pub struct Day12 {}
impl Solution for Day12 { impl Solution for Day12 {
fn part1( fn part1(
&self, &self,
_input: &mut Vec<String>, input: &mut Vec<String>,
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> { ) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
Ok(Box::new("Ready")) let mut ans = 0usize;
for s in input {
let springs = s.split_whitespace().nth(0).unwrap().to_owned();
let nums = s
.split_whitespace()
.nth(1)
.unwrap()
.split(',')
.map(|n| n.parse::<usize>().unwrap())
.collect::<Vec<_>>();
ans += self.solve(&springs.as_bytes(), None, &nums);
}
Ok(Box::new(ans))
} }
fn part2( fn part2(
&self, &self,
_input: &mut Vec<String>, input: &mut Vec<String>,
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> { ) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
Ok(Box::new("Ready")) for l in input.iter_mut() {
let (s, n) = l.split_once(" ").unwrap();
*l = format!("{s}?{s}?{s}?{s}?{s} {n},{n},{n},{n},{n}\n");
}
let mut ans = 0usize;
for s in input {
let springs = s.split_whitespace().nth(0).unwrap().to_owned();
let nums = s
.split_whitespace()
.nth(1)
.unwrap()
.split(',')
.map(|n| n.parse::<usize>().unwrap())
.collect::<Vec<_>>();
ans += self.solve(&springs.as_bytes(), None, &nums);
}
Ok(Box::new(ans))
} }
fn get_day(&self) -> u8 { fn get_day(&self) -> u8 {
@ -22,7 +53,28 @@ impl Solution for Day12 {
} }
} }
impl Day12 {} impl Day12 {
/// recursively counts the number of permutations of spring we could get from
/// the splits specified in 'nums'
fn solve(&self, s: &[u8], in_group: Option<usize>, cons: &[usize]) -> usize {
if s.is_empty() {
return match in_group {
Some(n) if cons == &[n] => 1,
None if cons.is_empty() => 1,
_ => 0,
};
}
// Resursively match based on the whether we are in a block and/or we have spaces left to fill
match (s[0], in_group, cons) {
(b'.', None, _) | (b'?', None, []) => self.solve(&s[1..], None, cons),
(b'.' | b'?', Some(n), [e, ..]) if n == *e => self.solve(&s[1..], None, &cons[1..]),
(b'#' | b'?', Some(n), [e, ..]) if n < *e => self.solve(&s[1..], Some(n + 1), cons),
(b'#', None, [_, ..]) => self.solve(&s[1..], Some(1), cons),
(b'?', None, _) => self.solve(&s[1..], None, cons) + self.solve(&s[1..], Some(1), cons),
_ => 0,
}
}
}
/// Test from puzzle input /// Test from puzzle input
#[cfg(test)] #[cfg(test)]
@ -44,7 +96,7 @@ mod test {
.unwrap() .unwrap()
.to_string(); .to_string();
assert_eq!(answer, "Ready"); assert_eq!(answer, "21");
} }
#[test] #[test]
@ -61,6 +113,6 @@ mod test {
.unwrap() .unwrap()
.to_string(); .to_string();
assert_eq!(answer, "Ready"); assert_eq!(answer, "525152");
} }
} }