summaryrefslogtreecommitdiff
path: root/day_05.zig
diff options
context:
space:
mode:
Diffstat (limited to 'day_05.zig')
-rw-r--r--day_05.zig138
1 files changed, 138 insertions, 0 deletions
diff --git a/day_05.zig b/day_05.zig
new file mode 100644
index 0000000..884fd81
--- /dev/null
+++ b/day_05.zig
@@ -0,0 +1,138 @@
+const std = @import("std");
+const Result = @import("util/aoc.zig").Result;
+
+const MAX_HEIGHT = 100;
+
+const Command = struct { From: u8, To: u8, Crates: u8 };
+const Data = struct {
+ Commands: []Command,
+ Crates: [][MAX_HEIGHT]u8,
+
+ fn deinit(self: Data, allocator: std.mem.Allocator) void {
+ allocator.free(self.Commands);
+ allocator.free(self.Crates);
+ }
+};
+
+pub fn puzzle_1(allocator: std.mem.Allocator, input: []const u8) !Result {
+ var data = try parse_input(allocator, input);
+ defer data.deinit(allocator);
+
+ for (data.Commands) |command| {
+ var command_crates = command.Crates;
+
+ while (command_crates > 0) : (command_crates -= 1) {
+ if (command_crates == 0) break;
+ const tmp = data.Crates[command.From][len(data.Crates[command.From]) - 1];
+ data.Crates[command.From][len(data.Crates[command.From]) - 1] = 0;
+ data.Crates[command.To][len(data.Crates[command.To])] = tmp;
+ }
+ }
+
+ return build_answer(allocator, data.Crates);
+}
+
+pub fn puzzle_2(allocator: std.mem.Allocator, input: []const u8) !Result {
+ var data = try parse_input(allocator, input);
+ defer data.deinit(allocator);
+
+ for (data.Commands) |command| {
+ var command_crates = command.Crates;
+
+ const crate_stack = blk: {
+ var r = std.mem.zeroes([MAX_HEIGHT]u8);
+ var idx: usize = 0;
+
+ while (command_crates > 0) : (command_crates -= 1) {
+ if (command_crates == 0) break;
+ r[idx] = data.Crates[command.From][len(data.Crates[command.From]) - 1];
+ data.Crates[command.From][len(data.Crates[command.From]) - 1] = 0;
+ idx += 1;
+ }
+
+ break :blk r;
+ };
+ var crate_stack_height = len(crate_stack);
+
+ while (true) {
+ data.Crates[command.To][len(data.Crates[command.To])] = crate_stack[crate_stack_height];
+ if (crate_stack_height == 0) break;
+ crate_stack_height -= 1;
+ }
+ }
+
+ return build_answer(allocator, data.Crates);
+}
+
+fn build_answer(allocator: std.mem.Allocator, crates: [][MAX_HEIGHT]u8) !Result {
+ var i: usize = 0;
+ var r = try std.ArrayList(u8).initCapacity(allocator, crates.len);
+ while (i < crates.len) : (i += 1) {
+ r.appendAssumeCapacity(crates[i][len(crates[i]) - 1]);
+ }
+
+ return .{ .string = r.toOwnedSlice() };
+}
+
+fn parse_input(allocator: std.mem.Allocator, input: []const u8) !Data {
+ var iter = std.mem.split(u8, input, "\n");
+
+ var floor: u8 = 0;
+ var rows: u8 = 0;
+
+ while (iter.next()) |line| : (floor += 1) {
+ if (line[1] == '1') {
+ var rows_iter = std.mem.splitBackwards(u8, line, " ");
+ _ = rows_iter.next();
+ rows = try std.fmt.parseInt(u8, rows_iter.next() orelse unreachable, 0);
+ iter.reset();
+ break;
+ }
+ }
+
+ var crates = blk: {
+ var r = try std.ArrayList([MAX_HEIGHT]u8).initCapacity(allocator, rows);
+ var i: usize = 0;
+ while (i < rows) : (i += 1) r.appendAssumeCapacity(std.mem.zeroes([MAX_HEIGHT]u8));
+ break :blk r.toOwnedSlice();
+ };
+
+ while (iter.next()) |line| : (floor -= 1) {
+ if (floor == 0) break;
+
+ var row: usize = 0;
+ var offset: usize = 1;
+ while (row < rows) : (row += 1) {
+ if (line[offset] != ' ')
+ crates[row][floor - 1] = line[offset];
+ offset += 4;
+ }
+ }
+
+ // There is an extra line between floor and commands
+ iter.index = iter.index.? + 1;
+ var commands = std.ArrayList(Command).init(allocator);
+ var i: usize = 0;
+ while (iter.next()) |line| : (i += 1) {
+ var command: Command = undefined;
+ var line_iter = std.mem.split(u8, line, " ");
+ _ = line_iter.next(); // move
+ command.Crates = try std.fmt.parseInt(u8, line_iter.next() orelse unreachable, 0);
+ _ = line_iter.next(); // from
+ command.From = try std.fmt.parseInt(u8, line_iter.next() orelse unreachable, 0) - 1;
+ _ = line_iter.next(); // to
+ command.To = try std.fmt.parseInt(u8, line_iter.next() orelse unreachable, 0) - 1;
+ try commands.append(command);
+ }
+ return .{ .Commands = commands.toOwnedSlice(), .Crates = crates };
+}
+
+fn len(row: [MAX_HEIGHT]u8) usize {
+ for (row) |v, i| {
+ if (v == 0) {
+ if (i > 0) return i;
+ return 0;
+ }
+ }
+ unreachable;
+}