diff options
author | Christian Segundo | 2022-12-05 17:00:08 +0100 |
---|---|---|
committer | Christian Segundo | 2022-12-05 22:16:11 +0100 |
commit | 061a5bae272f45db6dcde99746922735f9769d25 (patch) | |
tree | e4dd9b6d903930c5c1b76286b4a08beea6f59162 /day_05.zig | |
parent | 8817203517907ef4248bde7474e6fb566515d6a7 (diff) | |
download | advent-of-zig-2022-061a5bae272f45db6dcde99746922735f9769d25.tar.gz |
add day 5
Diffstat (limited to 'day_05.zig')
-rw-r--r-- | day_05.zig | 138 |
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; +} |