diff --git a/src/year_2023/day_12_hot_springs/common.rs b/src/year_2023/day_12_hot_springs/common.rs index a505f65..67740d4 100644 --- a/src/year_2023/day_12_hot_springs/common.rs +++ b/src/year_2023/day_12_hot_springs/common.rs @@ -1,6 +1,6 @@ -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Clone, Copy, Hash, Eq)] pub enum Spring { - Operational, - Damaged, - Unknown, + O, + D, + U, } \ No newline at end of file diff --git a/src/year_2023/day_12_hot_springs/mod.rs b/src/year_2023/day_12_hot_springs/mod.rs index f0f5484..ba6532e 100644 --- a/src/year_2023/day_12_hot_springs/mod.rs +++ b/src/year_2023/day_12_hot_springs/mod.rs @@ -1,5 +1,5 @@ pub mod part_one; -// pub mod part_two; +pub mod part_two; pub mod common; use crate::utils::solution::Solution; @@ -19,7 +19,7 @@ impl Solution for DaySolution { } fn part_two(&self) -> String { - //input_reader::read_input_file(self.input_path(), part_two::part_two) - String::from("Not implemented") + input_reader::read_input_file(self.input_path(), part_two::part_two) + //String::from("Not implemented") } } \ No newline at end of file diff --git a/src/year_2023/day_12_hot_springs/part_one.rs b/src/year_2023/day_12_hot_springs/part_one.rs index efe5fe5..ef7c668 100644 --- a/src/year_2023/day_12_hot_springs/part_one.rs +++ b/src/year_2023/day_12_hot_springs/part_one.rs @@ -31,9 +31,9 @@ fn parse_springs(line: String) -> Vec { for c in line.chars() { match c { - '.' => spring_line.push(Spring::Operational), - '#' => spring_line.push(Spring::Damaged), - _ => spring_line.push(Spring::Unknown), + '.' => spring_line.push(Spring::O), + '#' => spring_line.push(Spring::D), + _ => spring_line.push(Spring::U), } } @@ -54,13 +54,13 @@ fn validate(spring_line: Vec, values: Vec) -> usize { for i in 0..spring_line.len() { match spring_line[i] { - Spring::Operational => { + Spring::O => { if count > 0 { validation_vals.push(count); count = 0; } }, - Spring::Damaged => { + Spring::D => { count += 1; }, _ => { @@ -87,7 +87,7 @@ fn unknown_search(spring_line: Vec, values: Vec) -> usize { let mut res = 0; - let unknowns: Vec = spring_line.iter().enumerate().filter(|(_, x)| **x == Spring::Unknown).map(|(i, _)| i).collect(); + let unknowns: Vec = spring_line.iter().enumerate().filter(|(_, x)| **x == Spring::U).map(|(i, _)| i).collect(); let i = unknowns.first(); if i.is_none() { @@ -97,11 +97,11 @@ fn unknown_search(spring_line: Vec, values: Vec) -> usize { let i = i.unwrap(); let mut op_spring_line = spring_line.clone(); - op_spring_line[*i] = Spring::Operational; + op_spring_line[*i] = Spring::O; res += unknown_search(op_spring_line, values.clone()); let mut dmg_spring_line = spring_line.clone(); - dmg_spring_line[*i] = Spring::Damaged; + dmg_spring_line[*i] = Spring::D; res += unknown_search(dmg_spring_line, values.clone()); diff --git a/src/year_2023/day_12_hot_springs/part_two.rs b/src/year_2023/day_12_hot_springs/part_two.rs new file mode 100644 index 0000000..a9ec777 --- /dev/null +++ b/src/year_2023/day_12_hot_springs/part_two.rs @@ -0,0 +1,131 @@ +use std::collections::HashMap; + +use super::common::Spring; + +pub fn part_two(input_lines: Vec) -> String { + + let mut springs: Vec> = Vec::new(); + let mut values: Vec> = Vec::new(); + + for line in input_lines { + + let split_line: Vec<&str> = line.split(' ').collect(); + + springs.push(parse_springs(split_line[0].to_string())); + values.push(parse_nums(split_line[1].to_string())); + } + + let mut res = 0; + let mut memory: HashMap<(Vec, Vec), usize> = HashMap::new(); + + for i in 0..springs.len() { + let search_spring = springs[i].clone(); + let val = search(search_spring, values[i].clone(), &mut memory); + res += val; + } + + res.to_string() +} + +fn parse_springs(line: String) -> Vec { + let mut spring_line: Vec = Vec::new(); + + for c in line.chars() { + match c { + '.' => spring_line.push(Spring::O), + '#' => spring_line.push(Spring::D), + _ => spring_line.push(Spring::U), + } + } + + let mut spring_res = >::new(); + + for i in 0..5 { + spring_res.extend_from_slice(&spring_line); + + if i != 4 { + spring_res.push(Spring::U); + } + } + + spring_res + // spring_line +} + +fn parse_nums(line: String) -> Vec { + let nums: Vec = line.split(',').map(|x| x.parse().unwrap()).collect(); + let mut res_nums: Vec = Vec::new(); + + for _ in 0..5 { + res_nums.extend_from_slice(&nums); + } + + res_nums + // nums +} + + +fn search(spring_line: Vec, groups: Vec, memory: &mut HashMap<(Vec, Vec), usize>) -> usize { + + if memory.contains_key(&(spring_line.clone(), groups.clone())) { + return memory[&(spring_line.clone(), groups.clone())]; + } + + let mut res = 0; + + if groups.len() == 0 { + let damaged: Vec = spring_line.iter().enumerate().filter(|(_, x)| **x == Spring::D).map(|(i, _)| i).collect(); + if damaged.is_empty(){ + return 1; + } + } else if !spring_line.is_empty() && spring_line.len() >= groups[0] { + + match spring_line[0] { + Spring::O => { + res += search(spring_line[1..].to_vec(), groups.clone(), memory); + }, + Spring::D => { + let group = groups[0]; + + let mut spring_group = spring_line[0..group].to_vec(); + + for i in 0..group { + if spring_group[i] == Spring::U { + spring_group[i] = Spring::D; + } + } + + let operational: Vec = spring_group.iter().enumerate().filter(|(_, x)| **x == Spring::O).map(|(i, _)| i).collect(); + if operational.len() == 0 { + if spring_line.len() == group { + if groups.len() == 1 { + return 1; + } + } else { + if spring_line[group] == Spring::O || spring_line[group] == Spring::U { + res += search(spring_line[group+1..].to_vec(), groups[1..].to_vec(), memory); + } + } + } + } + _ => { + let mut val; + + let mut op_clone = spring_line.clone(); + op_clone[0] = Spring::O; + let op_groups = groups.clone(); + val = search(op_clone, op_groups, memory); + res += val; + + let mut dmg_clone = spring_line.clone(); + dmg_clone[0] = Spring::D; + let dmg_groups = groups.clone(); + val = search(dmg_clone, dmg_groups, memory); + res += val; + } + } + } + + memory.insert((spring_line.clone(), groups.clone()), res); + res +} \ No newline at end of file