| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- const std = @import("std");
- const shapeModule = @import("shape.zig");
- const inputModule = @import("input.zig");
- const areaModule = @import("area.zig");
- const Shape = shapeModule.Shape;
- const Area = areaModule.Area;
- const kShapeSize = shapeModule.kShapeSize;
- const readInputIntoString = inputModule.readInputIntoString;
- const parseInput = inputModule.parseInput;
- const Coord = struct {
- row: u8,
- col: u8,
- };
- pub fn getEligibleCoords(allocator: std.mem.Allocator,
- area: Area,
- eligibleCoords: *std.ArrayList(Coord)) !void {
- eligibleCoords.clearRetainingCapacity();
- for (0 .. area.rows) |row| {
- for (0 .. area.cols) |col| {
- if (area.getCell(@intCast(row), @intCast(col)) == '.') {
- var shouldAdd = false;
- if (row > 0 and area.getCell(@intCast(row-1), @intCast(col)) != '.') {
- shouldAdd = true;
- } else if (col > 0 and area.getCell(@intCast(row), @intCast(col-1)) != '.') {
- shouldAdd = true;
- } else if (row < area.rows - 1 and area.getCell(@intCast(row+1), @intCast(col)) != '.') {
- shouldAdd = true;
- } else if (col < area.cols - 1 and area.getCell(@intCast(row), @intCast(col+1)) != '.') {
- shouldAdd = true;
- }
- if (shouldAdd) {
- var newEligibleCoord = try eligibleCoords.addOne(allocator);
- newEligibleCoord.row = @intCast(row);
- newEligibleCoord.col = @intCast(col);
- }
- }
- }
- }
- if (eligibleCoords.items.len == 0 and area.getCell(0, 0) == '.') {
- var newEligibleCoord = try eligibleCoords.addOne(allocator);
- newEligibleCoord.row = 0;
- newEligibleCoord.col = 0;
- }
- }
- pub fn calculateShapeSizes(allocator: std.mem.Allocator, shapeTransforms: []const []const Shape) ![]usize{
- var shapeSizes = try allocator.alloc(usize, shapeTransforms.len);
- for (0..shapeTransforms.len) |i| {
- shapeSizes[i] = 0;
- for (shapeTransforms[i][0].data) |d| {
- if (d != '.') {
- shapeSizes[i] += 1;
- }
- }
- }
- return shapeSizes;
- }
- pub fn calcShapesTotalSize(shapeCounts: []u8, shapeSizes: []usize) usize {
- var totalSize: usize = 0;
- for (0..shapeCounts.len) |i| {
- totalSize += shapeSizes[i] * shapeCounts[i];
- }
- return totalSize;
- }
- pub fn canContainShapes(allocator: std.mem.Allocator, area: Area,
- shapeCounts: []u8, shapeTransforms: []const []const Shape,
- shapeSizes: []usize) !bool {
- // try std.fs.File.stdout().writeAll("canContainShapes: [");
- // for (shapeCounts) |shapeCount| {
- // try std.fs.File.stdout().writeAll(
- // try std.fmt.allocPrint(allocator, " {d} ", .{shapeCount}));
- // }
- // try std.fs.File.stdout().writeAll("]\n");
- if (calcShapesTotalSize(shapeCounts, shapeSizes) > area.totalFreeSize()) {
- return false;
- }
- var eligibleCoords = std.ArrayList(Coord).empty;
- defer eligibleCoords.deinit(allocator);
-
- var allEmpty = true;
- for (shapeCounts) |shapeCount| {
- if (shapeCount != 0) {
- allEmpty = false;
- break;
- }
- }
- if (allEmpty) {
- try area.print(allocator);
- return true;
- }
- for (0 .. shapeCounts.len) |shapeIndex| {
- if (shapeCounts[shapeIndex] == 0) {
- continue;
- }
- for (0..shapeTransforms[shapeIndex].len) |shapeVariant| {
- try getEligibleCoords(allocator, area, &eligibleCoords);
- for (eligibleCoords.items) |coord| {
- const row = coord.row;
- const col = coord.col;
- if (try area.appendShape(
- allocator,
- &shapeTransforms[shapeIndex][shapeVariant],
- @intCast(row), @intCast(col), '#')) |newArea| {
- defer newArea.deinit();
- // try std.fs.File.stdout().writeAll("Step: \n");
- // try newArea.print(allocator);
- // try std.fs.File.stdout().writeAll("\n");
- var newShapeCounts = try allocator.alloc(u8, shapeCounts.len);
- defer allocator.free(newShapeCounts);
- std.mem.copyForwards(u8, newShapeCounts, shapeCounts);
- newShapeCounts[shapeIndex] -= 1;
- if (try canContainShapes(allocator, newArea, newShapeCounts,
- shapeTransforms, shapeSizes)) {
- return true;
- }
- }
- }
- }
- }
- return false;
- }
- pub fn main() !void {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- const allocator = gpa.allocator();
- const inputBuffer = try readInputIntoString(allocator, "input.txt");
- const input = try parseInput(allocator, inputBuffer);
-
- for (input.areas) |area| {
- try std.fs.File.stdout().writeAll(
- try std.fmt.allocPrint(allocator, "area: rows={d}, cols={d}, shapes=[ ", .{area.rows, area.cols}));
- for (area.shapesCount) |shapeCount| {
- try std.fs.File.stdout().writeAll(
- try std.fmt.allocPrint(allocator, "{d}, ", .{shapeCount}));
- }
- try std.fs.File.stdout().writeAll("]\n");
- }
- var shapeTransforms: [][]Shape = try allocator.alloc([]Shape, input.shapes.len);
- for (0..input.shapes.len) |i| {
- var allTransforms = try input.shapes[i].getAllTransforms(allocator);
- defer allTransforms.deinit();
- shapeTransforms[i] = try allocator.alloc(Shape, allTransforms.count());
- var j: usize = 0;
- var it = allTransforms.keyIterator();
- while (it.next()) |shapeTransform| {
- shapeTransforms[i][j] = shapeTransform.*;
- j += 1;
- }
- }
- const shapeSizes = try calculateShapeSizes(allocator, shapeTransforms);
- defer allocator.free(shapeSizes);
- var counter: usize = 0;
- for (0..input.areas.len) |i| {
- const area = try Area.init(allocator, input.areas[i].rows, input.areas[i].cols);
- defer area.deinit();
-
- if(try canContainShapes(allocator, area, input.areas[i].shapesCount, shapeTransforms, shapeSizes)) {
- try std.fs.File.stdout().writeAll("Can contain shapes!\n");
- counter += 1;
- }
- else {
- try std.fs.File.stdout().writeAll("Can NOT contain shapes!\n");
- }
- }
- try std.fs.File.stdout().writeAll(
- try std.fmt.allocPrint(allocator, "Answer: {d}\n", .{counter}));
- }
|