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;
}
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,
};
}

Loading…
Cancel
Save