diff --git a/day10/src/main.rs b/day10/src/main.rs index b077099..904b88b 100644 --- a/day10/src/main.rs +++ b/day10/src/main.rs @@ -1,35 +1,15 @@ -use std::collections::HashMap; +mod part2; fn main() { - let pipes = HashMap::from([ - ('|', (0, 1)), - ('-', (1, 0)), - ('L', (1, 1)), - ('J', (1, -1)), - ('7', (1, -1)), - ('F', (1, 1)), - ]); - let data = util::get_data_chars("data.txt"); - let (start, starting_directions) = find_starting_directions(&data, &pipes); + let (start, starting_direction) = find_starting_directions(&data); - let max = go_through_pipe(&data, start, &starting_directions); + let max = get_max_result(&data, start, &starting_direction); + let inside_count = part2::get_insides(&data, &start, &starting_direction); println!("## part 1 max: {}", max); -} - -fn go_through_pipe( - d: &Vec>, - start: (i32, i32), - starting_directions: &Vec<(i32, i32)>, -) -> i32 { - let results = starting_directions - .iter() - .map(|direction| get_max_result(&d, start, direction)) - .collect::>(); - - return *results.iter().max().unwrap(); + println!("## part 2 insides: {}", inside_count); } fn get_max_result(d: &Vec>, start: (i32, i32), direction: &(i32, i32)) -> i32 { @@ -119,11 +99,7 @@ fn get_max_result(d: &Vec>, start: (i32, i32), direction: &(i32, i32)) return count / 2; } -fn find_starting_directions( - d: &Vec>, - pipes: &HashMap, -) -> ((i32, i32), Vec<(i32, i32)>) { - let mut v = Vec::new(); +fn find_starting_directions(d: &Vec>) -> ((i32, i32), (i32, i32)) { let mut start: (i32, i32) = (-1, -1); for i in 0..d.len() { @@ -140,20 +116,23 @@ fn find_starting_directions( panic!("failed to find the starting position"); } + // find a possible start + let possible_starts = vec![ - (start.0 - 1, start.1), - (start.0, start.1 - 1), - (start.0 + 1, start.1), - (start.0, start.1 + 1), + ((start.0 - 1, start.1), vec!['|', '7', 'F']), + ((start.0, start.1 - 1), vec!['-', 'F', 'L']), + ((start.0, start.1 + 1), vec!['-', '7', 'J']), + ((start.0 + 1, start.1), vec!['|', 'J', 'L']), ]; for i in 0..possible_starts.len() { - let el = possible_starts[i]; + let pos = &possible_starts[i].0; + let signs = &possible_starts[i].1; - if el.0 >= 0 && el.1 >= 0 && pipes.contains_key(&d[el.0 as usize][el.1 as usize]) { - v.push(el); + if pos.0 >= 0 && pos.1 >= 0 && signs.contains(&d[pos.0 as usize][pos.1 as usize]) { + return (start, *pos); } } - return (start, v); + panic!("failed to find a starting position"); } diff --git a/day10/src/part2.rs b/day10/src/part2.rs new file mode 100644 index 0000000..3ed33c3 --- /dev/null +++ b/day10/src/part2.rs @@ -0,0 +1,125 @@ +pub fn get_insides(d: &Vec>, start: &(i32, i32), direction: &(i32, i32)) -> i32 { + let path = get_path(d, start, direction); + + // the other sign combined with those counts as 1 + let turns_chars = Vec::from(['J', 'L', '|']); + + let mut count = 0; + + for i in 0..d.len() { + let row = &d[i]; + + let mut pipes_count = 0; + + for j in 0..row.len() { + let c = if row[j] == 'S' { 'J' } else { row[j] }; + + let is_char_path = is_path((i, j), &path); + + if is_char_path && turns_chars.contains(&c) { + pipes_count += 1; + } else if !is_char_path && pipes_count % 2 != 0 { + count += 1; + } + } + } + + return count; +} + +fn get_path(d: &Vec>, start: &(i32, i32), direction: &(i32, i32)) -> Vec<(usize, usize)> { + let mut finished = false; + + let mut row = direction.0 as usize; + let mut col = direction.1 as usize; + + let mut prev_row = start.0 as usize; + let mut prev_col = start.1 as usize; + + let mut path = Vec::from([(prev_row, prev_col)]); + + while !finished { + let next_char = &d[row][col]; + + path.push((row, col)); + + if *next_char == 'S' { + finished = true; + } else { + let tmp_row = row; + let tmp_col = col; + + match *next_char { + '|' => { + if prev_row > row { + row -= 1; + } else { + row += 1; + } + } + '-' => { + if prev_col > col { + col -= 1; + } else { + col += 1; + } + } + 'L' => { + if prev_col > col { + row -= 1; + } else { + col += 1; + } + } + 'J' => { + if prev_col < col { + row -= 1; + } else { + col -= 1; + } + } + '7' => { + if prev_col < col { + row += 1; + } else { + col -= 1; + } + } + 'F' => { + if prev_col > col { + row += 1; + } else { + col += 1; + } + } + _ => { + println!("unexpected char: {}", next_char); + break; + } + }; + + prev_row = tmp_row; + prev_col = tmp_col; + } + } + + return path; +} + +fn is_path(pos: (usize, usize), path: &Vec<(usize, usize)>) -> bool { + for i in 0..path.len() { + let p = path[i]; + + if p.0 == pos.0 && p.1 == pos.1 { + return true; + } + } + + return false; +} + +fn print_path_row(path: &Vec<(usize, usize)>, row: usize) { + let r: Vec<&(usize, usize)> = path.iter().filter(|x| x.0 == row).collect(); + + println!("row path: {:?}", r); +}