diff --git a/Cargo.toml b/Cargo.toml index c9d2842..0c61850 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,8 @@ path = "day14/part1.rs" [[bin]] name = "d14p2" path = "day14/part2.rs" + +[[bin]] +name = "d15p1" +path = "day15/part1.rs" + diff --git a/day15/part1.rs b/day15/part1.rs new file mode 100644 index 0000000..cfb9050 --- /dev/null +++ b/day15/part1.rs @@ -0,0 +1,153 @@ +#![feature(const_str_split_at)] + +#[derive(Debug, Clone, Copy, PartialEq)] +enum BlockType { + Wall, + Box, + Empty, + Robot +} + +#[derive(Debug, Clone, Copy)] +enum InstructionType { + Up, + Down, + Left, + Right +} + +const GRID_SIZE: usize = 50; +const INSTRUCTIONS_LENGTH: usize = 1000; +const INSTRUCTIONS_COUNT: usize = 20; + +const INPUT: (([[BlockType; GRID_SIZE]; GRID_SIZE], (usize, usize)), [InstructionType; INSTRUCTIONS_COUNT * INSTRUCTIONS_LENGTH]) = { + let split = include_str!("input.txt").split_at(GRID_SIZE * (GRID_SIZE + 1)); + let grid_str = split.0.trim_ascii().as_bytes(); + + let mut grid = [[BlockType::Empty; GRID_SIZE]; GRID_SIZE]; + let mut i = 0; + let mut newlines = 0; + let mut robot_pos = (0usize, 0usize); + while i < grid_str.len() { + if grid_str[i] == b'\n' { + newlines += 1; + i += 1; + continue; + }; + + let row = (i - newlines) / GRID_SIZE; + let col = i - newlines - (row * GRID_SIZE); + grid[row][col] = match grid_str[i] { + b'#' => BlockType::Wall, + b'O' => BlockType::Box, + b'.' => BlockType::Empty, + b'@' => { + robot_pos = (row, col); + BlockType::Robot + }, + _ => { + let mut tmp = [0u8; 4]; + let your_string = (grid_str[i] as char).encode_utf8(&mut tmp); + panic!("{}", your_string); + } + }; + + i += 1; + } + + let instructions_str = split.1.trim_ascii().as_bytes(); + let mut i = 0; + let mut newlines = 0; + let mut instructions = [InstructionType::Up; INSTRUCTIONS_COUNT * INSTRUCTIONS_LENGTH]; + while i < instructions_str.len() { + if instructions_str[i] == b'\n' { + newlines += 1; + i += 1; + continue; + } + + instructions[i - newlines] = match instructions_str[i] { + b'^' => InstructionType::Up, + b'v' => InstructionType::Down, + b'<' => InstructionType::Left, + b'>' => InstructionType::Right, + _ => { + let mut tmp = [0u8; 4]; + let your_string = (grid_str[i] as char).encode_utf8(&mut tmp); + panic!("{}", your_string); + } + }; + + i += 1; + } + + ((grid, robot_pos), instructions) +}; + +fn main() { + let ((mut grid, mut robot_pos), instructions) = INPUT; + + for instruction in instructions { + let mut next = match instruction { + InstructionType::Up => (robot_pos.0 - 1, robot_pos.1), + InstructionType::Down => (robot_pos.0 + 1, robot_pos.1), + InstructionType::Left => (robot_pos.0, robot_pos.1 - 1), + InstructionType::Right => (robot_pos.0, robot_pos.1 + 1) + }; + + match grid[next.0][next.1] { + // Can't do anything if next is a wall + BlockType::Wall => continue, + // If empty, shrimply move there + BlockType::Empty => { + grid[robot_pos.0][robot_pos.1] = BlockType::Empty; + grid[next.0][next.1] = BlockType::Robot; + robot_pos = next; + }, + // Wtf + BlockType::Robot => unreachable!(), + // Do box pusher logic + BlockType::Box => { + let original_box = next; + // Loop until we find a place to put the box + let mut failed = false; + loop { + next = match instruction { + InstructionType::Up => (next.0 - 1, next.1), + InstructionType::Down => (next.0 + 1, next.1), + InstructionType::Left => (next.0, next.1 - 1), + InstructionType::Right => (next.0, next.1 + 1) + }; + // Overflow impossible, breaks on wall + match grid[next.0][next.1] { + BlockType::Wall => { + failed = true; + break; + }, + BlockType::Box => continue, + BlockType::Empty => break, + BlockType::Robot => unreachable!(), + } + } + if !failed { + // Move robot to box location + grid[original_box.0][original_box.1] = BlockType::Robot; + grid[robot_pos.0][robot_pos.1] = BlockType::Empty; + robot_pos = original_box; + // Put box in empty slot + grid[next.0][next.1] = BlockType::Box; + } + }, + } + } + + let mut sum = 0_usize; + for row in 0..GRID_SIZE { + for col in 0..GRID_SIZE { + if grid[row][col] != BlockType::Box { continue } + sum += 100 * row + col; + } + } + + println!("Result: {sum}") +} \ No newline at end of file diff --git a/flake.lock b/flake.lock index c52050c..4eb9466 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1733759999, - "narHash": "sha256-463SNPWmz46iLzJKRzO3Q2b0Aurff3U1n0nYItxq7jU=", + "lastModified": 1734119587, + "narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a73246e2eef4c6ed172979932bc80e1404ba2d56", + "rev": "3566ab7246670a43abd2ffa913cc62dad9cdf7d5", "type": "github" }, "original": { @@ -62,11 +62,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1733884434, - "narHash": "sha256-8GXR9kC07dyOIshAyfZhG11xfvBRSZzYghnZ2weOKJU=", + "lastModified": 1734402816, + "narHash": "sha256-cgQ8mjUJz7J3fp97lnvl0dSJ6vLt8yzUSmw3B7QKw94=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "d0483df44ddf0fd1985f564abccbe568e020ddf2", + "rev": "e38fbd6e56e8cd1d61c65a21bbb7785e966707b4", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index a00c340..e72da03 100644 --- a/flake.nix +++ b/flake.nix @@ -19,6 +19,7 @@ extensions = [ "rust-src" "rustfmt" ]; targets = [ "x86_64-unknown-linux-gnu" ]; })) + evcxr ]; }; });