const std = @import("std"); const shapeModule = @import("shape.zig"); const Shape = shapeModule.Shape; pub const AreaRequirements = struct { rows: u8, cols: u8, shapesCount: []u8, }; pub const Input = struct { shapes: []Shape, areas: []AreaRequirements, }; fn parseShape(shapeText: []const u8) Shape { var it = std.mem.tokenizeScalar(u8, shapeText, '\n'); _ = it.next(); // skip header var shape: Shape = .{ .data = undefined, }; for (0..3) |row| { const rowText = it.next().?; for (0..3) |col| { shape.setCell(@intCast(row), @intCast(col), rowText[col]); } } return shape; } fn parseAreaRequirements(allocator: std.mem.Allocator, line: []const u8) !AreaRequirements { var it = std.mem.tokenizeSequence(u8, line, ": "); const sizeText = it.next().?; const shapesCountText = it.next().?; var sizeTextIt = std.mem.tokenizeScalar(u8, sizeText, 'x'); const rowsText = sizeTextIt.next().?; const colsText = sizeTextIt.next().?; const rows = try std.fmt.parseInt(u8, rowsText, 10); const cols = try std.fmt.parseInt(u8, colsText, 10); var shapesCountTextIt = std.mem.tokenizeScalar(u8, shapesCountText, ' '); var shapesCount = std.ArrayList(u8).empty; while (shapesCountTextIt.next()) |shapeCountText| { const shapeCount = try shapesCount.addOne(allocator); shapeCount.* = try std.fmt.parseInt(u8, shapeCountText, 10); } const area: AreaRequirements = .{ .rows = rows, .cols = cols, .shapesCount = shapesCount.items, }; return area; } pub fn parseInput(allocator: std.mem.Allocator, inputBuffer: []u8) !Input { var shapes = std.ArrayList(Shape).empty; var areas = std.ArrayList(AreaRequirements).empty; var i = std.mem.tokenizeSequence(u8, inputBuffer, "\n\n"); while (i.next()) |inputBlock| { if (inputBlock.len >= 2 and inputBlock[1] == ':') { const shape = try shapes.addOne(allocator); shape.* = parseShape(inputBlock); } else { var it = std.mem.tokenizeScalar(u8, inputBlock, '\n'); while(it.next()) |line| { const area = try areas.addOne(allocator); area.* = try parseAreaRequirements(allocator, line); } } } const input: Input = .{ .shapes = shapes.items, .areas = areas.items, }; return input; } pub fn readInputIntoString(allocator: std.mem.Allocator, fileName: []const u8) ![]u8 { const inputFile = try std.fs.cwd().openFile( fileName, .{.mode = .read_only,}); defer inputFile.close(); var inputFileReader = inputFile.reader( try allocator.alignedAlloc(u8, null, 1024)); const inputFileSize = try inputFileReader.getSize(); const inputBuffer = try allocator.alignedAlloc(u8, null, inputFileSize); try inputFileReader.interface.readSliceAll(inputBuffer); return inputBuffer; }