From 3f063f931c29cbe1d23eeb155fdc7eba2a9479a9 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Sun, 13 Dec 2020 14:48:37 -0500 Subject: [PATCH] Finish day 12 --- day12/build.zig | 27 ++ day12/input | 750 +++++++++++++++++++++++++++++++++++++++++++++ day12/src/main.zig | 197 ++++++++++++ 3 files changed, 974 insertions(+) create mode 100644 day12/build.zig create mode 100644 day12/input create mode 100644 day12/src/main.zig diff --git a/day12/build.zig b/day12/build.zig new file mode 100644 index 0000000..49704c7 --- /dev/null +++ b/day12/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + // Standard target options allows the person running `zig build` to choose + // what target to build for. Here we do not override the defaults, which + // means any target is allowed, and the default is native. Other options + // for restricting supported target set are available. + const target = b.standardTargetOptions(.{}); + + // Standard release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day12", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day12/input b/day12/input new file mode 100644 index 0000000..dc64185 --- /dev/null +++ b/day12/input @@ -0,0 +1,750 @@ +W1 +F91 +W3 +F82 +N1 +E2 +N4 +R90 +F25 +N2 +F75 +E4 +R90 +F91 +R90 +F64 +L90 +E1 +L90 +S2 +L180 +S2 +E3 +N2 +E5 +L90 +N2 +R90 +F30 +L90 +N1 +F37 +S1 +E5 +F3 +E2 +F59 +W3 +L270 +S5 +W5 +S4 +F84 +N5 +R180 +E4 +F31 +L90 +E2 +F77 +L90 +N5 +F17 +N4 +N4 +W2 +F45 +S1 +F92 +E1 +F33 +L270 +F21 +L90 +E1 +F81 +N5 +F20 +E2 +R90 +N4 +W3 +L180 +S2 +F33 +E5 +F87 +R90 +N2 +F29 +E3 +S4 +L90 +E4 +R90 +S2 +F65 +L90 +F69 +W2 +N4 +F73 +R180 +S3 +R90 +N3 +R90 +W1 +L180 +F96 +N3 +W2 +L180 +S5 +F29 +E3 +S4 +W1 +F53 +E1 +L90 +E5 +F26 +E3 +R270 +E2 +S2 +W2 +F43 +W2 +F53 +F74 +R180 +N5 +W3 +S4 +F70 +R90 +W4 +F56 +L90 +S5 +R180 +E4 +S4 +F80 +S1 +F91 +R90 +S4 +F88 +L90 +S5 +R90 +E2 +S1 +F37 +N1 +R90 +F92 +W5 +F14 +N2 +E5 +S2 +F89 +L180 +N4 +E4 +L90 +F32 +E4 +R90 +F99 +N3 +L180 +F78 +S1 +R270 +W1 +F11 +S4 +F47 +N4 +L90 +F17 +R90 +E4 +S3 +F14 +S1 +R90 +N3 +F52 +W3 +S5 +L180 +F41 +R90 +F62 +W1 +R90 +E4 +F1 +W5 +F86 +W1 +N5 +F5 +S1 +E5 +F67 +W3 +F97 +E1 +L90 +S2 +E1 +R90 +F82 +E3 +N2 +F16 +L90 +W2 +F35 +R180 +N2 +E3 +N4 +W4 +F13 +S5 +E1 +S5 +L90 +E5 +F65 +E5 +L90 +S4 +E3 +W4 +N1 +R90 +N5 +F93 +R90 +S5 +R90 +L90 +F86 +E3 +F90 +E4 +N2 +E4 +R180 +W5 +R90 +E3 +F98 +F56 +L90 +F68 +L90 +N3 +F35 +S1 +W5 +F25 +L180 +F7 +R270 +F84 +R90 +S4 +E5 +S3 +L270 +F33 +W3 +R90 +W5 +N3 +E4 +R90 +W2 +F100 +E5 +S2 +L90 +F6 +E1 +L90 +S1 +F17 +N3 +E1 +S3 +F78 +R90 +W5 +N4 +L90 +F13 +W5 +R90 +F7 +F74 +R90 +E4 +F28 +L90 +S5 +R90 +F77 +S2 +E2 +N3 +F30 +E1 +R90 +W2 +S2 +F62 +E2 +L90 +E2 +F56 +L90 +F61 +S1 +F14 +W3 +F23 +L90 +E3 +S3 +L270 +S5 +F97 +E5 +S1 +F96 +W2 +F61 +L180 +F25 +L90 +W4 +F100 +W4 +F14 +W4 +S5 +R90 +F67 +E1 +R90 +F89 +W5 +S3 +W2 +N2 +F64 +L180 +S4 +R270 +F47 +E1 +S1 +E4 +N1 +R90 +N2 +E5 +F97 +N3 +E5 +S5 +R180 +E5 +F34 +L90 +W1 +W1 +N3 +R90 +F17 +N1 +F75 +S4 +W5 +N2 +W1 +N2 +L90 +W3 +N2 +F1 +N1 +W3 +R90 +F18 +E4 +N4 +F18 +N4 +F73 +W4 +F61 +W3 +R90 +N5 +L90 +N4 +F70 +E4 +F10 +L90 +F33 +N5 +L90 +W4 +L180 +E2 +F41 +E1 +S4 +E4 +L90 +F28 +N2 +W4 +S2 +F86 +R180 +S3 +W3 +S3 +W2 +F55 +W1 +F18 +W2 +F18 +L90 +S4 +W1 +L90 +F47 +L90 +S4 +F39 +N5 +L180 +S3 +W5 +F95 +W1 +R90 +E2 +N3 +L90 +S4 +F77 +S1 +W4 +S5 +E4 +R90 +W1 +R90 +W3 +W2 +N4 +F1 +W1 +N5 +F55 +E4 +N4 +W5 +L90 +F90 +E4 +R90 +E2 +R90 +S5 +F44 +N2 +E3 +R90 +F64 +W1 +L180 +L180 +F55 +L90 +F15 +S2 +E1 +R270 +F10 +R90 +W4 +F43 +E1 +F7 +N2 +W3 +F10 +N1 +L270 +N2 +L90 +E2 +R90 +F28 +W2 +N5 +F70 +R90 +E3 +E3 +F75 +W4 +L90 +S2 +R90 +F83 +L270 +E1 +F87 +R180 +N3 +L90 +F30 +L90 +E1 +N5 +F87 +N4 +R90 +F51 +W5 +N3 +R90 +S5 +F98 +W4 +N2 +E2 +L90 +E4 +S1 +E5 +F60 +N1 +L180 +E1 +F10 +R90 +W5 +F90 +W5 +F9 +S1 +W3 +F9 +E2 +S4 +L180 +F61 +W2 +N3 +F35 +R90 +E4 +N3 +W4 +L90 +E1 +L90 +S1 +F62 +S5 +W1 +N5 +L180 +F76 +W3 +L90 +W4 +L90 +N2 +E3 +N5 +E1 +N2 +F13 +S1 +F20 +W5 +L90 +S1 +F89 +S3 +L90 +W2 +L90 +F48 +W5 +N1 +R90 +F93 +L90 +E4 +L90 +N2 +F100 +W5 +S5 +W1 +S1 +E2 +S1 +W4 +R90 +S2 +F99 +W2 +F80 +L90 +F78 +N4 +L90 +F67 +S1 +L90 +F23 +W3 +N1 +W5 +F76 +R270 +F51 +L90 +W2 +N1 +E3 +S3 +L90 +F83 +L90 +F46 +S5 +L180 +N3 +E3 +F49 +E5 +N4 +W5 +L90 +E3 +R90 +S4 +F54 +E1 +F49 +N4 +L180 +E3 +L90 +R90 +F95 +W2 +N2 +F12 +R180 +E4 +R90 +N5 +L180 +S3 +W3 +S1 +F22 +W1 +F18 +L90 +F35 +R90 +F3 +S4 +L90 +F53 +W5 +F58 +L90 +S2 +F48 +S5 +R180 +F67 +L180 +W1 +S3 +L90 +F33 +F34 +R90 +F54 +W2 +L180 +S5 +W4 +R90 +F80 +W4 +S1 +W4 +F35 +E1 +F48 +N3 +L270 +F78 +N4 +S4 +F11 +S1 +W3 +L90 +W1 +F26 +R180 +E3 +F43 +S4 +R180 +W3 +N2 +F80 +W4 +F29 +W5 +W1 +R270 +N3 +L90 +F17 +W4 +F49 +S4 +S1 +F47 diff --git a/day12/src/main.zig b/day12/src/main.zig new file mode 100644 index 0000000..0d4d24f --- /dev/null +++ b/day12/src/main.zig @@ -0,0 +1,197 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + defer gpa.free(contents); + + var ship = ShipPosition{}; + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + ship.update(line[0], try std.fmt.parseInt(i64, line[1..], 10)); + std.log.debug("After '{}', ship at ({}, {}) facing {}", + .{line, ship.position[0], ship.position[1], ship.facing}); + } + std.log.info("Ship is at ({},{}) facing {}. It has travalled {} manhattan distance from start", + .{ship.position[0], ship.position[1], ship.facing, + ship.manhattan_distance_from([_]i64{0, 0})}); + + // Part 2 + ship = ShipPosition{}; + it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + ship.update_part2(line[0], try std.fmt.parseInt(i64, line[1..], 10)); + std.log.debug("After '{}', ship at ({}, {}), with waypoint ({}, {})", + .{line, ship.position[0], ship.position[1], + ship.waypoint[0], ship.waypoint[1]}); + } + std.log.info("Ship is at ({},{}) facing {} and waypoint ({}, {}). It has travalled {} manhattan distance from start", + .{ship.position[0], ship.position[1], ship.facing, + ship.waypoint[0], ship.waypoint[1], + ship.manhattan_distance_from([_]i64{0, 0})}); +} + +const ShipPosition = struct { + facing : i64 = 90, + position : [2]i64 = [_]i64{0, 0}, + waypoint: [2]i64 = [_]i64{10, 1}, + + pub fn update(self: *ShipPosition, command: u8, value: i64) void { + switch(command) { + 'N' => { + self.position[1] += value; + }, + 'S' => { + self.position[1] -= value; + }, + 'E' => { + self.position[0] += value; + }, + 'W' => { + self.position[0] -= value; + }, + 'R' => { + self.facing += value; + }, + 'L' => { + self.facing -= value; + }, + 'F' => { + std.log.debug("Facing before moving forward: {}", .{self.facing}); + while (self.facing < 0) { + self.facing += 360; + } + if (self.facing >= 360) { + self.facing = @intCast(i64, @mod(self.facing, 360)); + } + std.log.debug("Facing after normalizing, before moving forward: {}", + .{self.facing}); + var c : u8 = switch(self.facing) { + 0 => 'N', + 90 => 'E', + 180 => 'S', + 270 => 'W', + else => { + std.log.warn("Unexpected facing {}", .{self.facing}); + unreachable; + }, + }; + self.update(c, value); + }, + else => { + std.log.warn("Unknown command: '{}'", .{command}); + }, + } + } + + pub fn manhattan_distance_from(self: *ShipPosition, from: [2]i64) u64 { + return (std.math.absCast(self.position[0] - from[0])) + + (std.math.absCast(self.position[1] - from [1])); + } + + pub fn update_part2(self: *ShipPosition, command: u8, value: i64) void { + switch(command) { + 'N' => { + self.waypoint[1] += value; + }, + 'S' => { + self.waypoint[1] -= value; + }, + 'E' => { + self.waypoint[0] += value; + }, + 'W' => { + self.waypoint[0] -= value; + }, + 'R' => { + // Rotate around the ship + self.waypoint = rotate_point(self.waypoint, -value); + }, + 'L' => { + // Rotate around the ship + self.waypoint = rotate_point(self.waypoint, value); + }, + 'F' => { + // For forward value times towards the waypoint. + self.position[0] += self.waypoint[0] * value; + self.position[1] += self.waypoint[1] * value; + // Waypoint stays relative to ship + //self.waypoint[0] = self.position[0] + self.waypoint[0]; + //self.waypoint[1] = self.position[1] + self.waypoint[1]; + }, + else => { + std.log.warn("Unknown command: '{}'", .{command}); + }, + } + } + +}; + +pub fn rotate_point(point: [2]i64, degrees: i64) [2]i64 { + var radians : f64 = (@intToFloat(f64, degrees) * std.math.pi) / 180.0; + var old_x = @intToFloat(f64, point[0]); + var old_y = @intToFloat(f64, point[1]); + var x : f64 = old_x * std.math.cos(radians) - old_y * std.math.sin(radians); + var y : f64 = old_y * std.math.cos(radians) + old_x * std.math.sin(radians); + return [2]i64 { + @floatToInt(i64, std.math.round(x)), + @floatToInt(i64, std.math.round(y)), + }; +} + +test "part_one" { + var data = [_][]const u8 { + "F10", + "N3", + "F7", + "R90", + "F11", + }; + var ship = ShipPosition{}; + for (data) |d| { + ship.update(d[0], try std.fmt.parseInt(i64, d[1..], 10)); + } + std.testing.expectEqual(ship.position[0], 17); + std.testing.expectEqual(ship.position[1], -8); + std.testing.expectEqual(ship.manhattan_distance_from([_]i64{0, 0}), 25); +} + +test "part_two" { + var data = [_][]const u8 { + "F10", + "N3", + "F7", + "R90", + "F11", + }; + var ship = ShipPosition{}; + for (data) |d| { + ship.update_part2(d[0], try std.fmt.parseInt(i64, d[1..], 10)); + std.log.warn("After '{}', ship at ({}, {}), with waypoint ({}, {})", + .{d, ship.position[0], ship.position[1], + ship.waypoint[0], ship.waypoint[1]}); + } + std.testing.expectEqual(ship.position[0], 214); + std.testing.expectEqual(ship.position[1], -72); + std.testing.expectEqual(ship.manhattan_distance_from([_]i64{0, 0}), 286); +} + +// test "rotate" { +// var point = [_]i64 {4,-3}; +// var p = rotate_point(point, 90); +// std.testing.expectEqual(p[0], 3); +// std.testing.expectEqual(p[1], 4); + +// p = rotate_point(point, 180); +// std.testing.expectEqual(p[0], -4); +// std.testing.expectEqual(p[1], 3); + +// p = rotate_point(point, 270); +// std.testing.expectEqual(p[0], -4); +// std.testing.expectEqual(p[1], 3); + +// }