day 18, part 2 (complete solution)

main
Inga 🏳‍🌈 4 months ago
parent 4d772cb786
commit e16d9d99ca
  1. 0
      day18-hard/hard.in
  2. 67
      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; 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 { fn Coordinates(comptime CoordinateType: type) type {
return struct { return struct {
const Self = @This(); const Self = @This();
@ -184,7 +217,7 @@ const CellStatus = enum(u2) {
const TerrainCoordinate = u16; const TerrainCoordinate = u16;
const Terrain = GenericTerrain(TerrainCoordinate, 1024, 1024, CellStatus); const Terrain = GenericTerrain(TerrainCoordinate, 2048, 2048, CellStatus);
const TerrainCoordinates = Coordinates(TerrainCoordinate); const TerrainCoordinates = Coordinates(TerrainCoordinate);
@ -195,12 +228,14 @@ const Direction = enum(u8) {
Up = 3, Up = 3,
}; };
const RawCoordinate = u32;
const RawCommand = packed struct(u32) { const RawCommand = packed struct(u32) {
direction: Direction, direction: Direction,
length: u24, length: u24,
}; };
const RawCoordinates = Coordinates(u24); const RawCoordinates = Coordinates(RawCoordinate);
fn floodTerrain(terrain: *Terrain) void { fn floodTerrain(terrain: *Terrain) void {
var queue_mem: [65_536]TerrainCoordinates = undefined; var queue_mem: [65_536]TerrainCoordinates = undefined;
@ -238,7 +273,7 @@ fn floodTerrain(terrain: *Terrain) void {
} }
fn getTargetRawCoordinates(coordinates: RawCoordinates, command: RawCommand) RawCoordinates { fn getTargetRawCoordinates(coordinates: RawCoordinates, command: RawCommand) RawCoordinates {
return @TypeOf(coordinates){ return RawCoordinates{
.x = switch (command.direction) { .x = switch (command.direction) {
.Right => coordinates.x + command.length, .Right => coordinates.x + command.length,
.Left => 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 { fn getCoordinate(known_values: []const RawCoordinate, raw_coordinate: RawCoordinate) TerrainCoordinate {
const maybe_index = std.sort.binarySearch(u24, raw_coordinate, known_values, {}, Order(u24).order); const maybe_index = std.sort.binarySearch(RawCoordinate, raw_coordinate, known_values, {}, Order(RawCoordinate).order);
return @as(TerrainCoordinate, @intCast(maybe_index.?)); return @as(TerrainCoordinate, @intCast(maybe_index.?));
} }
@ -263,12 +298,12 @@ fn solveForCommands(raw_commands: []const RawCommand) usize {
.x = start_value, .x = start_value,
.y = 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(0);
known_values.addUnique(start_value - 1); known_values.addUnique(start_value - 1);
known_values.addUnique(start_value); known_values.addUnique(start_value);
known_values.addUnique(start_value + 1); 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| { for (raw_commands) |raw_command| {
raw_coordinates = getTargetRawCoordinates(raw_coordinates, raw_command); raw_coordinates = getTargetRawCoordinates(raw_coordinates, raw_command);
known_values.addUnique(raw_coordinates.x - 1); 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); 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(); var known_values_slice = known_values.getSlice();
@ -331,17 +366,19 @@ fn solveForCommands(raw_commands: []const RawCommand) usize {
fn parseCommand(command: []const u8) RawCommand { fn parseCommand(command: []const u8) RawCommand {
var index: usize = 2; var index: usize = 2;
const length = readNumber(u24, command, &index); _ = readNumber(u8, command, &index);
const direction: Direction = switch (command[0]) { index += 3;
'R' => .Right, const value = readHexNumber(u24, command, &index);
'L' => .Left, const direction: Direction = switch (value % 16) {
'U' => .Up, 0 => .Right,
'D' => .Down, 1 => .Down,
2 => .Left,
3 => .Up,
else => unreachable, else => unreachable,
}; };
return .{ return .{
.length = length, .length = value / 16,
.direction = direction, .direction = direction,
}; };
} }

Loading…
Cancel
Save