diff --git a/data/examples/15-2.txt b/data/examples/15-2.txt new file mode 100644 index 0000000..8163605 --- /dev/null +++ b/data/examples/15-2.txt @@ -0,0 +1,10 @@ +######## +#..O.O.# +##@.O..# +#...O..# +#.#.O..# +#...O..# +#......# +######## + +<^^>>>vv>v<< diff --git a/data/examples/15.txt b/data/examples/15.txt new file mode 100644 index 0000000..84cf1fb --- /dev/null +++ b/data/examples/15.txt @@ -0,0 +1,21 @@ +########## +#..O..O.O# +#......O.# +#.OO..O.O# +#..O@..O.# +#O#..O...# +#O..O..O.# +#.OO.O.OO# +#....O...# +########## + +^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^ +vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv< +<>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^ +^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^>< +^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^ +<><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<> +^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<>< +v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^ diff --git a/data/examples/16.txt b/data/examples/16.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/bin/15.rs b/src/bin/15.rs new file mode 100644 index 0000000..9af951f --- /dev/null +++ b/src/bin/15.rs @@ -0,0 +1,129 @@ +use itertools::Itertools; + +advent_of_code::solution!(15); + +#[derive(Debug)] +#[derive(PartialEq)] +enum TileObject { + Empty, + Wall, + Robot, + Box +} + +fn get_tile_object(c: char) -> TileObject { + match c { + '.' => TileObject::Empty, + '#' => TileObject::Wall, + '@' => TileObject::Robot, + 'O' => TileObject::Box, + _ => panic!() + } +} + +fn get_direction(c: char) -> (isize, isize) { + match c { + '^' => (-1, 0), + 'v' => (1, 0), + '<' => (0, -1), + '>' => (0, 1), + _ => panic!() + } +} + +pub fn part_one(input: &str) -> Option { + + let mut i = input.lines(); + let mut grid = i.by_ref().take_while(|l| !l.is_empty()).map(|l| l.chars().map(|c| get_tile_object(c)).collect_vec()).collect_vec(); + + let moves = i.by_ref().flat_map(|l| { + l.chars().map(|c| get_direction(c)).collect_vec() + }); + + let mut robot_pos = grid.iter().enumerate().find_map(|(row_idx, row)| { + row.iter().enumerate().find_map(|(col_idx, t)| if *t == TileObject::Robot { Some((row_idx, col_idx)) } else { None }) + }).unwrap(); + + grid[robot_pos.0 as usize][robot_pos.1 as usize] = TileObject::Empty; + + // println!("GRID ({}, {})", grid_height, grid_width); + // println!("ROBOT ({}, {})", robot_pos.0, robot_pos.1); + + for m in moves { + let new_row = (robot_pos.0 as isize + m.0) as usize; + let new_col = (robot_pos.1 as isize + m.1) as usize; + let next_pos = &grid[new_row][new_col]; + + match next_pos { + TileObject::Empty => { + robot_pos = (new_row, new_col); + // print!("M"); + }, + TileObject:: Box => { + if let Some(next_open_space) = get_next_open_space(&grid, robot_pos, m) { + grid[new_row][new_col] = TileObject::Empty; + grid[next_open_space.0][next_open_space.1] = TileObject::Box; + + robot_pos = (new_row, new_col); + // print!("~"); + } else { + // print!("!"); + } + }, + _ => { + // print!("!"); + } + } + } + + let calc_score = |row_idx, col_idx| 100 * row_idx + col_idx; + + let gps_score = grid.iter().enumerate().fold(0, |total, (row_idx, row)| { + total + row.iter().enumerate().fold(0, |sub_total, (col_idx, tile)| { + sub_total + if *tile == TileObject::Box { calc_score(row_idx, col_idx) } else { 0 } + }) + }); + + + Some(gps_score as u32) +} + +pub fn part_two(_input: &str) -> Option { + None +} + +fn get_next_open_space(grid: &[Vec], pos: (usize, usize), m: (isize, isize)) -> Option<(usize, usize)> { + let new_row = (pos.0 as isize + m.0) as usize; + let new_col = (pos.1 as isize + m.1) as usize; + let tile = &grid[new_row][new_col]; + + match tile { + TileObject::Empty => Some((new_row, new_col)), + TileObject::Box => get_next_open_space(grid, (new_row, new_col), m), + _ => None + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(10092)); + } + + #[test] + fn test_part_one_2() { + let result = part_one(&advent_of_code::template::read_file_part("examples", DAY, 2)); + assert_eq!(result, Some(2028)); + } + + #[ignore] + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, None); + } +} diff --git a/src/bin/16.rs b/src/bin/16.rs new file mode 100644 index 0000000..8bad048 --- /dev/null +++ b/src/bin/16.rs @@ -0,0 +1,26 @@ +advent_of_code::solution!(16); + +pub fn part_one(input: &str) -> Option { + None +} + +pub fn part_two(input: &str) -> Option { + None +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, None); + } + + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, None); + } +}