You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
6.7 KiB
Zig
233 lines
6.7 KiB
Zig
const std = @import("std");
|
|
|
|
const Point = struct { row: i32, col: i32 };
|
|
const Direction = enum(usize) { up, right, down, left };
|
|
const Instruction = struct { direction: Direction, distance: usize };
|
|
|
|
pub fn main() !void {
|
|
var content = @embedFile("test.txt");
|
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
const allocator = gpa.allocator();
|
|
|
|
var path = std.AutoHashMap(Point, void).init(allocator);
|
|
defer path.deinit();
|
|
|
|
var instructions = std.ArrayList(Instruction).init(allocator);
|
|
defer instructions.deinit();
|
|
|
|
try parseInstructions(content, &instructions);
|
|
|
|
var minCol: i32 = 0;
|
|
var maxCol: i32 = 0;
|
|
var minRow: i32 = 0;
|
|
var maxRow: i32 = 0;
|
|
|
|
var row: i32 = 0;
|
|
var col: i32 = 0;
|
|
for (instructions.items) |ins| {
|
|
for (0..ins.distance) |_| {
|
|
try path.put(Point{ .row = row, .col = col }, {});
|
|
|
|
if (row > maxRow) {
|
|
maxRow = row;
|
|
}
|
|
if (row < minRow) {
|
|
minRow = row;
|
|
}
|
|
if (col > maxCol) {
|
|
maxCol = col;
|
|
}
|
|
if (col < minCol) {
|
|
minCol = col;
|
|
}
|
|
|
|
if (ins.direction == Direction.up) {
|
|
row -= 1;
|
|
} else if (ins.direction == Direction.right) {
|
|
col += 1;
|
|
} else if (ins.direction == Direction.down) {
|
|
row += 1;
|
|
} else {
|
|
col -= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
std.debug.print("min row:{d}, max row: {d}\n", .{ minRow, maxRow });
|
|
std.debug.print("min col:{d}, max col: {d}\n", .{ minCol, maxCol });
|
|
|
|
// guess at finding a spot inside
|
|
var inside = Point{ .row = @divFloor(maxRow - minRow, 2), .col = @divFloor(maxCol - minCol, 2) };
|
|
|
|
var filled = try path.clone();
|
|
defer filled.deinit();
|
|
|
|
std.debug.print("count pre: {d}\n", .{path.count()});
|
|
|
|
try fill(&filled, inside);
|
|
|
|
std.debug.print("count post: {d}\n", .{filled.count()});
|
|
|
|
// printGrid(filled);
|
|
|
|
// Part 2
|
|
var path2 = std.AutoHashMap(Point, void).init(allocator);
|
|
defer path2.deinit();
|
|
|
|
var instructions2 = std.ArrayList(Instruction).init(allocator);
|
|
defer instructions2.deinit();
|
|
|
|
try parseInstructions2(content, &instructions2);
|
|
|
|
minCol = 0;
|
|
maxCol = 0;
|
|
minRow = 0;
|
|
maxRow = 0;
|
|
|
|
row = 0;
|
|
col = 0;
|
|
for (instructions2.items) |ins| {
|
|
for (0..ins.distance) |_| {
|
|
try path2.put(Point{ .row = row, .col = col }, {});
|
|
|
|
if (row > maxRow) {
|
|
maxRow = row;
|
|
}
|
|
if (row < minRow) {
|
|
minRow = row;
|
|
}
|
|
if (col > maxCol) {
|
|
maxCol = col;
|
|
}
|
|
if (col < minCol) {
|
|
minCol = col;
|
|
}
|
|
|
|
if (ins.direction == Direction.up) {
|
|
row -= 1;
|
|
} else if (ins.direction == Direction.right) {
|
|
col += 1;
|
|
} else if (ins.direction == Direction.down) {
|
|
row += 1;
|
|
} else {
|
|
col -= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
std.debug.print("min row:{d}, max row: {d}\n", .{ minRow, maxRow });
|
|
std.debug.print("min col:{d}, max col: {d}\n", .{ minCol, maxCol });
|
|
|
|
// guess at finding a spot inside
|
|
inside = Point{ .row = @divFloor(maxRow - minRow, 2), .col = @divFloor(maxCol - minCol, 2) };
|
|
|
|
var filled2 = try path2.clone();
|
|
defer filled2.deinit();
|
|
|
|
std.debug.print("count pre: {d}\n", .{path2.count()});
|
|
|
|
try fill(&filled2, inside);
|
|
|
|
std.debug.print("count post: {d}\n", .{filled2.count()});
|
|
}
|
|
|
|
fn fill(grid: *std.AutoHashMap(Point, void), point: Point) !void {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
const allocator = gpa.allocator();
|
|
|
|
var toVisit = std.ArrayList(Point).init(allocator);
|
|
defer toVisit.deinit();
|
|
|
|
try toVisit.append(point);
|
|
|
|
while (toVisit.items.len > 0) {
|
|
const p = toVisit.pop();
|
|
// std.debug.print("Looping in fill. point: {any}\n", .{p});
|
|
const ns = [_]Point{ Point{ .row = p.row - 1, .col = p.col }, Point{ .row = p.row + 1, .col = p.col }, Point{ .row = p.row, .col = p.col + 1 }, Point{ .row = p.row, .col = p.col - 1 } };
|
|
for (ns) |px| {
|
|
if (!grid.contains(px)) {
|
|
try grid.put(px, {});
|
|
// try fill(grid, px);
|
|
try toVisit.append(px);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn parseInstructions(content: []const u8, instructions: *std.ArrayList(Instruction)) !void {
|
|
var lines = std.mem.split(u8, content, "\n");
|
|
|
|
while (lines.next()) |line| {
|
|
if (line.len < 1) {
|
|
break;
|
|
}
|
|
|
|
var parts = std.mem.split(u8, line, " ");
|
|
const dirString = parts.next().?;
|
|
|
|
var direction: Direction = undefined;
|
|
|
|
if (std.mem.eql(u8, dirString, "U")) {
|
|
direction = Direction.up;
|
|
} else if (std.mem.eql(u8, dirString, "R")) {
|
|
direction = Direction.right;
|
|
} else if (std.mem.eql(u8, dirString, "D")) {
|
|
direction = Direction.down;
|
|
} else if (std.mem.eql(u8, dirString, "L")) {
|
|
direction = Direction.left;
|
|
} else {
|
|
unreachable;
|
|
}
|
|
|
|
const distance = std.fmt.parseInt(u8, parts.next().?, 10);
|
|
|
|
const instruction = Instruction{ .direction = direction, .distance = try distance };
|
|
try instructions.*.append(instruction);
|
|
}
|
|
}
|
|
|
|
fn parseInstructions2(content: []const u8, instructions: *std.ArrayList(Instruction)) !void {
|
|
var lines = std.mem.split(u8, content, "\n");
|
|
|
|
while (lines.next()) |line| {
|
|
if (line.len < 1) {
|
|
break;
|
|
}
|
|
|
|
var hex = line[6..12];
|
|
const dirString = hex[5..6];
|
|
var direction: Direction = undefined;
|
|
|
|
if (std.mem.eql(u8, dirString, "0")) {
|
|
direction = Direction.right;
|
|
} else if (std.mem.eql(u8, dirString, "1")) {
|
|
direction = Direction.down;
|
|
} else if (std.mem.eql(u8, dirString, "2")) {
|
|
direction = Direction.left;
|
|
} else if (std.mem.eql(u8, dirString, "3")) {
|
|
direction = Direction.up;
|
|
} else {
|
|
unreachable;
|
|
}
|
|
|
|
const distance = try std.fmt.parseInt(usize, hex[0..5], 16);
|
|
|
|
const instruction = Instruction{ .direction = direction, .distance = distance };
|
|
try instructions.append(instruction);
|
|
}
|
|
}
|
|
|
|
fn printGrid(grid: std.AutoHashMap(Point, void)) void {
|
|
for (0..300) |row| {
|
|
for (0..300) |col| {
|
|
if (grid.contains(Point{ .row = @as(i32, @intCast(row)) - 43, .col = @as(i32, @intCast(col)) - 5 })) {
|
|
std.debug.print("#", .{});
|
|
} else {
|
|
std.debug.print(".", .{});
|
|
}
|
|
}
|
|
std.debug.print("\n", .{});
|
|
}
|
|
}
|