diff --git a/benchmark.zig b/benchmark.zig index f7d1ea0..d05bdcd 100644 --- a/benchmark.zig +++ b/benchmark.zig @@ -11,6 +11,7 @@ const d41 = @import("day4/part1.zig"); const d42 = @import("day4/part2.zig"); const d51 = @import("day5/part1.zig"); const d52 = @import("day5/part2.zig"); +const d61 = @import("day6/part1.zig"); const NUMBER_OF_RUN = 1000; @@ -38,6 +39,9 @@ pub fn main() !void { try benchmark(d51.main, 5, 1); try benchmark(d52.main, 5, 2); separator(); + try benchmark(d61.main, 6, 1); + print("| 6 | 2 | Too long | 0 | 0 |\n", .{}); + 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/day6/input b/day6/input new file mode 100644 index 0000000..5bc1f4c --- /dev/null +++ b/day6/input @@ -0,0 +1,130 @@ +...#........................................#........#.................#............#.#.......................#...............#..# +...#........#.....#..................................................................................#......#..#.................. +.................#.......................#.#........#......#...........................................#...#..........#........... +..................#..................#...#.....................................#........#......................................... +...#.....#.......#..............#.#....##.............#....##......................................#...................#.......... +...#..........................................................................................................................#... +..#..#.............#.....#...............#.......#..............................................#....#............................ +......................#..#...............#...................#....#..........................#...#............#...#....##......... +..#.#.........#................#............#............#.#.......#................#....#..#..................................... +.......................................................................#.....................................#...........#........ +...........#.....................................................................#.................................#......#....... +...#.........#....................................................#..............#.............#..........#....................... +.................................................................................................#................................ +..................................#.#.#...#.......#.............#.......................#..#.......................#.#............ +.......................#.........................................#..........#...#.....#....................................#...... +.......#.......#.#...........#......................#.....#..#...#.#...............#.............................#...#............ +............##...#......#.........#......#............................................................#.........#..............#.. +..#........................................#........##..#...............................................................#......... +...........#..............##................................................................................#..................... +..#................................................................................#..............#............................... +...................................##..............#..........................#.......#..#...............#........#............... +....#............#.........................#................................................................#........#............ +............#.....................................................................#.............................................#. +............#..........#.......#...........#.#......#..............#.........#.......................................#......#..... +..#...............................................#..................................#.............................#.............# +.........................................................................#........#................#......#.......#....#........#. +.......................................................................#.....##.................................................#. +..............#.............#...........................#...#..#....................................................#............. +.......#..........................#.......................###..................................#.....................#..#......... +................#.................#.............#......................................................................#........#. +.#.....#................#......................................................................#................#................. +................................#........................#........#..#........................#................................... +..............................................................................................#.....................#.........#... +..................#.................#.........................#.....#................#............................................ +......#...................#...#...................#..................#...........................#......###...................#... +.............................##.....#..............#..............................................................#....#.......... +......#..................#....................................................###....................#..............#............. +............#...#..................#........#.............#..............................#.........#..........................#... +....#...............................#......#......#...............#.#......#............#...................................#..... +.......#...................................#.#.#.........................................................#..................#..... +.....................#.......#.#......#.#.....................#................................................................... +......#.....#............................................................................#............#.......#..#................ +..........#.#......#...................................#....#.#............##..................................................... +...............#........................#..................................#...........#...................................#...... +.#....................................................#.......................................................................#... +......#.........................................#...#.........................................#........#.......................... +.........................................#..........#............................................................................. +...................#.....................................#.....................#..#............#....#........................##... +.................................#.........#.............#.............................#...........................#...#.......... +..#................................................................#.....#....#.................................#................. +........#................#............#.#..........................................#.............................................. +..#...........##.....................#..#..........................#...#...#....#................................................. +................................................................................#................................................. +............#...........#.........#....#.........................................................................#................ +.............................#...........................................#...............##...................................#... +......................#..............#...#........................#........................................#...................... +............#..............#...#.....#.....#..........#...........................#........#...............#...................... +..................#............................#....#................................................................#............ +..#........................#.............................#......#...............#....#...........#................................ +.................................................#................................................#..................#........#... +.#......#.........................................................#...........#...#.......................#....................... +..........................................#.......##........#................................................#..##............##.. +..............#...#....................................................................#........#...........................#..... +................#....................................................................#........................................###. +....#............................................#........................#.................#........#.....#...#.....#.#....#..... +...##..........#.................................................................................................................. +#....#.........#....................#.#.........................#..........##.......#....#..#....................#................ +........#.........#..........#.................#..................#................................#.......#................#...#. +.#..........................................#..#..#......#................................#.#.#..#................................ +....#.......#.........#............................................................#....#......................................... +.....................................................................#...#......................#................................. +............#.....#.....#..........#...............................................................................#.............. +.........................#...#.#.......#....................................................................#.................#... +......................................................#.#..........................#...#................#......................... +.....#.........#.........#..............................................................#...................#.#......#............ +.......................................#......#.......................#.................................................#.....#... +.....#....#....................................................................................................................... +#..........#....#....................................#.............#...............#...................#..........#............... +..#....................................##.....................................#...............................#................... +....#..................................#........................#................................................................. +....#................................................................................................#...................#........ +....#................................................................................#............................................ +..........#.....#...................#.......................#......#.............................................................. +#...................#..........#............................................................#............#..............#......... +...#...#....#................................#............................#.##.....................................#.............. +..........#.........#.....#...........#............................#...............#.#....#................#....................## +.....#...................................................#........................................................................ +............##....................................#..................#.#..#.....................#.........#....##......#...#...... +...........#.......#....................#.......................#..#.................#.......#.........#.......................... +#.....................#..#..............................................................................................#......... +....#....#..............#............##....................................................^.................#..............#..... +.........#......................................................#..............#............#...#......#....#..................... +.......##...................#...........#.........#.......................................#..........................#............ +.#........#.#........................#...........#............#..#........#........#.............#................................ +..................##........##.................................................................................#................#. +...#...................#.....#...........#.........#..#............#..................................#.....#..................... +.................#.........#..........#............#......#.........................#.............#.......#......................# +.................................................................#...............#.....#.#....#................................... +..........................#...........................................................................................#..#........ +..............#.................................................................................##......................#......... +....#...#....................#...............................................#................#............#...................... +........................................................................#........#................................................ +....#.....#......................#.......#............#......................................#..................................#. +................#................................#.#.............#.#.........#..............................................#..... +..............#..................#...#...........................................................................#................ +...#..........#....................................................#...............................#...........#.......#.......... +...................................#....................#..#.#........#..#.......................#...#.....#...................... +.......#.....#.#.......#....#............#...............#..........#.................#........#.#................................ +.....#....#.........#........#.......#............................................................................................ +..#........#......#............................................................#..........#...............................#....... +..#..#...................................#....................#...#.#................#......................#..................... +....................................#......#.....................#...........#.....................#........#..................... +.#..................#.........................................................................................................#... +..............#...........#.#....#..#......#..#.#...#.#.........................................................................#. +...#............##.......................................................#.......................#..#............................. +......#........#..........#..#.#........#.....................#................................................................... +...#...........#.........................................#............#.............#....#.....................................#.. +...........#.....................#......................................................................................#......... +.......#..............#...............#............#..........................#............................#........##............ +.............#..........#..............................................#................#..............................#.......... +...............#..............................#.................#.....#................#....#..................................... +............#.................#..........#........#............#..#......#.......................#....#...#.#...#.#............... +.......#.#...................................##..............#.....#.....................#.................................##..... +..#..#...#...#....#.............#..#.....................................................................................#........ +......#......................#...#...#..........#......................................#.................#....#.................#. +.......#...........#...........#...................#..............................#.......................................#....... +......#.......................................#...............................................#.........#........#....#.........## +......#.................................................................#...#............#..........#............................. +.....................................#..........#.........#.....#.............#...........#....................................... +.#.....................................#......................#.....#..#.......................................................... diff --git a/day6/part1.zig b/day6/part1.zig new file mode 100644 index 0000000..f53187b --- /dev/null +++ b/day6/part1.zig @@ -0,0 +1,151 @@ +const std = @import("std"); +const print = std.debug.print; + +const UP = Position{ .x = -1, .y = 0 }; +const RIGHT = Position{ .x = 0, .y = 1 }; +const DOWN = Position{ .x = 1, .y = 0 }; +const LEFT = Position{ .x = 0, .y = -1 }; + +const Point = enum { Empty, Obstacle, Visited, End }; + +const Position = struct { + x: i16, + y: i16, + + fn move(self: *Position, to: Position) void { + self.x += to.x; + self.y += to.y; + } + + fn rotate(self: *Position) void { + if (std.meta.eql(self.*, UP)) { + self.* = RIGHT; + return; + } + if (std.meta.eql(self.*, RIGHT)) { + self.* = DOWN; + return; + } + if (std.meta.eql(self.*, DOWN)) { + self.* = LEFT; + return; + } + if (std.meta.eql(self.*, LEFT)) { + self.* = UP; + return; + } + } +}; + +const Map = struct { + buff: [132][132]Point = undefined, + gard_position: Position = undefined, + gard_orientation: Position = UP, + + fn next(self: *Map) ?bool { + // Check upfront + var new_visite: ?bool = false; + switch (self.look()) { + .End => return null, + .Empty => { + new_visite = true; + self.gard_position.move(self.gard_orientation); + self.buff[@as(usize, @intCast(self.gard_position.x))][@as(usize, @intCast(self.gard_position.y))] = .Visited; + }, + .Visited => self.gard_position.move(self.gard_orientation), + .Obstacle => { + self.gard_orientation.rotate(); + new_visite = self.next(); + }, + } + return new_visite; + } + + fn printMap(self: Map, writer: anytype) !void { + for (self.buff, 0..) |row, x| { + try writer.writeByte('\n'); + for (row, 0..) |cell, y| { + if (self.gard_position.x == x and self.gard_position.y == y) { + try writer.writeByte('X'); + continue; + } + switch (cell) { + .Obstacle => try writer.writeByte('#'), + .Empty => try writer.writeByte(' '), + .Visited => try writer.writeByte('.'), + .End => try writer.writeByte('E'), + } + } + } + } + + fn get(self: Map, position: Position) Point { + return self.buff[@as(usize, @intCast(position.x))][@as(usize, @intCast(position.y))]; + } + + fn look(self: Map) Point { + return self.buff[@as(usize, @intCast(self.gard_position.x + self.gard_orientation.x))][@as(usize, @intCast(self.gard_position.y + self.gard_orientation.y))]; + } +}; + +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"); + } + + // ========= Load file =========== + const file = try std.fs.cwd().openFile("day6/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); + + // ========= Parse map =========== + var iter = std.mem.split(u8, buffer, "\n"); + var map = Map{}; + + for (0..132) |x| { + for (0..132) |y| { + map.buff[x][y] = .End; + } + } + + var x: usize = 1; + while (iter.next()) |line| { + for (line, 1..) |c, y| switch (c) { + '.' => map.buff[x][y] = .Empty, + '#' => map.buff[x][y] = .Obstacle, + '^' => { + map.gard_position = .{ .x = 1 + @as(i16, @intCast(x)), .y = @as(i16, @intCast(y)) }; + map.buff[x][y] = .Empty; + }, + else => unreachable, + }; + x += 1; + } + + // ========= Make the gard move to the end =========== + //var map_array = std.ArrayList(u8).init(allocator); + //defer map_array.deinit(); + var total: usize = 0; + while (map.next()) |new_visite| { + //defer map_array.clearRetainingCapacity(); + //try map.printMap(map_array.writer()); + if (new_visite) total += 1; + //clearScreen(); + //print("{s}", .{map_array.items}); + //std.time.sleep(2000000); + } + + try std.testing.expectEqual(5516, total); +} + +fn clearScreen() void { + print("\x1B[2J\x1B[H", .{}); +} diff --git a/day6/part2.zig b/day6/part2.zig new file mode 100644 index 0000000..be69100 --- /dev/null +++ b/day6/part2.zig @@ -0,0 +1,278 @@ +const std = @import("std"); +const print = std.debug.print; + +const VisitedBy = struct { up: bool = false, down: bool = false, right: bool = false, left: bool = false }; + +const Point = struct { + type_: enum { End, Obstacle, Empty } = .End, + visited_by: VisitedBy = .{}, + + fn point2Orientation(self: Point) Orientation { + return switch (self) { + .VisitedUp => .UP, + .VisitedRight => .RIGHT, + .VisitedDown => .DOWN, + .VisitedLeft => .LEFT, + else => unreachable, + }; + } + + fn visitedAny(self: Point) bool { + return self.visited_by.up or self.visited_by.down or self.visited_by.left or self.visited_by.right; + } +}; + +const Orientation = enum { UP, DOWN, LEFT, RIGHT }; + +const Position = struct { + x: i16, + y: i16, +}; + +const Gard = struct { + position: Position = undefined, + orientation: Orientation = .UP, + + fn move(self: *Gard) void { + self.position.x += if (self.orientation == .UP) -1 else if (self.orientation == .DOWN) 1 else 0; + self.position.y += if (self.orientation == .LEFT) -1 else if (self.orientation == .RIGHT) 1 else 0; + } + + fn inFront(self: Gard) Position { + var x = self.position.x; + x += if (self.orientation == .UP) -1 else if (self.orientation == .DOWN) 1 else 0; + var y = self.position.y; + y += if (self.orientation == .LEFT) -1 else if (self.orientation == .RIGHT) 1 else 0; + return Position{ + .x = x, + .y = y, + }; + } + + fn rotate(self: *Gard) void { + self.orientation = switch (self.orientation) { + .UP => .RIGHT, + .RIGHT => .DOWN, + .DOWN => .LEFT, + .LEFT => .UP, + }; + } +}; + +const Map = struct { + buff: [132][132]Point = undefined, + gard: Gard, + + allocator: std.mem.Allocator, + founded_loop: *std.AutoHashMap(Position, void), + + fn init(allocator: std.mem.Allocator) !Map { + const map = try allocator.create(std.AutoHashMap(Position, void)); + map.* = std.AutoHashMap(Position, void).init(allocator); + return Map{ + .allocator = allocator, + .gard = Gard{}, + .founded_loop = map, + }; + } + + fn deinit(self: *Map) void { + self.founded_loop.deinit(); + self.allocator.destroy(self.founded_loop); + } + + fn isNextPositionVisited(self: Map) bool { + var gard_ = self.gard; + for (0..4) |_| { + if (self.get(gard_.inFront()).?.type_ == .Obstacle) { + gard_.rotate(); + continue; + } + gard_.move(); + break; + } + + return switch (gard_.orientation) { + .UP => self.get(gard_.position).?.visited_by.up, + .DOWN => self.get(gard_.position).?.visited_by.down, + .LEFT => self.get(gard_.position).?.visited_by.left, + .RIGHT => self.get(gard_.position).?.visited_by.right, + }; + } + + fn isNextPositionVisitedAny(self: Map) bool { + var gard_ = self.gard; + for (0..4) |_| { + if (self.get(gard_.inFront()).?.type_ == .Obstacle) { + gard_.rotate(); + continue; + } + gard_.move(); + break; + } + + return self.get(gard_.position).?.visitedAny(); + } + + fn next(self: *Map) ?void { + // Check upfront + switch (self.look().type_) { + .End => return null, + .Empty => { + self.gard.move(); + self.setVisited(self.gard); + }, + .Obstacle => { + self.gard.rotate(); + self.setVisited(self.gard); + return self.next(); + }, + } + } + + fn setVisited(self: *Map, gard: Gard) void { + switch (gard.orientation) { + .UP => self.buff[@as(usize, @intCast(gard.position.x))][@as(usize, @intCast(gard.position.y))].visited_by.up = true, + .DOWN => self.buff[@as(usize, @intCast(gard.position.x))][@as(usize, @intCast(gard.position.y))].visited_by.down = true, + .LEFT => self.buff[@as(usize, @intCast(gard.position.x))][@as(usize, @intCast(gard.position.y))].visited_by.left = true, + .RIGHT => self.buff[@as(usize, @intCast(gard.position.x))][@as(usize, @intCast(gard.position.y))].visited_by.right = true, + } + } + + fn printMap(self: Map) !void { + var array = std.ArrayList(u8).init(self.allocator); + defer array.deinit(); + const writer = array.writer(); + + for (self.buff, 0..) |row, x| { + try writer.writeByte('\n'); + for (row, 0..) |cell, y| { + if (self.gard.position.x == x and self.gard.position.y == y) { + try writer.writeByte('X'); + continue; + } + switch (cell.type_) { + .Obstacle => try writer.writeByte('#'), + .Empty => { + if (self.founded_loop.contains(Position{ .x = @as(i16, @intCast(x)), .y = @as(i16, @intCast(y)) })) { + try writer.writeByte('0'); + } else if ((cell.visited_by.up or cell.visited_by.down) and (cell.visited_by.left or cell.visited_by.right)) { + try writer.writeByte('+'); + } else if (cell.visited_by.up or cell.visited_by.down) { + try writer.writeByte('|'); + } else if (cell.visited_by.right or cell.visited_by.left) { + try writer.writeByte('-'); + } else { + try writer.writeByte(' '); + } + }, + .End => try writer.writeByte('E'), + } + } + } + + print("{s}", .{array.items}); + } + + fn isInLoop(self: *Map) !bool { + const initial_buff = self.buff; + const initial_gard = self.gard; + + defer self.buff = initial_buff; + defer self.gard = initial_gard; + + while (self.next()) |_| { + if (self.isNextPositionVisited()) return true; + } + + return false; + } + + fn set(self: *Map, position: Position, point: Point) void { + self.buff[@as(usize, @intCast(position.x))][@as(usize, @intCast(position.y))] = point; + } + + fn get(self: Map, position: Position) ?Point { + if (0 > position.x or position.x >= 132 or 0 > position.y or position.y >= 132) return null; + return self.buff[@as(usize, @intCast(position.x))][@as(usize, @intCast(position.y))]; + } + + fn look(self: Map) Point { + const position = self.gard.inFront(); + return self.buff[@as(usize, @intCast(position.x))][@as(usize, @intCast(position.y))]; + } +}; + +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"); + } + + // ========= Load file =========== + const file = try std.fs.cwd().openFile("day6/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); + + // ========= Parse map =========== + var iter = std.mem.split(u8, buffer, "\n"); + var map = try Map.init(allocator); + defer map.deinit(); + + for (0..132) |x| { + for (0..132) |y| { + map.buff[x][y] = Point{}; + } + } + + var x: usize = 1; + while (iter.next()) |line| { + for (line, 1..) |c, y| switch (c) { + '.' => map.buff[x][y].type_ = .Empty, + '#' => map.buff[x][y].type_ = .Obstacle, + '^' => { + map.gard.position = .{ .x = @as(i16, @intCast(x)), .y = @as(i16, @intCast(y)) }; + map.buff[x][y].type_ = .Empty; + map.buff[x][y].visited_by.up = true; + }, + else => unreachable, + }; + x += 1; + } + + // ========= Make the gard move to the end =========== + var total: usize = 0; + const start_map = map; + + while (map.next()) |_| { + var map2 = start_map; + map2.set(map.gard.position, Point{ .type_ = .Obstacle }); + + if (try map2.isInLoop()) { + if (!map.founded_loop.contains(map.gard.position)) total += 1; + try map.founded_loop.put(map.gard.position, {}); + } + } + + try std.testing.expectEqual(2008, total); +} + +fn progressBar(value: usize, max: usize, size: usize, writer: anytype) !void { + try writer.writeByte('|'); + const nb_fill = @divFloor(size * value, max); + for (0..nb_fill) |_| try writer.writeByte('='); + for (0..size - nb_fill) |_| try writer.writeByte(' '); + try writer.writeByte('|'); + try writer.print(" {d}/{d}", .{ value, max }); +} + +fn clearScreen() void { + print("\x1B[2J\x1B[H", .{}); +}