const std = @import("std");
const path = "data/day13/input.txt";
const RetType = u7;
const PointType = u11;
const Point = [2]PointType;
const Axis = enum(u1) { x, y };
const FoldInstruction = struct {
axis: Axis,
value: PointType,
};
const Dots = std.AutoArrayHashMap(Point, void);
const Folds = std.ArrayList(FoldInstruction);
const Paper = struct {
dots: Dots,
folds: Folds,
pub fn Fold(self: *@This(), a: std.mem.Allocator, axis: Axis, value: PointType) !void {
var to_remove = std.ArrayList(Point).init(a);
defer to_remove.deinit();
switch (axis) {
.x => {
for (self.dots.keys()) |item| {
if (item[0] > value) {
try to_remove.append(item);
try self.dots.put(Point{ value - (item[0] - value), item[1] }, {});
}
}
},
.y => {
for (self.dots.keys()) |item| {
if (item[1] > value) {
try to_remove.append(item);
try self.dots.put(Point{ item[0], value - (item[1] - value) }, {});
}
}
},
}
for (to_remove.items) |item| {
_ = self.dots.swapRemove(item);
}
}
};
fn parseInput(a: std.mem.Allocator) anyerror!Paper {
const input = @embedFile(path);
var lines = std.mem.split(u8, input, "\n");
var ret = Paper{
.dots = Dots.init(a),
.folds = Folds.init(a),
};
// read in coordinates
while (lines.next()) |line| {
if (line.len == 0) break;
var coord = std.mem.tokenize(u8, line, ",");
const x = try std.fmt.parseUnsigned(PointType, coord.next().?, 10);
const y = try std.fmt.parseUnsigned(PointType, coord.next().?, 10);
// std.debug.print("{s} {d} {d}\n", .{ line, x, y });
try ret.dots.put(Point{ x, y }, {});
}
// parse fold instructions
while (lines.next()) |foldline| {
if (foldline.len == 0) break;
var fold = std.mem.tokenize(u8, foldline, " ");
_ = fold.next();
_ = fold.next();
var f = std.mem.tokenize(u8, fold.next().?, "=");
const axis: Axis = if (std.mem.eql(u8, f.next().?, "x")) .x else .y;
const value = try std.fmt.parseUnsigned(PointType, f.next().?, 10);
// std.debug.print("{s} {d}\n", .{axis, value});
try ret.folds.append(FoldInstruction{ .axis = axis, .value = value });
}
return ret;
}
pub fn second(allocator: ?std.mem.Allocator) anyerror!RetType {
var p = try parseInput(allocator.?);
defer {
p.dots.deinit();
p.folds.deinit();
}
for (p.folds.items) |fold| {
try p.Fold(allocator.?, fold.axis, fold.value);
}
// var row: PointType = 0;
// while (row < 7) : (row += 1) {
// std.debug.print("\n", .{});
// var col: PointType = 0;
// while (col < 50) : (col += 1) {
// if (p.dots.contains(Point{ col, row })) {
// std.debug.print("#", .{});
// } else {
// std.debug.print(" ", .{});
// }
// }
// }
return @intCast(RetType, p.dots.count());
}
pub fn main() anyerror!void {
var buf: [75_000]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buf);
var timer = try std.time.Timer.start();
const ret = try second(fba.allocator());
const t = timer.lap() / 1000;
try std.testing.expectEqual(@as(RetType, 103), ret);
std.debug.print("Day 13b result: {d} \t\ttime: {d}us\n", .{ ret, t });
}
test "day13b" {
try std.testing.expectEqual(@as(RetType, 103), try second(std.testing.allocator));
}