const std = @import("std"); const State = enum { Parse, Move }; pub fn main() !void { var file = try std.fs.cwd().openFile("input.txt", .{}); defer file.close(); var a = std.io.bufferedReader(file.reader()); var readerStream = a.reader(); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); const stackCharWidth = 4; var stackCount: ?u32 = null; var state = State.Parse; var stacks = std.ArrayList(std.ArrayList(u8)).init(allocator); defer { for (stacks.items) |stack| { stack.deinit(); } stacks.deinit(); } var buf: [200]u8 = undefined; while (try readerStream.readUntilDelimiterOrEof(&buf, '\n')) |line| { switch (state) { State.Parse => { if (stackCount == null) { // first iteration - allocate stacks stackCount = (@intCast(u32, line.len) + 1) / stackCharWidth; var i: u32 = 0; while (i < stackCount.?) : (i += 1) { try stacks.append(std.ArrayList(u8).init(allocator)); } } if (std.mem.eql(u8, line, "")) { // done parsing state = State.Move; for (stacks.items) |*stack| { _ = stack.pop(); // the stack's index number that also gets parsed std.mem.reverse(u8, stack.items); } } else { // parse stacks for (stacks.items) |*stack, i| { const charIdx = i * stackCharWidth + 1; const char = line[charIdx .. charIdx + 1]; if (char[0] != ' ') try stack.append(char[0]); } } }, State.Move => { var tokens = std.mem.split(u8, line, " "); _ = tokens.next(); // skip "move" const iterations = try std.fmt.parseInt(u32, tokens.next().?, 10); _ = tokens.next(); // skip "from" const src = try std.fmt.parseInt(u32, tokens.next().?, 10) - 1; _ = tokens.next(); // skip "to" const dest = try std.fmt.parseInt(u32, tokens.next().?, 10) - 1; var i: u32 = 0; while (i < iterations) : (i += 1) { const tmp = stacks.items[src].pop(); try stacks.items[dest].append(tmp); } }, } } for (stacks.items) |*stack| { std.debug.print("{c}", .{stack.pop()}); } std.debug.print("\n", .{}); }