80 lines
2.6 KiB
Zig
80 lines
2.6 KiB
Zig
const std = @import("std");
|
|
|
|
const v2d = [2]i32;
|
|
|
|
pub fn main() void {
|
|
const input = @embedFile("input");
|
|
std.debug.print("Part 1: {}\n", .{nVisitedSnake(input, 2)});
|
|
std.debug.print("Part 2: {}\n", .{nVisitedSnake(input, 10)});
|
|
}
|
|
|
|
pub fn nVisitedSnake(input: []const u8, comptime len: usize) usize {
|
|
if (len < 2) @compileError("The length has to be greater than 1.");
|
|
|
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
|
defer arena.deinit();
|
|
const allocator = arena.allocator();
|
|
|
|
var knots = [_]v2d{v2d{ 0, 0 }} ** len;
|
|
var visited = std.ArrayList(v2d).init(allocator);
|
|
|
|
var iter = std.mem.split(u8, input, "\n");
|
|
while (iter.next()) |line| {
|
|
|
|
// Line not valid
|
|
if (line.len < 2) continue;
|
|
|
|
// Get the number, continue on error
|
|
const num = std.fmt.parseInt(usize, line[2..], 10) catch continue;
|
|
|
|
// Direction of said movement
|
|
const dir: v2d = switch (line[0]) {
|
|
'U' => .{ 0, 1 },
|
|
'D' => .{ 0, -1 },
|
|
'R' => .{ 1, 0 },
|
|
'L' => .{ -1, 0 },
|
|
else => unreachable,
|
|
};
|
|
|
|
// Move the head one step at a time
|
|
var step: usize = 0;
|
|
while (step < num) : (step += 1) {
|
|
// Move the head
|
|
knots[0][0] += dir[0];
|
|
knots[0][1] += dir[1];
|
|
|
|
// Go through each pair of "head/tail" knots
|
|
var tailIdx: usize = 1;
|
|
while (tailIdx < knots.len) : (tailIdx += 1) {
|
|
const head = &knots[tailIdx - 1];
|
|
const tail = &knots[tailIdx];
|
|
|
|
var axis: u8 = 0;
|
|
while (axis < 2) : (axis += 1) {
|
|
const diff = head[axis] - tail[axis];
|
|
const dist = std.math.absInt(diff) catch unreachable;
|
|
if (dist >= 2) {
|
|
// Move it to where the head is -1
|
|
tail[axis] = head[axis] - @divTrunc(dist, diff);
|
|
|
|
// If one axis is at a +2 distance, snap the other one
|
|
const otherAxis = (axis + 1) % 2;
|
|
tail[otherAxis] = head[otherAxis];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Register the poisition again if it hasn't been saved before
|
|
const tail = knots[knots.len - 1];
|
|
for (visited.items) |coord| {
|
|
if (coord[0] == tail[0] and coord[1] == tail[1]) break;
|
|
} else {
|
|
visited.append(tail) catch unreachable;
|
|
}
|
|
}
|
|
}
|
|
|
|
return visited.items.len;
|
|
}
|