From e16d9d99cae5ff81b80948739a06507aed111b52 Mon Sep 17 00:00:00 2001 From: Inga Date: Sun, 7 Jan 2024 18:03:38 +0000 Subject: [PATCH] day 18, part 2 (complete solution) --- day18-hard/{easy.in => hard.in} | 0 day18-hard/src/main.zig | 67 +++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 15 deletions(-) rename day18-hard/{easy.in => hard.in} (100%) diff --git a/day18-hard/easy.in b/day18-hard/hard.in similarity index 100% rename from day18-hard/easy.in rename to day18-hard/hard.in diff --git a/day18-hard/src/main.zig b/day18-hard/src/main.zig index c2e4923..2a0a518 100644 --- a/day18-hard/src/main.zig +++ b/day18-hard/src/main.zig @@ -119,6 +119,39 @@ fn readNumber(comptime T: type, line: []const u8, index: *usize) T { return if (is_negative) (0 - result) else result; } +fn readHexNumber(comptime T: type, line: []const u8, index: *usize) T { + var result: T = 0; + while (index.* < line.len and line[index.*] == ' ') : (index.* += 1) {} + + var is_negative = false; + if (index.* < line.len and line[index.*] == '-') { + is_negative = true; + index.* += 1; + } + + std.debug.assert(index.* < line.len); + + while (index.* < line.len) : (index.* += 1) { + const char = line[index.*]; + switch (char) { + '0'...'9' => { + result = result * 16 + (char - '0'); + }, + 'a'...'f' => { + result = result * 16 + 10 + (char - 'a'); + }, + 'A'...'F' => { + result = result * 16 + 10 + (char - 'A'); + }, + else => { + break; + }, + } + } + + return if (is_negative) (0 - result) else result; +} + fn Coordinates(comptime CoordinateType: type) type { return struct { const Self = @This(); @@ -184,7 +217,7 @@ const CellStatus = enum(u2) { const TerrainCoordinate = u16; -const Terrain = GenericTerrain(TerrainCoordinate, 1024, 1024, CellStatus); +const Terrain = GenericTerrain(TerrainCoordinate, 2048, 2048, CellStatus); const TerrainCoordinates = Coordinates(TerrainCoordinate); @@ -195,12 +228,14 @@ const Direction = enum(u8) { Up = 3, }; +const RawCoordinate = u32; + const RawCommand = packed struct(u32) { direction: Direction, length: u24, }; -const RawCoordinates = Coordinates(u24); +const RawCoordinates = Coordinates(RawCoordinate); fn floodTerrain(terrain: *Terrain) void { var queue_mem: [65_536]TerrainCoordinates = undefined; @@ -238,7 +273,7 @@ fn floodTerrain(terrain: *Terrain) void { } fn getTargetRawCoordinates(coordinates: RawCoordinates, command: RawCommand) RawCoordinates { - return @TypeOf(coordinates){ + return RawCoordinates{ .x = switch (command.direction) { .Right => coordinates.x + command.length, .Left => coordinates.x - command.length, @@ -252,8 +287,8 @@ fn getTargetRawCoordinates(coordinates: RawCoordinates, command: RawCommand) Raw }; } -fn getCoordinate(known_values: []const u24, raw_coordinate: u24) TerrainCoordinate { - const maybe_index = std.sort.binarySearch(u24, raw_coordinate, known_values, {}, Order(u24).order); +fn getCoordinate(known_values: []const RawCoordinate, raw_coordinate: RawCoordinate) TerrainCoordinate { + const maybe_index = std.sort.binarySearch(RawCoordinate, raw_coordinate, known_values, {}, Order(RawCoordinate).order); return @as(TerrainCoordinate, @intCast(maybe_index.?)); } @@ -263,12 +298,12 @@ fn solveForCommands(raw_commands: []const RawCommand) usize { .x = start_value, .y = start_value, }; - var known_values = StackList(u24, u16, 2048).init(); + var known_values = StackList(RawCoordinate, u16, 2048).init(); known_values.addUnique(0); known_values.addUnique(start_value - 1); known_values.addUnique(start_value); known_values.addUnique(start_value + 1); - known_values.addUnique(std.math.maxInt(u24)); + known_values.addUnique(std.math.maxInt(RawCoordinate)); for (raw_commands) |raw_command| { raw_coordinates = getTargetRawCoordinates(raw_coordinates, raw_command); known_values.addUnique(raw_coordinates.x - 1); @@ -279,7 +314,7 @@ fn solveForCommands(raw_commands: []const RawCommand) usize { known_values.addUnique(raw_coordinates.y + 1); } - std.sort.heap(u24, known_values.getMutableSlice(), {}, std.sort.asc(u24)); + std.sort.heap(RawCoordinate, known_values.getMutableSlice(), {}, std.sort.asc(RawCoordinate)); var known_values_slice = known_values.getSlice(); @@ -331,17 +366,19 @@ fn solveForCommands(raw_commands: []const RawCommand) usize { fn parseCommand(command: []const u8) RawCommand { var index: usize = 2; - const length = readNumber(u24, command, &index); - const direction: Direction = switch (command[0]) { - 'R' => .Right, - 'L' => .Left, - 'U' => .Up, - 'D' => .Down, + _ = readNumber(u8, command, &index); + index += 3; + const value = readHexNumber(u24, command, &index); + const direction: Direction = switch (value % 16) { + 0 => .Right, + 1 => .Down, + 2 => .Left, + 3 => .Up, else => unreachable, }; return .{ - .length = length, + .length = value / 16, .direction = direction, }; }