diff --git a/benchmark.zig b/benchmark.zig index c5a8781..ff66133 100644 --- a/benchmark.zig +++ b/benchmark.zig @@ -14,6 +14,8 @@ const d52 = @import("day5/part2.zig"); const d61 = @import("day6/part1.zig"); const d71 = @import("day7/part1.zig"); const d72 = @import("day7/part2.zig"); +const d81 = @import("day8/part1.zig"); +const d82 = @import("day8/part2.zig"); const NUMBER_OF_RUN = 1000; @@ -47,6 +49,9 @@ pub fn main() !void { try benchmark(d71.main, 7, 1); print("| 7 | 2 | Too long ~0.2s | 0 | 0 |\n", .{}); separator(); + try benchmark(d81.main, 8, 1); + try benchmark(d82.main, 8, 2); + separator(); print("| Total | {d: >8} ± {d: <6.2} | {d:>8} | {d:>8} |\n", .{ total_mean, total_std_dev, total_min, total_max }); separator(); } diff --git a/day8/input b/day8/input new file mode 100644 index 0000000..43b8c92 --- /dev/null +++ b/day8/input @@ -0,0 +1,50 @@ +........5..................................e..3... +.......q...........m................e............. +....m.......................................e..... +.........................................C........ +.u.m........................8..................... +...........7......9.......8...........F...s....... +6...q..............................s.............. +.................................................. +.................................................. +.................................................. +..........9....................F.................. +.................................M....D........... +.........U........................................ +..q................................8.............. +.......9.......................................... +0....6.....................e..Qs...............F.. +.................................Q...D............ +.0.u....................................2......... +.................................................. +........u................Q........................ +.....E........1................................... +...n....v....................................3.... +......u..0................N....................... +............................................z..... +.........7....U.........4.....Z...Q.....D.....V... +..............n1.........f.................2...... +E.............................f..............z.... +...E........1.Z.......U......................D.... +.......n...v....7Z...N............................ +..........7..N.....Zf...........................3. +................................b............V.... +............4..................................9.. +..n...v........................5................2. +.........v.................5.........S............ +..........................s....................... +.....U.........4..C.....................S..V...... +.................................................. +......................c........b............M..... +...........4.Wc....d.......1.....b.....S.......... +..E........c............................5......z.. +..............w..C....................SM.2........ +........................d......................... +...............c......C3.......................... +...............w....W............................. +.................................................. +.........d.......B....w........................... +....B.....W.......dw..........................M... +...............W......................N...V....... +.B................................................ +....................B...............b............. diff --git a/day8/part1.zig b/day8/part1.zig new file mode 100644 index 0000000..3fe50d8 --- /dev/null +++ b/day8/part1.zig @@ -0,0 +1,144 @@ +const std = @import("std"); +const print = std.debug.print; + +const MAP_SIZE = 50; + +const Position = struct { + x: i64, + y: i64, + + /// Return a Position so self + returned = to + fn minus(self: Position, to: Position) Position { + return Position{ .x = self.x - to.x, .y = self.y - to.y }; + } + + fn add(self: Position, to: Position) Position { + return Position{ .x = self.x + to.x, .y = self.y + to.y }; + } + + // Some basic vector operation. I get the vecto to go from A to B, then apply it from B to C. C is the place of one antinode. + // I do the same A minus vector to get D, the second antinode + fn antinodesPositions(self: Position, to: Position) [2]?Position { + const diff = to.minus(self); + const pos1 = self.minus(diff); + const pos2 = to.add(diff); + + return [2]?Position{ + if (pos1.x < 0 or pos1.y >= MAP_SIZE or pos1.y < 0 or pos1.x >= MAP_SIZE) null else pos1, + if (pos2.x < 0 or pos2.y >= MAP_SIZE or pos2.y < 0 or pos2.x >= MAP_SIZE) null else pos2, + }; + } +}; + +const Cell = struct { + position: Position, + antenna: u8, + antinodes: [20]u8 = [_]u8{'.'} ** 20, + antinodes_len: usize = 0, + + fn haveAnyAntinode(self: Cell) bool { + return self.antinodes[0] != '.'; + } +}; + +const Map = struct { + cells: [MAP_SIZE][MAP_SIZE]Cell = undefined, + unique_antenna: std.AutoHashMap(u8, usize), + + fn printMap(self: Map) !void { + var array = std.ArrayList(u8).init(std.heap.page_allocator); + defer array.deinit(); + const writer = array.writer(); + + for (self.cells) |row| { + for (row) |cell| try writer.writeByte(cell.antenna); + try writer.writeByte('\n'); + } + + print("{s}", .{array.items}); + } + + // Lets make a function that take an antenna, find all other antenna with same char, useing 2 position find 2 new, then add to list + fn addAntinodes(self: *Map, char: u8) void { + // So here I need to loop over all cells -> find first of this char -> look for next of -> add 2 antinodes -> + // -> Find the next of same char and add antinodes -> do it for all cells -> Repeat but skip first, then 2 first, etc + const count_antenna = self.unique_antenna.get(char).?; + + for (0..count_antenna) |step| { + var left_cell: Cell = undefined; + var founded: usize = 0; + for (self.cells) |row| for (row) |cell| { + if (cell.antenna == char) { + defer founded += 1; + if (founded < step) continue; + if (founded == step) { + left_cell = cell; + continue; + } + + const antinodes_positions = left_cell.position.antinodesPositions(cell.position); + if (antinodes_positions[0]) |pos| self.addAntinodeToCell(pos, char); + if (antinodes_positions[1]) |pos| self.addAntinodeToCell(pos, char); + } + }; + } + } + + fn addAntinodeToCell(self: *Map, position: Position, char: u8) void { + var cell = self.cells[@as(usize, @intCast(position.x))][@as(usize, @intCast(position.y))]; + defer self.cells[@as(usize, @intCast(position.x))][@as(usize, @intCast(position.y))] = cell; + + cell.antinodes[cell.antinodes_len] = char; + cell.antinodes_len += 1; + } + + fn countUniqueAntinodes(self: Map) usize { + var total: usize = 0; + for (self.cells) |row| for (row) |cell| { + if (cell.haveAnyAntinode()) total += 1; + }; + + return total; + } +}; + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const allocator = gpa.allocator(); + defer { + const deinit_status = gpa.deinit(); + if (deinit_status == .leak) @panic("TEST FAIL"); + } + + const file = try std.fs.cwd().openFile("day8/input", .{}); + defer file.close(); + + const file_size = (try file.stat()).size; + const buffer = try allocator.alloc(u8, file_size); + defer allocator.free(buffer); + + _ = try file.readAll(buffer); + + var map = Map{ .unique_antenna = std.AutoHashMap(u8, usize).init(allocator) }; + defer map.unique_antenna.deinit(); + var iter = std.mem.split(u8, buffer, "\n"); + var x: usize = 0; + while (iter.next()) |line| { + if (std.mem.eql(u8, line, "")) continue; + defer x += 1; + for (line, 0..) |c, y| switch (c) { + '\n' => {}, + else => { + map.cells[x][y] = Cell{ .position = Position{ .x = @as(i64, @intCast(x)), .y = @as(i64, @intCast(y)) }, .antenna = c }; + if (c != '.') try map.unique_antenna.put(c, 1 + (map.unique_antenna.get(c) orelse 0)); + }, + }; + } + + var keys = map.unique_antenna.keyIterator(); + while (keys.next()) |key| { + map.addAntinodes(key.*); + } + + try std.testing.expectEqual(228, map.countUniqueAntinodes()); +} diff --git a/day8/part2.zig b/day8/part2.zig new file mode 100644 index 0000000..8ca5f74 --- /dev/null +++ b/day8/part2.zig @@ -0,0 +1,154 @@ +const std = @import("std"); +const print = std.debug.print; + +// Agaain happy with the result, only needed to change few things + +const MAP_SIZE = 50; + +const Position = struct { + x: i64, + y: i64, + + /// Return a Position so self + returned = to + fn minus(self: Position, to: Position) Position { + return Position{ .x = self.x - to.x, .y = self.y - to.y }; + } + + fn add(self: Position, to: Position) Position { + return Position{ .x = self.x + to.x, .y = self.y + to.y }; + } + + // Now I do a loop to add as much as long it is inside boundary + fn antinodesPositions(self: Position, to: Position, allocator: std.mem.Allocator) ![]Position { + var list = std.ArrayList(Position).init(allocator); + const diff = to.minus(self); + + var left = self; + while (left.inBoundary()) : (left = left.minus(diff)) try list.append(left); + var right = to; + while (right.inBoundary()) : (right = right.add(diff)) try list.append(right); + + return try list.toOwnedSlice(); + } + + fn outBoundary(self: Position) bool { + return self.x < 0 or self.y >= MAP_SIZE or self.y < 0 or self.x >= MAP_SIZE; + } + + fn inBoundary(self: Position) bool { + return !self.outBoundary(); + } +}; + +const Cell = struct { + position: Position, + antenna: u8, + antinodes: [20]u8 = [_]u8{'.'} ** 20, + antinodes_len: usize = 0, + + fn haveAnyAntinode(self: Cell) bool { + return self.antinodes[0] != '.'; + } +}; + +const Map = struct { + cells: [MAP_SIZE][MAP_SIZE]Cell = undefined, + unique_antenna: std.AutoHashMap(u8, usize), + + fn printMap(self: Map) !void { + var array = std.ArrayList(u8).init(std.heap.page_allocator); + defer array.deinit(); + const writer = array.writer(); + + for (self.cells) |row| { + for (row) |cell| try writer.writeByte(cell.antenna); + try writer.writeByte('\n'); + } + + print("{s}", .{array.items}); + } + + fn addAntinodes(self: *Map, char: u8, parent_allocator: std.mem.Allocator) !void { + var arena = std.heap.ArenaAllocator.init(parent_allocator); + const allocator = arena.allocator(); + defer arena.deinit(); + + const count_antenna = self.unique_antenna.get(char).?; + + for (0..count_antenna) |step| { + var left_cell: Cell = undefined; + var founded: usize = 0; + for (self.cells) |row| for (row) |cell| { + if (cell.antenna == char) { + defer founded += 1; + if (founded < step) continue; + if (founded == step) { + left_cell = cell; + continue; + } + + const antinodes_positions = try left_cell.position.antinodesPositions(cell.position, allocator); + for (antinodes_positions) |pos| self.addAntinodeToCell(pos, char); + } + }; + } + } + + fn addAntinodeToCell(self: *Map, position: Position, char: u8) void { + var cell = self.cells[@as(usize, @intCast(position.x))][@as(usize, @intCast(position.y))]; + defer self.cells[@as(usize, @intCast(position.x))][@as(usize, @intCast(position.y))] = cell; + + cell.antinodes[cell.antinodes_len] = char; + cell.antinodes_len += 1; + } + + fn countUniqueAntinodes(self: Map) usize { + var total: usize = 0; + for (self.cells) |row| for (row) |cell| { + if (cell.haveAnyAntinode()) total += 1; + }; + + return total; + } +}; + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const allocator = gpa.allocator(); + defer { + const deinit_status = gpa.deinit(); + if (deinit_status == .leak) @panic("TEST FAIL"); + } + + const file = try std.fs.cwd().openFile("day8/input", .{}); + defer file.close(); + + const file_size = (try file.stat()).size; + const buffer = try allocator.alloc(u8, file_size); + defer allocator.free(buffer); + + _ = try file.readAll(buffer); + + var map = Map{ .unique_antenna = std.AutoHashMap(u8, usize).init(allocator) }; + defer map.unique_antenna.deinit(); + var iter = std.mem.split(u8, buffer, "\n"); + var x: usize = 0; + while (iter.next()) |line| { + if (std.mem.eql(u8, line, "")) continue; + defer x += 1; + for (line, 0..) |c, y| switch (c) { + '\n' => {}, + else => { + map.cells[x][y] = Cell{ .position = Position{ .x = @as(i64, @intCast(x)), .y = @as(i64, @intCast(y)) }, .antenna = c }; + if (c != '.') try map.unique_antenna.put(c, 1 + (map.unique_antenna.get(c) orelse 0)); + }, + }; + } + + var keys = map.unique_antenna.keyIterator(); + while (keys.next()) |key| { + try map.addAntinodes(key.*, allocator); + } + + try std.testing.expectEqual(766, map.countUniqueAntinodes()); +}