From 6129705885129c29d311f8664c40f777133e58bc Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Fri, 9 Dec 2022 15:04:28 +0100 Subject: 2022-09 in zig --- 2022/09-rope-bridge/example | 8 + 2022/09-rope-bridge/example2 | 8 + 2022/09-rope-bridge/first.zig | 222 +++++ 2022/09-rope-bridge/input | 2000 ++++++++++++++++++++++++++++++++++++++++ 2022/09-rope-bridge/second.zig | 247 +++++ 5 files changed, 2485 insertions(+) create mode 100644 2022/09-rope-bridge/example create mode 100644 2022/09-rope-bridge/example2 create mode 100644 2022/09-rope-bridge/first.zig create mode 100644 2022/09-rope-bridge/input create mode 100644 2022/09-rope-bridge/second.zig diff --git a/2022/09-rope-bridge/example b/2022/09-rope-bridge/example new file mode 100644 index 0000000..9874df2 --- /dev/null +++ b/2022/09-rope-bridge/example @@ -0,0 +1,8 @@ +R 4 +U 4 +L 3 +D 1 +R 4 +D 1 +L 5 +R 2 diff --git a/2022/09-rope-bridge/example2 b/2022/09-rope-bridge/example2 new file mode 100644 index 0000000..60bd43b --- /dev/null +++ b/2022/09-rope-bridge/example2 @@ -0,0 +1,8 @@ +R 5 +U 8 +L 8 +D 3 +R 17 +D 10 +L 25 +U 20 diff --git a/2022/09-rope-bridge/first.zig b/2022/09-rope-bridge/first.zig new file mode 100644 index 0000000..9229f5d --- /dev/null +++ b/2022/09-rope-bridge/first.zig @@ -0,0 +1,222 @@ +const std = @import("std"); + +const example = @embedFile("example"); +const input = @embedFile("input"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + const allocator = arena.allocator(); + + try std.testing.expectEqual(try solve(example, allocator), 13); + const result = try solve(input, allocator); + try std.io.getStdOut().writer().print("{}\n", .{result}); +} + +const Line = struct { + data: std.ArrayList(bool), + x: i64, + fn init(allocator: std.mem.Allocator) !*Line { + var l = try allocator.create(Line); + l.data = std.ArrayList(bool).init(allocator); + return l; + } + inline fn len(l: Line) usize { + return l.data.items.len; + } + fn set(l: *Line, x: i64) !void { + if (l.len() == 0) { // this is en empty line + l.x = x; + try l.data.append(true); + return; + } + const lx = @intCast(i64, l.len()); + if (x >= l.x) { + if (x < l.x + lx) { // just set the value + l.data.items[@intCast(usize, x - l.x)] = true; + } else { // we need to add trailing spaces + var i: usize = l.len(); + while (i < x - l.x) : (i += 1) { + try l.data.append(false); + } + try l.data.append(true); + } + } else { // we need to shift right and add leading spaces + const oldLen = l.len(); + l.data.items.len += @intCast(usize, l.x - x); + try l.data.ensureUnusedCapacity(l.len()); + std.mem.copyBackwards(bool, l.data.items[@intCast(usize, l.x - x)..], l.data.items[0..oldLen]); + l.data.items[0] = true; + var i: usize = 1; + while (i < @intCast(usize, l.x - x)) : (i += 1) { + l.data.items[i] = false; + } + l.x = x; + } + } + pub fn visited(l: Line) u64 { + var tot: u64 = 0; + var i: usize = 0; + while (i < l.len()) : (i += 1) { + if (l.data.items[i]) { + tot += 1; + } + } + return tot; + } +}; + +pub const Field = struct { + allocator: std.mem.Allocator, + x: i64 = 0, + y: i64 = 0, + lines: std.ArrayList(*Line), + lx: usize = 0, + fn init(allocator: std.mem.Allocator) !*Field { + var f = try allocator.create(Field); + f.allocator = allocator; + f.x = undefined; + f.y = 0; + f.lines = std.ArrayList(*Line).init(allocator); + var l = try f.lines.addOne(); + l.* = try Line.init(allocator); + f.lx = 0; + return f; + } + inline fn len(f: Field) usize { + return f.lines.items.len; + } + pub fn set(f: *Field, x: i64, y: i64) !void { + if (y >= f.y) { + if (y < f.y + @intCast(i64, f.lines.items.len)) { // the line exists + try f.lines.items[@intCast(usize, y - f.y)].set(x); + } else { // append lines + var i: usize = f.lines.items.len; + while (i < y - f.y) : (i += 1) { + try f.lines.append(try Line.init(f.allocator)); + } + var l = try Line.init(f.allocator); + try l.set(x); + try f.lines.append(l); + } + } else { // preprend lines + const oldLen = f.lines.items.len; + f.lines.items.len += @intCast(usize, f.y - y); + try f.lines.ensureUnusedCapacity(f.lines.items.len); + std.mem.copyBackwards(*Line, f.lines.items[@intCast(usize, f.y - y)..], f.lines.items[0..oldLen]); + var l = try Line.init(f.allocator); + try l.set(x); + f.lines.items[0] = l; + var i: usize = 1; + while (i < @intCast(usize, f.y - y)) : (i += 1) { + f.lines.items[i] = try Line.init(f.allocator); + } + f.y = y; + } + if (x < f.x or x >= f.x + @intCast(i64, f.lx)) { // recalculate boundaries + f.x = std.math.maxInt(i64); + var x2: i64 = std.math.minInt(i64); + for (f.lines.items) |line| { + if (line.len() == 0) continue; + if (f.x > line.x) f.x = line.x; + if (x2 < line.x + @intCast(i64, line.len())) x2 = line.x + @intCast(i64, line.len()); + } + f.lx = @intCast(usize, x2 - f.x); + } + return; + } + pub fn visited(f: Field) u64 { + var tot: u64 = 0; + var i: usize = 0; + while (i < f.len()) : (i += 1) { + tot += f.lines.items[i].visited(); + } + return tot; + } +}; + +const Rope = struct { + hx: i64 = 0, + hy: i64 = 0, + tx: i64 = 0, + ty: i64 = 0, + fn step(r: *Rope, direction: u8) void { + switch (direction) { + 'D' => { + r.hy += 1; + }, + 'L' => { + r.hx -= 1; + }, + 'R' => { + r.hx += 1; + }, + 'U' => { + r.hy -= 1; + }, + else => unreachable, + } + if (r.tx == r.hx) { // same line + if (r.ty + 2 == r.hy) { // to the left + r.ty += 1; + } else if (r.ty - 2 == r.hy) { // to the right + r.ty -= 1; + } + } else if (r.ty == r.hy) { + if (r.tx + 2 == r.hx) { // to the top + r.tx += 1; + } else if (r.tx - 2 == r.hx) { // to the bottom + r.tx -= 1; + } + } else if (r.tx + 1 == r.hx) { // on the left by one + if (r.ty + 2 == r.hy) { // above by two + r.tx += 1; + r.ty += 1; + } else if (r.ty - 2 == r.hy) { // bellow by two + r.tx += 1; + r.ty -= 1; + } + } else if (r.tx - 1 == r.hx) { // on the right by one + if (r.ty + 2 == r.hy) { // above by two + r.tx -= 1; + r.ty += 1; + } else if (r.ty - 2 == r.hy) { // bellow by two + r.tx -= 1; + r.ty -= 1; + } + } else if (r.ty + 1 == r.hy) { // above by one + if (r.tx + 2 == r.hx) { // two to the left + r.tx += 1; + r.ty += 1; + } else if (r.tx - 2 == r.hx) { // two to the right + r.tx -= 1; + r.ty += 1; + } + } else if (r.ty - 1 == r.hy) { // bellow by one + if (r.tx + 2 == r.hx) { // two to the left + r.tx += 1; + r.ty -= 1; + } else if (r.tx - 2 == r.hx) { // two to the right + r.tx -= 1; + r.ty -= 1; + } + } + } +}; + +fn solve(puzzle: []const u8, allocator: std.mem.Allocator) !u64 { + var it = std.mem.tokenize(u8, puzzle, "\n"); + var rope = Rope{}; + var field = try Field.init(allocator); + // process input + while (it.next()) |line| { + var elts = std.mem.split(u8, line, " "); + _ = elts.next() orelse unreachable; // the move word + var n = try std.fmt.parseInt(u8, elts.next() orelse unreachable, 10); + while (n > 0) : (n -= 1) { + rope.step(line[0]); + try field.set(rope.tx, rope.ty); + } + } + return field.visited(); +} diff --git a/2022/09-rope-bridge/input b/2022/09-rope-bridge/input new file mode 100644 index 0000000..757d633 --- /dev/null +++ b/2022/09-rope-bridge/input @@ -0,0 +1,2000 @@ +R 1 +D 1 +L 1 +D 1 +R 2 +L 1 +U 2 +D 1 +U 2 +L 1 +U 1 +L 2 +D 1 +U 2 +L 1 +R 1 +D 1 +L 2 +D 2 +L 2 +R 1 +L 2 +U 2 +R 2 +L 2 +U 2 +L 1 +D 1 +L 2 +U 1 +R 1 +D 2 +L 2 +U 1 +R 1 +D 1 +U 2 +L 1 +D 2 +U 1 +D 1 +R 2 +D 1 +L 2 +D 1 +L 1 +R 1 +D 2 +L 1 +R 2 +D 2 +U 2 +R 2 +D 2 +R 2 +L 2 +D 2 +L 2 +D 1 +U 2 +R 1 +D 2 +L 2 +R 2 +L 1 +D 1 +U 2 +D 1 +R 2 +U 2 +R 2 +D 1 +L 1 +U 2 +D 1 +U 1 +D 2 +U 1 +R 1 +U 2 +D 1 +L 2 +U 1 +L 2 +D 2 +R 1 +U 2 +L 1 +D 2 +R 1 +U 1 +D 1 +L 2 +U 1 +R 1 +D 2 +U 2 +L 1 +U 2 +D 2 +R 1 +U 2 +R 1 +U 2 +R 1 +D 2 +U 1 +D 2 +L 2 +D 2 +L 2 +D 2 +R 1 +U 1 +D 3 +U 1 +R 2 +U 3 +D 1 +U 2 +D 2 +U 2 +D 1 +U 2 +R 2 +L 2 +U 1 +L 3 +D 1 +R 3 +D 3 +R 2 +L 1 +U 3 +D 1 +U 2 +R 2 +D 1 +R 3 +D 2 +R 3 +D 1 +U 3 +L 3 +R 2 +U 3 +L 3 +U 2 +L 3 +D 1 +R 3 +U 3 +R 2 +D 1 +U 3 +R 3 +D 1 +L 2 +D 2 +L 2 +D 3 +R 2 +U 3 +L 3 +D 2 +U 3 +L 2 +U 3 +D 1 +L 1 +D 3 +R 1 +D 3 +U 1 +L 3 +U 1 +D 2 +U 1 +D 1 +U 2 +D 3 +L 1 +U 1 +R 1 +U 3 +D 3 +R 1 +L 2 +R 3 +L 3 +U 1 +D 2 +R 2 +U 2 +D 3 +U 2 +D 3 +L 1 +R 3 +D 3 +R 2 +U 3 +D 3 +L 2 +R 3 +D 3 +R 2 +L 1 +R 3 +D 2 +R 1 +D 3 +L 1 +U 1 +D 2 +R 1 +D 1 +L 1 +R 2 +L 1 +U 1 +L 2 +D 2 +L 2 +D 1 +L 2 +U 3 +D 1 +R 3 +L 2 +R 1 +L 2 +R 3 +U 2 +L 4 +R 3 +L 1 +R 2 +D 2 +L 4 +U 3 +L 1 +D 1 +L 3 +U 2 +L 3 +U 2 +L 1 +R 2 +L 3 +U 1 +D 2 +R 1 +L 4 +R 4 +L 4 +U 2 +D 2 +R 2 +L 2 +U 2 +R 1 +D 3 +L 4 +R 2 +U 1 +L 4 +R 1 +L 1 +D 4 +R 3 +D 1 +R 2 +L 2 +R 3 +L 1 +U 1 +D 3 +U 2 +R 1 +L 1 +D 3 +R 2 +U 2 +R 3 +U 2 +D 1 +R 4 +U 4 +D 3 +U 3 +R 2 +U 1 +L 1 +U 4 +D 1 +R 4 +D 4 +L 3 +U 4 +R 4 +L 1 +R 1 +U 2 +R 4 +D 2 +R 1 +U 2 +L 1 +D 1 +L 3 +R 3 +L 3 +D 3 +L 4 +D 2 +U 2 +D 3 +R 1 +U 1 +D 3 +U 1 +R 3 +D 2 +L 3 +R 2 +D 1 +L 3 +D 3 +U 3 +D 4 +L 2 +U 3 +D 5 +L 2 +D 2 +R 2 +L 3 +D 5 +U 4 +R 1 +D 5 +R 1 +D 1 +L 2 +R 4 +U 2 +D 3 +R 5 +L 2 +R 2 +D 1 +R 2 +U 5 +L 4 +U 5 +D 1 +L 2 +U 2 +R 2 +D 4 +U 3 +L 2 +D 1 +U 4 +L 4 +D 3 +L 3 +D 3 +R 1 +U 1 +R 1 +U 1 +R 2 +D 3 +R 5 +U 1 +D 2 +L 5 +U 5 +L 4 +D 4 +U 4 +L 1 +R 5 +U 2 +L 3 +U 2 +D 3 +L 5 +D 5 +L 2 +U 2 +D 4 +U 3 +D 3 +L 1 +D 2 +R 2 +D 1 +R 4 +L 3 +D 1 +U 4 +L 1 +R 2 +L 4 +D 5 +R 3 +D 1 +L 5 +D 5 +U 3 +R 2 +D 4 +L 2 +R 2 +D 3 +R 3 +U 2 +R 5 +U 4 +R 3 +L 1 +D 2 +U 1 +L 1 +R 2 +U 4 +D 4 +L 1 +R 1 +U 4 +L 3 +U 5 +R 3 +L 4 +D 3 +U 1 +R 4 +U 1 +L 1 +U 3 +R 4 +L 5 +D 1 +U 4 +R 5 +L 1 +R 4 +D 2 +L 6 +D 5 +U 5 +L 5 +R 6 +D 1 +U 2 +R 1 +U 4 +D 6 +L 6 +D 6 +U 6 +D 4 +U 4 +D 1 +U 3 +L 5 +D 6 +R 1 +L 1 +D 2 +L 4 +D 4 +L 4 +R 4 +U 2 +L 3 +D 4 +R 3 +D 4 +U 5 +R 4 +U 1 +R 6 +L 3 +R 2 +U 1 +L 1 +R 2 +D 3 +R 6 +D 6 +U 1 +D 3 +U 4 +D 5 +L 5 +U 3 +D 6 +L 5 +R 5 +U 1 +R 4 +D 2 +L 2 +R 4 +L 5 +R 4 +L 3 +D 5 +R 6 +L 6 +U 1 +R 5 +U 6 +D 2 +R 2 +D 1 +L 6 +U 4 +L 1 +R 5 +L 1 +R 2 +D 1 +L 4 +U 4 +L 1 +R 3 +U 5 +L 2 +D 6 +U 5 +R 6 +D 6 +U 3 +L 3 +U 3 +L 4 +D 5 +U 2 +D 4 +U 5 +R 6 +U 5 +D 2 +U 6 +D 3 +L 3 +D 6 +L 5 +R 2 +D 6 +R 7 +D 3 +L 7 +D 3 +U 2 +R 7 +U 2 +L 6 +R 7 +D 3 +R 7 +U 5 +R 7 +L 5 +R 7 +L 7 +U 4 +D 4 +U 1 +D 3 +U 1 +D 5 +R 3 +U 1 +D 2 +U 1 +L 4 +U 2 +L 6 +D 7 +U 1 +D 4 +U 6 +L 4 +R 4 +D 4 +R 6 +D 7 +R 1 +D 7 +L 4 +R 4 +L 1 +U 1 +R 6 +L 7 +D 7 +L 5 +U 7 +D 3 +L 6 +D 6 +U 4 +R 1 +L 2 +D 4 +R 3 +L 1 +R 7 +D 1 +L 2 +U 1 +D 2 +R 1 +U 3 +D 4 +L 3 +U 6 +L 4 +R 2 +L 1 +U 6 +D 1 +R 5 +U 2 +D 2 +L 7 +U 2 +R 5 +D 2 +R 4 +D 4 +R 3 +L 2 +R 3 +U 7 +L 5 +R 7 +U 2 +L 7 +D 3 +U 6 +D 4 +U 4 +D 6 +U 3 +L 6 +R 4 +D 2 +R 4 +D 2 +R 3 +L 5 +D 1 +U 7 +D 4 +L 4 +U 2 +D 2 +U 7 +L 5 +R 6 +U 8 +L 7 +D 2 +U 1 +R 6 +D 4 +L 4 +R 7 +D 1 +L 6 +D 7 +R 7 +U 3 +L 6 +U 1 +L 8 +D 6 +U 8 +L 7 +U 5 +D 8 +L 2 +D 3 +L 8 +U 1 +D 5 +L 4 +R 6 +D 8 +L 6 +U 5 +R 3 +U 7 +R 6 +U 3 +L 3 +D 4 +R 4 +L 2 +R 6 +D 3 +R 3 +L 8 +U 2 +D 6 +U 3 +D 8 +U 6 +D 4 +U 8 +R 7 +D 2 +U 6 +D 6 +R 1 +U 3 +D 3 +R 1 +U 3 +R 1 +D 7 +L 8 +R 8 +U 7 +R 3 +L 8 +U 2 +L 8 +D 4 +U 4 +R 1 +D 3 +R 4 +U 3 +L 7 +U 2 +R 7 +D 2 +U 4 +D 3 +L 8 +D 5 +L 3 +U 4 +D 6 +L 5 +D 2 +U 1 +R 6 +L 4 +R 6 +U 5 +R 8 +U 8 +D 7 +L 5 +D 2 +L 8 +U 2 +D 1 +R 1 +L 7 +U 4 +R 2 +U 7 +D 6 +R 6 +L 5 +U 8 +D 7 +R 8 +L 8 +D 6 +U 6 +R 1 +D 5 +L 7 +R 8 +L 4 +D 3 +L 2 +U 5 +R 9 +L 8 +D 8 +L 2 +R 4 +L 7 +R 5 +L 1 +R 8 +D 8 +L 4 +U 2 +D 7 +L 7 +D 6 +R 8 +L 3 +D 7 +U 1 +R 6 +D 6 +U 6 +L 9 +D 1 +R 7 +L 5 +R 5 +U 5 +D 4 +L 8 +U 4 +D 8 +R 4 +D 6 +U 3 +D 7 +L 5 +D 6 +R 9 +U 4 +R 6 +L 3 +U 4 +D 9 +L 7 +R 5 +D 9 +L 6 +U 7 +L 7 +R 4 +D 5 +R 7 +L 5 +R 3 +U 8 +L 6 +U 5 +L 9 +R 8 +U 4 +D 2 +L 4 +D 7 +R 7 +D 4 +L 4 +U 2 +L 3 +R 1 +D 3 +U 6 +R 1 +U 8 +R 2 +L 4 +D 3 +L 5 +U 4 +R 7 +L 2 +R 7 +L 9 +D 9 +U 5 +L 4 +U 1 +D 1 +U 6 +D 1 +L 6 +D 7 +U 5 +D 9 +R 9 +D 5 +U 9 +L 3 +R 5 +D 10 +R 1 +U 7 +D 6 +L 3 +U 5 +R 1 +D 5 +R 8 +U 3 +L 1 +D 2 +R 1 +L 6 +R 8 +D 9 +U 9 +D 4 +R 1 +U 8 +L 5 +U 4 +D 7 +L 1 +R 4 +L 6 +D 4 +R 5 +D 1 +R 10 +D 5 +R 7 +U 6 +R 5 +U 2 +L 8 +R 1 +U 3 +L 5 +U 4 +L 3 +D 3 +U 6 +D 10 +L 3 +D 7 +L 5 +D 4 +U 6 +R 9 +U 5 +D 5 +R 2 +L 7 +U 8 +D 5 +R 9 +L 6 +R 8 +U 9 +L 4 +R 10 +D 10 +L 9 +R 8 +L 4 +R 5 +L 9 +D 1 +L 3 +R 9 +U 2 +L 5 +R 2 +U 1 +R 4 +D 10 +U 3 +D 8 +L 9 +D 8 +L 5 +D 4 +U 2 +L 8 +R 5 +U 4 +D 1 +L 4 +U 7 +D 9 +R 3 +D 7 +R 9 +L 6 +R 6 +U 8 +L 10 +U 5 +D 4 +R 5 +L 6 +D 7 +L 10 +R 1 +L 9 +U 6 +D 9 +R 7 +L 7 +D 6 +U 6 +R 1 +D 7 +L 1 +R 9 +D 9 +R 3 +L 5 +D 4 +R 3 +L 5 +D 11 +U 1 +R 6 +D 8 +R 4 +D 3 +R 9 +U 3 +D 8 +U 7 +R 2 +U 10 +R 4 +L 4 +D 10 +R 8 +U 11 +R 7 +D 7 +R 9 +D 11 +U 6 +R 7 +D 10 +L 4 +D 5 +L 7 +D 3 +L 4 +D 4 +U 4 +R 3 +L 9 +D 4 +L 8 +U 5 +R 7 +L 2 +D 4 +R 11 +U 10 +D 3 +R 8 +D 3 +R 10 +L 8 +U 6 +R 4 +D 10 +R 7 +D 3 +R 2 +U 1 +D 5 +L 8 +U 2 +R 1 +U 8 +R 11 +L 3 +U 10 +L 5 +D 3 +L 6 +U 10 +L 11 +D 4 +L 5 +D 1 +L 4 +D 1 +L 3 +R 7 +U 7 +R 4 +L 1 +U 10 +D 11 +L 1 +R 1 +U 9 +D 6 +L 9 +D 1 +L 4 +D 11 +L 5 +U 2 +L 5 +D 8 +U 10 +D 5 +U 10 +L 8 +R 11 +D 10 +U 11 +R 4 +U 6 +D 11 +R 1 +L 4 +U 12 +L 8 +U 12 +D 4 +L 7 +U 7 +L 8 +D 3 +U 1 +L 12 +D 5 +U 3 +D 6 +R 7 +U 1 +D 12 +R 6 +U 3 +D 3 +R 12 +U 5 +R 3 +U 8 +L 6 +R 6 +U 3 +L 4 +D 8 +L 5 +D 12 +U 1 +L 9 +R 4 +L 1 +D 6 +U 9 +L 5 +R 3 +L 9 +D 8 +R 6 +D 3 +U 6 +L 1 +D 7 +U 5 +D 1 +L 11 +R 7 +D 11 +L 3 +U 6 +R 9 +D 12 +R 11 +L 5 +R 8 +L 2 +U 10 +R 6 +U 10 +L 9 +U 1 +L 1 +R 8 +L 7 +R 3 +U 4 +L 3 +R 8 +L 9 +R 11 +L 9 +D 11 +U 1 +L 12 +R 6 +L 3 +R 3 +D 12 +U 9 +L 9 +D 8 +R 4 +L 7 +R 1 +U 2 +R 4 +U 4 +R 11 +U 7 +D 11 +U 3 +D 6 +U 7 +L 2 +D 4 +U 9 +R 3 +L 8 +R 9 +L 4 +R 5 +L 7 +D 3 +R 8 +L 6 +U 10 +R 3 +L 6 +D 8 +U 3 +D 9 +L 1 +U 13 +R 12 +L 13 +R 2 +U 8 +R 1 +D 11 +R 5 +L 4 +U 5 +L 3 +D 13 +U 2 +D 1 +U 2 +L 9 +D 3 +R 6 +U 13 +L 3 +U 5 +R 2 +D 2 +L 5 +U 4 +R 6 +D 1 +U 9 +L 7 +R 11 +U 10 +D 12 +R 10 +U 7 +R 5 +L 2 +R 13 +L 13 +D 3 +R 7 +U 1 +L 1 +D 2 +L 9 +U 12 +D 7 +U 13 +L 12 +U 13 +D 7 +U 7 +D 8 +L 2 +U 6 +D 2 +U 6 +L 8 +U 4 +D 11 +U 11 +L 11 +R 10 +L 10 +R 6 +D 13 +U 2 +L 7 +U 8 +D 1 +R 6 +L 7 +R 9 +L 8 +R 9 +L 6 +R 7 +D 12 +R 11 +L 8 +R 1 +D 5 +R 5 +L 10 +U 6 +L 8 +D 9 +L 5 +U 4 +D 12 +U 8 +L 13 +U 6 +D 10 +R 5 +L 13 +D 7 +L 13 +R 5 +L 10 +D 13 +L 9 +R 3 +D 8 +U 9 +D 10 +U 10 +D 7 +L 5 +R 5 +D 9 +L 7 +R 10 +D 13 +R 1 +U 2 +R 6 +U 14 +R 10 +D 6 +U 13 +D 14 +U 5 +D 1 +U 8 +R 4 +U 9 +R 13 +L 4 +D 2 +R 8 +U 2 +D 12 +U 3 +R 6 +U 6 +D 11 +R 7 +L 12 +R 9 +U 7 +D 1 +R 14 +L 11 +U 4 +D 13 +U 5 +L 7 +R 14 +L 1 +U 6 +D 3 +L 1 +U 13 +D 8 +U 14 +D 5 +U 14 +L 1 +R 1 +D 5 +U 7 +L 8 +R 6 +U 1 +D 2 +R 14 +U 13 +L 10 +U 8 +D 13 +U 6 +R 2 +D 4 +R 6 +U 7 +D 10 +L 6 +U 5 +L 3 +D 9 +U 13 +D 8 +U 3 +R 3 +L 12 +D 5 +R 8 +U 7 +R 11 +U 6 +D 7 +R 13 +U 1 +D 9 +U 10 +D 3 +L 5 +R 12 +L 4 +D 13 +R 7 +D 12 +R 11 +D 9 +R 5 +U 13 +R 3 +D 4 +U 10 +R 3 +U 6 +L 4 +R 1 +U 4 +L 9 +D 11 +U 5 +D 3 +U 13 +D 1 +L 1 +D 13 +L 2 +R 9 +L 4 +R 2 +U 9 +D 9 +U 12 +L 14 +R 2 +L 9 +R 5 +U 2 +D 3 +R 13 +U 5 +D 1 +U 15 +R 6 +D 14 +R 8 +L 9 +D 14 +L 6 +R 8 +U 14 +R 11 +L 3 +D 15 +U 5 +R 1 +L 7 +R 12 +D 1 +R 4 +D 13 +U 9 +D 2 +L 3 +U 10 +R 10 +D 2 +R 6 +U 13 +D 7 +R 5 +U 5 +L 12 +U 6 +R 1 +L 7 +U 9 +D 15 +L 8 +U 9 +L 5 +R 3 +L 9 +U 6 +L 11 +D 8 +L 11 +D 13 +U 3 +R 6 +D 2 +L 10 +R 15 +U 2 +D 8 +R 6 +D 6 +L 8 +D 7 +U 2 +D 14 +U 4 +R 6 +D 15 +L 12 +R 4 +D 3 +U 7 +D 10 +L 8 +U 7 +R 10 +U 11 +D 2 +R 10 +D 10 +U 13 +R 8 +L 2 +U 12 +R 9 +U 12 +R 5 +U 10 +L 6 +R 3 +D 10 +L 10 +U 6 +L 4 +R 3 +D 9 +R 15 +D 14 +L 11 +R 5 +U 2 +R 14 +L 15 +R 3 +D 3 +L 4 +U 10 +D 14 +L 9 +D 5 +L 16 +U 12 +L 4 +D 15 +L 10 +R 14 +D 4 +R 12 +L 7 +U 5 +R 3 +L 6 +U 16 +L 5 +U 8 +D 8 +L 6 +D 3 +U 14 +R 1 +L 13 +U 4 +D 11 +R 5 +L 11 +D 7 +R 1 +L 14 +U 10 +L 5 +D 15 +U 14 +L 4 +D 7 +U 3 +R 1 +U 2 +R 3 +D 16 +U 7 +R 7 +D 13 +R 7 +D 5 +U 7 +R 16 +U 4 +L 3 +R 9 +U 1 +D 2 +R 5 +D 3 +U 8 +R 5 +L 13 +U 13 +L 2 +R 9 +L 14 +D 10 +R 1 +U 1 +R 14 +U 14 +R 2 +L 1 +R 12 +L 1 +D 6 +R 2 +D 7 +R 11 +L 5 +D 8 +R 15 +D 12 +R 12 +L 8 +D 10 +R 2 +D 12 +U 15 +L 9 +D 4 +U 3 +L 8 +D 3 +U 9 +D 16 +L 2 +U 14 +R 15 +D 14 +U 12 +D 6 +U 14 +R 11 +D 12 +R 2 +U 13 +L 2 +R 1 +D 6 +U 13 +D 15 +U 1 +R 14 +L 16 +D 8 +R 13 +L 14 +R 3 +D 8 +L 6 +R 16 +D 6 +L 13 +R 2 +L 11 +D 2 +U 1 +R 15 +L 9 +U 1 +R 12 +L 9 +D 7 +L 8 +U 2 +L 14 +R 7 +U 8 +D 15 +R 8 +D 13 +L 15 +R 11 +D 17 +U 2 +R 14 +L 9 +U 11 +D 6 +U 4 +D 8 +U 16 +D 5 +L 3 +D 11 +L 7 +U 11 +L 4 +D 5 +L 5 +D 2 +U 8 +R 17 +D 17 +U 12 +R 4 +L 13 +R 15 +L 10 +U 2 +L 10 +R 6 +D 1 +U 6 +L 3 +D 8 +R 4 +D 1 +L 4 +D 13 +R 1 +U 3 +L 1 +U 9 +D 13 +U 2 +D 13 +R 6 +D 8 +R 6 +D 13 +R 4 +D 10 +L 10 +U 8 +D 1 +R 6 +U 14 +R 3 +L 10 +U 15 +L 11 +U 13 +L 4 +U 5 +L 16 +R 16 +U 11 +R 14 +D 7 +U 5 +R 9 +L 5 +U 12 +R 16 +U 10 +D 5 +R 17 +L 3 +D 5 +U 13 +R 3 +U 3 +L 14 +U 1 +L 8 +R 2 +D 3 +U 9 +D 7 +L 1 +D 5 +R 16 +D 12 +R 1 +U 2 +L 16 +U 3 +R 18 +D 11 +R 3 +L 17 +R 7 +L 6 +D 13 +L 5 +R 12 +D 3 +U 1 +L 1 +U 5 +L 8 +R 11 +L 13 +D 14 +R 17 +D 17 +L 2 +U 7 +D 18 +R 3 +D 2 +U 6 +D 9 +R 3 +U 3 +R 5 +D 16 +R 9 +D 13 +U 8 +D 17 +R 4 +L 6 +R 7 +D 2 +R 15 +U 10 +R 15 +D 6 +L 8 +R 17 +D 5 +L 9 +U 18 +D 10 +U 3 +L 6 +U 10 +D 10 +U 16 +R 6 +D 18 +U 10 +D 8 +U 14 +R 3 +U 14 +L 16 +R 3 +D 5 +L 2 +R 4 +D 9 +L 13 +R 17 +L 8 +D 2 +R 16 +D 18 +L 11 +D 15 +U 5 +D 7 +U 14 +D 13 +U 7 +L 13 +D 13 +R 1 +D 15 +R 11 +L 1 +U 6 +D 14 +L 6 +U 8 +D 15 +R 8 +L 12 +D 17 +R 8 +L 17 +D 16 +R 9 +D 19 +U 4 +R 9 +U 10 +L 3 +U 3 +D 5 +R 2 +U 6 +L 16 +D 8 +R 4 +L 16 +R 15 +U 6 +L 8 +D 6 +L 6 +R 1 +L 8 +D 13 +L 1 +U 7 +R 16 +L 16 +U 1 +L 18 +D 16 +L 8 +U 2 +D 1 +R 2 +D 10 +U 8 +D 2 +R 18 +U 14 +D 15 +R 15 +U 3 +D 1 +U 17 +L 17 +D 15 +L 14 +R 6 +L 18 +U 19 +L 6 +U 17 +L 1 +D 2 +U 17 +R 11 +L 3 +R 3 +L 12 +U 1 +L 9 +U 13 +D 15 +U 12 +R 1 +L 5 +D 17 +L 14 +D 13 +L 2 +D 10 +U 5 +R 13 +L 19 +D 1 +R 12 +U 17 +R 15 +D 19 +U 12 +D 16 +R 2 +U 3 +R 15 +L 13 +U 11 +D 19 +R 10 +D 19 +L 2 +U 12 +R 5 +L 13 +U 13 +R 1 +D 11 +R 17 +D 7 +U 4 +D 14 +L 13 +R 8 +L 8 +D 8 diff --git a/2022/09-rope-bridge/second.zig b/2022/09-rope-bridge/second.zig new file mode 100644 index 0000000..f866b75 --- /dev/null +++ b/2022/09-rope-bridge/second.zig @@ -0,0 +1,247 @@ +const std = @import("std"); + +const example = @embedFile("example"); +const example2 = @embedFile("example2"); +const input = @embedFile("input"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + const allocator = arena.allocator(); + + try std.testing.expectEqual(try solve(example, allocator), 1); + try std.testing.expectEqual(try solve(example2, allocator), 36); + const result = try solve(input, allocator); + try std.io.getStdOut().writer().print("{}\n", .{result}); +} + +const Line = struct { + data: std.ArrayList(bool), + x: i64, + fn init(allocator: std.mem.Allocator) !*Line { + var l = try allocator.create(Line); + l.data = std.ArrayList(bool).init(allocator); + return l; + } + inline fn len(l: Line) usize { + return l.data.items.len; + } + fn set(l: *Line, x: i64) !void { + if (l.len() == 0) { // this is en empty line + l.x = x; + try l.data.append(true); + return; + } + const lx = @intCast(i64, l.len()); + if (x >= l.x) { + if (x < l.x + lx) { // just set the value + l.data.items[@intCast(usize, x - l.x)] = true; + } else { // we need to add trailing spaces + var i: usize = l.len(); + while (i < x - l.x) : (i += 1) { + try l.data.append(false); + } + try l.data.append(true); + } + } else { // we need to shift right and add leading spaces + const oldLen = l.len(); + l.data.items.len += @intCast(usize, l.x - x); + try l.data.ensureUnusedCapacity(l.len()); + std.mem.copyBackwards(bool, l.data.items[@intCast(usize, l.x - x)..], l.data.items[0..oldLen]); + l.data.items[0] = true; + var i: usize = 1; + while (i < @intCast(usize, l.x - x)) : (i += 1) { + l.data.items[i] = false; + } + l.x = x; + } + } + pub fn visited(l: Line) u64 { + var tot: u64 = 0; + var i: usize = 0; + while (i < l.len()) : (i += 1) { + if (l.data.items[i]) { + tot += 1; + } + } + return tot; + } +}; + +pub const Field = struct { + allocator: std.mem.Allocator, + x: i64 = 0, + y: i64 = 0, + lines: std.ArrayList(*Line), + lx: usize = 0, + fn init(allocator: std.mem.Allocator) !*Field { + var f = try allocator.create(Field); + f.allocator = allocator; + f.x = undefined; + f.y = 0; + f.lines = std.ArrayList(*Line).init(allocator); + var l = try f.lines.addOne(); + l.* = try Line.init(allocator); + f.lx = 0; + return f; + } + inline fn len(f: Field) usize { + return f.lines.items.len; + } + pub fn set(f: *Field, x: i64, y: i64) !void { + if (y >= f.y) { + if (y < f.y + @intCast(i64, f.lines.items.len)) { // the line exists + try f.lines.items[@intCast(usize, y - f.y)].set(x); + } else { // append lines + var i: usize = f.lines.items.len; + while (i < y - f.y) : (i += 1) { + try f.lines.append(try Line.init(f.allocator)); + } + var l = try Line.init(f.allocator); + try l.set(x); + try f.lines.append(l); + } + } else { // preprend lines + const oldLen = f.lines.items.len; + f.lines.items.len += @intCast(usize, f.y - y); + try f.lines.ensureUnusedCapacity(f.lines.items.len); + std.mem.copyBackwards(*Line, f.lines.items[@intCast(usize, f.y - y)..], f.lines.items[0..oldLen]); + var l = try Line.init(f.allocator); + try l.set(x); + f.lines.items[0] = l; + var i: usize = 1; + while (i < @intCast(usize, f.y - y)) : (i += 1) { + f.lines.items[i] = try Line.init(f.allocator); + } + f.y = y; + } + if (x < f.x or x >= f.x + @intCast(i64, f.lx)) { // recalculate boundaries + f.x = std.math.maxInt(i64); + var x2: i64 = std.math.minInt(i64); + for (f.lines.items) |line| { + if (line.len() == 0) continue; + if (f.x > line.x) f.x = line.x; + if (x2 < line.x + @intCast(i64, line.len())) x2 = line.x + @intCast(i64, line.len()); + } + f.lx = @intCast(usize, x2 - f.x); + } + return; + } + pub fn visited(f: Field) u64 { + var tot: u64 = 0; + var i: usize = 0; + while (i < f.len()) : (i += 1) { + tot += f.lines.items[i].visited(); + } + return tot; + } +}; + +const Rope = struct { + hx: i64 = 0, + hy: i64 = 0, + tx: i64 = 0, + ty: i64 = 0, + fn stepH(r: *Rope, direction: u8) void { + switch (direction) { + 'D' => { + r.hy += 1; + }, + 'L' => { + r.hx -= 1; + }, + 'R' => { + r.hx += 1; + }, + 'U' => { + r.hy -= 1; + }, + else => unreachable, + } + } + fn stepT(r: *Rope) void { + if (r.tx == r.hx) { // same line + if (r.ty + 2 == r.hy) { // to the left + r.ty += 1; + } else if (r.ty - 2 == r.hy) { // to the right + r.ty -= 1; + } + } else if (r.ty == r.hy) { // same column + if (r.tx + 2 == r.hx) { // to the top + r.tx += 1; + } else if (r.tx - 2 == r.hx) { // to the bottom + r.tx -= 1; + } + } else if (r.tx + 1 == r.hx) { // on the left by one + if (r.ty + 2 == r.hy) { // above by two + r.tx += 1; + r.ty += 1; + } else if (r.ty - 2 == r.hy) { // bellow by two + r.tx += 1; + r.ty -= 1; + } + } else if (r.tx - 1 == r.hx) { // on the right by one + if (r.ty + 2 == r.hy) { // above by two + r.tx -= 1; + r.ty += 1; + } else if (r.ty - 2 == r.hy) { // bellow by two + r.tx -= 1; + r.ty -= 1; + } + } else if (r.ty + 1 == r.hy) { // above by one + if (r.tx + 2 == r.hx) { // two to the left + r.tx += 1; + r.ty += 1; + } else if (r.tx - 2 == r.hx) { // two to the right + r.tx -= 1; + r.ty += 1; + } + } else if (r.ty - 1 == r.hy) { // bellow by one + if (r.tx + 2 == r.hx) { // two to the left + r.tx += 1; + r.ty -= 1; + } else if (r.tx - 2 == r.hx) { // two to the right + r.tx -= 1; + r.ty -= 1; + } + } else { + if (r.tx + 2 == r.hx) { // far left + r.tx += 1; + } else if (r.tx - 2 == r.hx) { // far right + r.tx -= 1; + } + if (r.ty + 2 == r.hy) { // far above + r.ty += 1; + } else if (r.ty - 2 == r.hy) { // far bellow + r.ty -= 1; + } + } + } +}; + +fn solve(puzzle: []const u8, allocator: std.mem.Allocator) !u64 { + var it = std.mem.tokenize(u8, puzzle, "\n"); + var rope: [9]Rope = undefined; + for (rope) |*r| { + r.* = Rope{}; + } + var field = try Field.init(allocator); + // process input + while (it.next()) |line| { + var elts = std.mem.split(u8, line, " "); + _ = elts.next() orelse unreachable; // the move word + var n = try std.fmt.parseInt(u8, elts.next() orelse unreachable, 10); + while (n > 0) : (n -= 1) { + rope[0].stepH(line[0]); + rope[0].stepT(); + var i: usize = 1; + while (i < rope.len) : (i += 1) { + rope[i].hx = rope[i - 1].tx; + rope[i].hy = rope[i - 1].ty; + rope[i].stepT(); + } + try field.set(rope[rope.len - 1].tx, rope[rope.len - 1].ty); + } + } + return field.visited(); +} -- cgit v1.2.3