const std = @import("std"); const path = "data/day05/input.txt"; const RetType = u16; const grid_size = 1000; const max_grid_value = u2; const Vents = [grid_size][grid_size]max_grid_value; const CoordType = i20; const Coord = struct { x: CoordType, y: CoordType }; fn countVents(directions: []const Coord, nodiag: bool) anyerror!RetType { const input = @embedFile(path); var lines = std.mem.split(u8, input, "\n"); var vts: Vents = [_][grid_size]max_grid_value{[_]max_grid_value{0} ** grid_size} ** grid_size; var counter: RetType = 0; while (lines.next()) |line| { if (line.len == 0) continue; var crop_line = std.mem.tokenize(u8, line, " -> "); // parse coordinates var l: [2]Coord = undefined; var idx: usize = 0; while (crop_line.next()) |cl| : (idx += 1) { var coords = std.mem.tokenize(u8, cl, ","); l[idx].x = try std.fmt.parseUnsigned(CoordType, coords.next().?, 10); l[idx].y = try std.fmt.parseUnsigned(CoordType, coords.next().?, 10); } // check if diagonal lines count or not if (nodiag and !((l[0].x == l[1].x) or (l[0].y == l[1].y))) continue; // setup lines const dir = try getDirection(l, directions); while ((l[0].x != l[1].x + dir.x) or (l[0].y != l[1].y + dir.y)) : ({ l[0].x += dir.x; l[0].y += dir.y; }) { var v = vts[@intCast(usize, l[0].x)][@intCast(usize, l[0].y)]; if (v == 1) { counter += 1; } v +|= 1; vts[@intCast(usize, l[0].x)][@intCast(usize, l[0].y)] = v; } } return counter; } fn getDirection(c: [2]Coord, directions: []const Coord) !Coord { var min = try manhattan(c[0], c[1]); for (directions) |d| { if ((try manhattan(Coord{ .x = c[0].x + d.x, .y = c[0].y + d.y }, c[1])) < min) { return d; } } unreachable; } fn manhattan(f: Coord, s: Coord) !CoordType { const xdiff = try std.math.absInt(f.x - s.x); const ydiff = try std.math.absInt(f.y - s.y); return xdiff + ydiff; } pub fn second(allocator: ?std.mem.Allocator) anyerror!RetType { _ = allocator; const directions = [_]Coord{ // Diagonal manhattan distance can decrease by 2, so these must be // tried first otherwise getDirection() will not return proper direction. .{ .x = -1, .y = -1 }, .{ .x = -1, .y = 1 }, .{ .x = 1, .y = -1 }, .{ .x = 1, .y = 1 }, .{ .x = -1, .y = 0 }, .{ .x = 1, .y = 0 }, .{ .x = 0, .y = -1 }, .{ .x = 0, .y = 1 }, }; return try countVents(directions[0..], false); } pub fn main() anyerror!void { var timer = try std.time.Timer.start(); const ret = try second(null); const s = timer.lap() / 1000; try std.testing.expectEqual(ret, @as(RetType, 21577)); std.debug.print("Day 5b result: {d} \t\ttime: {d}us\n", .{ ret, s }); } test "day05b" { try std.testing.expectEqual(@as(RetType, 21577), try second(std.testing.allocator)); }