From a98e7d425d578cffd286ff38ddde3308cbbd0d9d Mon Sep 17 00:00:00 2001 From: Andrea Feletto Date: Mon, 12 Dec 2022 13:56:44 +0100 Subject: [PATCH] year 2022 day 12 --- 2022/12/input | 41 ++++++++++ 2022/12/solve.zig | 190 ++++++++++++++++++++++++++++++++++++++++++++++ build.zig | 1 + 3 files changed, 232 insertions(+) create mode 100644 2022/12/input create mode 100644 2022/12/solve.zig diff --git a/2022/12/input b/2022/12/input new file mode 100644 index 0000000..4ff75ee --- /dev/null +++ b/2022/12/input @@ -0,0 +1,41 @@ +abcccccccccccccccccccccccccccccccccccccaaaaaaacccccccaaaaaaaaaaaccccccccccccccccccccaaacaaaaaaaacccccccccccccccccccccccccccccccccccaaaaa +abccccccccccccccccccaaccaacccccccccccccaaaaaaaccccccccaaaaaaaaaaacccccccaaaaccccccccaaaaaaaaaaaaacccccccccccccccccccccccccccccccccaaaaaa +abccccccccccccccccccaaaaaaccccccccccaaaccaaaaaacccccccaaaaaaaaaaccccccccaaaaccccccaaaaaaaaaaaaaaacccccccccccccccccccaaacccccccccccaaaaaa +abcccccccccccccccccccaaaaacccccccccccaaccaacaaaccccccaaaaaaaaaaaccccccccaaaacccccaaaaaaaaacaaaaaaacccccccccccccccccaaaacccccccccccaaacaa +abccccccccccccccccccaaaaaaccccccccaacaaaaaacccccccccaaaaaaaaaaaaacaaaccccaaccccccaaaaaaaaacaacccccccccccccccccaaaccaaaacccccccccccccccaa +abcccccccccccccccccaaaaaaaacccccccaaaaaaaaccccccaaaaaaaacaaaacaaaaaaacccccccccaaccccaaaaaacaaacccccccccccccccaaaakkkaaccccccccccccccccaa +abcccccccccccccccccaaaaaaaaccccccccaaaaaccccaacccaaaaaaaaaaaacaaaaaaccccccccccaacccaaaaaaaaaaaacccccccccccccccakkkkkklcccccccccccccccccc +abaaacccccccccccaaccccaaccccccccccccaaaaaccaaacccaaaaaaaaaaaaaaaaaaaaccccccaaaaaaaacaacccaaaaaaccccccccccccccckkkkkkkllcccccccaaaccccccc +abaaaacccccccaacaaccccaacccccccccccaaacaaaaaaaccccaaaaaaaaaaaaaaaaaaaacccccaaaaaaaaaaaccccaaaaacccccccccccccckkkksssllllccccccaaaaaacccc +abaaaacccccccaaaaacccccccccccaaaccccaacaaaaaaccccaaaaaacaaaaaaaaaaaaaacccccccaaaaccccccccaaaaacccccccccccccckkkksssssllllcccccaaaaaacccc +abaaacccccccccaaaaaaccccccccaaaaccccccccaaaaaaaacaaaaaaaaaaaaacaaacaaacccccccaaaaacccccccaaaaacccccccccccccjkkkrssssssllllccccccaaaccccc +abccccccccccaaaaaaaaccccccccaaaacccccccaaaaaaaaacaacaaaaaaaaaacaaaccccccccccaaacaaccccccccccccccccccccccccjjkkrrsuuussslllllcccccaaccccc +abccaaacccccaaaaacccccccccccaaaaccccccaaaaaaaaaacccccaaaaaaaaaacaaccccccccccaacccacccccccccccccccccccccjjjjjjrrrsuuuussslllllmcccddacccc +abcccaaaccaccacaaaccccccccccccccccccccaaaaaaaccccccccccaaaaaaaaccccccaacccccccccccaaaaacccccccccccccccjjjjjjrrrruuuuuusssllmmmmmddddcccc +abccaaaaaaaacccaaaccccccccccccccccaaacccccaaaccccccccccccaaacccccccccaacccccccccccaaaaacccccccccccccjjjjjrrrrrruuuxuuussqqqqmmmmmdddcccc +abcaaaaaaaacccaaaaaacaaaaaccccccaaaaaaccccaaacccaaccccccccaaccccccaaaaaaaaccaaacccaaaaaaccccccccccccjjjjrrrrrruuuxxxuuuqqqqqqqmmmdddcccc +abaaaaaaaaaccccaaaaacaaaaaccccccaaaaaaaaccccccaaaaaaccccccccccccccaaaaaaaaccaaacaaaaaaaacccccccccccjjjjrrrtttuuuuxxxyvvvvvqqqqmmmdddcccc +abaaaaaaaaaccaaaaaaacaaaaaaccccccaaaaaaaacccccaaaaaaccccccccccccccccaaaaccaaaaaaaaaaaaaacccccccccaaiijqqqrttttuuuxxyyvvvvvvvqqmmmdddcccc +abcaaaaaaaaccaaaaaaaaaaaaaacccccaaaaaaaacccccccaaaacccccaaaaccccccccaaaaacaaaaaaaaccaaccccccccccaaaiiiqqqttttxxxxxxyyyyyyvvvqqmmmdddcccc +abcccaaaaaaacaaaaaaaaaaaaaacccccaaaaaaaaaaaccccaaaaccccaaaaacccccccaaaaaacaaaaaaacccccccccccccccaaaiiiqqqtttxxxxxxxyyyyyyvvqqqmmmdddcccc +SbcccaacccaccccaaacacccaaacccccccccaaaaaaaaacccaccaccccaaaaaaccccccaaccaacccaaaaaccccccccccccccccaaiiiiqqtttxxxxEzzzyyyyvvvqqqmmmddccccc +abccaaaccccccccaaccccccccccccccccccaaaaaaaaccccccccccccaaaaaaccccccccccccccaaacaaaccaacccccccccccccciiiqqqttttxxxyyyyyvvvvqqqmmmdddccccc +abccccccccccccccccccccccccccccccccaaaaaaaccccccccccccccaaaaaacccccccccccccccaacccccaaaaaaaccccccccccciiiqqqttttxxyyyyyvvvrrrnnneeecccccc +abcaaaaccccccccccccccccccccccccccaaaaaaaaccccccccccccccccaacccccccccccccccccccccccccaaaaacccccccccccciiiqqqqttxxyyyyyyyvvrrnnnneeecccccc +abcaaaaacccccccccccccccccccccccccaaaacaaacccaccaaacccccccccccccccccccccccccaaaccccaaaaaaaccccccccccccciiiqqqttwwyywwyyywwrrnnneeeccccccc +abaaaaaacccaccaccccccccccccccccccaaaaccaacccaaaaaaccccccccccccccccaaaccccaaaaaacccaaaaaaaacccccccccccciiiqqqtswwwwwwwwwwwrrnnneeeccccccc +abaaaaaacccaaaaccccccccaaaacccccccaaacccccccaaaaaacccccccccccccccaaaaaaccaaaaaacccaaaaaaaacaaccccccaaciiiqppsswwwwsswwwwwrrrnneeeccccccc +abcaaaaacccaaaaacccccccaaaacccccccccccccccccaaaaaaaccccccccccccccaaaaaaccaaaaaacccccaaaaaaaaaccccccaaaahhpppssswwsssswwwwrrrnneeeacccccc +abcaaaccccaaaaaacccccccaaaaccccccccccccccccaaaaaaaaccccccccccccccaaaaacccaaaaaccccccaacaaaaaaaaccaaaaaahhpppsssssssssrrrrrrnnneeeacccccc +abccccccccaaaaaaccccccccaacccccccccccccccccaaaaaaaaccccaacccccccccaaaaaccaaaaacccccccccaaaaaaaaccaaaaachhpppssssssoosrrrrrrnnneeeaaacccc +abccccccccccaaccccccccccccccccaaaaaccccccaacccaaacccaaaaacccccccccaacaacccccccccccccccccaaaaaaacccaaaaahhhppppssppooooorroonnffeaaaacccc +abaaccccccccccccccccccccccccccaaaaaccccccaacccaaaccccaaaaacccccccccccccccccccccccccccaacaaaaacccccaacaahhhppppppppoooooooooonfffaaaacccc +abaccccccccccccccccccccccccccaaaaaacccaaaaaaaacccccccaaaaaccccccccccccccccccccccccaaaaaaaaaaaccccccccccchhhpppppppgggoooooooffffaacccccc +abaccccccccccccccccccccccccccaaaaaacccaaaaaaaaccccccaaaaaccccccacccaacccccccccccccaaaaaccccaaccccccccccchhhhhhggggggggfffffffffaaacccccc +abaacccccccccccccccccccccccccaaaaaacccccaaaacccccccccaaaacccaacaacaaacccccccccccccaaaaaaacccccccccccccccchhhhgggggggggffffffffccaacccccc +abcccccccaacccccccccccccccccccaaaccccccaaaaaccccccccaaaaccaaaacaaaaacccccccccccccaaaaaaaaccccccccccccccccchhhggggaaaagffffffcccccccccccc +abcccccccaacccccccccccccaacccccccccccccaaaaaaccaaccccaaaaaaaaacaaaaaacccccccaaaacaaaaaaaacccccccccccaacccccccaaaacaaaacccccccccccccccccc +abccccaaaaaaaacccccccaacaaaccccccccccccaaccaacaaaacccaaaaaaaacaaaaaaaaccccccaaaaccacaaaccaaaccccaaaaaacccccccaacccaaaacccccccccccccaaaaa +abccccaaaaaaaacccccccaaaaaccccccccccccccccccccaaaaccccaaaaaaacaaaaaaaaccccccaaaaccccaaaccaaaaaccaaaaaaaacccccccccccaaaccccccccccccccaaaa +abccccccaaaaccccccccccaaaaaaccccccccccccccccccaaaacccaaaaaaaaaaccaaccccccccccaacccccccccaaaaacccaaaaaaaacccccccccccaaaccccccccccccccaaaa +abcccccaaaaaacccccccaaaaaaaacccccccccccccccccccccccaaaaaaaaaaaaaaaacccccccccccccccccccccaaaaaacccaaaaaaaccccccccccccccccccccccccccaaaaaa diff --git a/2022/12/solve.zig b/2022/12/solve.zig new file mode 100644 index 0000000..4fae071 --- /dev/null +++ b/2022/12/solve.zig @@ -0,0 +1,190 @@ +const std = @import("std"); +const fs = std.fs; +const heap = std.heap; +const io = std.io; +const math = std.math; +const mem = std.mem; +const process = std.process; +const testing = std.testing; + +const Point = struct { + i: usize, + j: usize, + + pub fn eql(self: Point, other: Point) bool { + return self.i == other.i and self.j == other.j; + } + + fn heuristic(self: Point, other: Point) usize { + const di = math.absCast( + @intCast(isize, self.i) - @intCast(isize, other.i), + ); + const dj = math.absCast( + @intCast(isize, self.j) - @intCast(isize, other.j), + ); + return di + dj; + } +}; + +const Cell = struct { + point: Point, + priority: usize, + + pub fn compare(_: void, lhs: Cell, rhs: Cell) math.Order { + return math.order(lhs.priority, rhs.priority); + } +}; + +const Search = struct { + map: [41][136]u8, + frontier: Frontier, + came_from: CameFrom, + cost_so_far: CostSoFar, + + const Frontier = std.PriorityQueue(Cell, void, Cell.compare); + const CameFrom = std.AutoHashMap(Point, Point); + const CostSoFar = std.AutoHashMap(Point, usize); + + pub fn init(alloc: mem.Allocator) !Search { + return Search{ + .map = undefined, + .frontier = Frontier.init(alloc, {}), + .came_from = CameFrom.init(alloc), + .cost_so_far = CostSoFar.init(alloc), + }; + } + + pub fn deinit(self: *Search) void { + self.frontier.deinit(); + self.came_from.deinit(); + self.cost_so_far.deinit(); + } + + pub fn findPoint(self: Search, height: u8) ?Point { + return p: for (self.map) |row, i| { + const j = mem.indexOfScalar(u8, &row, height) orelse continue; + break :p .{ .i = i, .j = j }; + } else null; + } + + pub fn findDistance(self: *Search, start: Point, goal: Point) !usize { + self.frontier.len = 0; + self.came_from.clearRetainingCapacity(); + self.cost_so_far.clearRetainingCapacity(); + + try self.frontier.add(.{ .point = start, .priority = 0 }); + try self.came_from.put(start, start); + try self.cost_so_far.put(start, 0); + + var point_buf: [4]Point = undefined; + while (self.frontier.removeOrNull()) |current| { + if (current.point.eql(goal)) break; + + const cost = self.cost_so_far.get(current.point).? + 1; + const neighbors = self.getNeighbors(&point_buf, current.point); + for (neighbors) |next| { + const next_cost = self.cost_so_far.get(next) orelse math.maxInt(usize); + if (cost < next_cost) { + try self.cost_so_far.put(next, cost); + const priority = cost + next.heuristic(goal); + try self.frontier.add(.{ + .point = next, + .priority = priority, + }); + try self.came_from.put(next, current.point); + } + } + } + + var distance: usize = 0; + var current = goal; + while (!current.eql(start)) { + current = self.came_from.get(current) orelse break; + distance += 1; + } + + return distance; + } + + fn getNeighbors(self: Search, buffer: []Point, center: Point) []Point { + const height = self.map[center.i][center.j]; + var k: usize = 0; + if (center.i > 0) { + const i = center.i - 1; + const j = center.j; + if (self.map[i][j] <= height + 1) { + buffer[k] = .{ .i = i, .j = j }; + k += 1; + } + } + if (center.j > 0) { + const i = center.i; + const j = center.j - 1; + if (self.map[i][j] <= height + 1) { + buffer[k] = .{ .i = i, .j = j }; + k += 1; + } + } + if (center.i < 40) { + const i = center.i + 1; + const j = center.j; + if (self.map[i][j] <= height + 1) { + buffer[k] = .{ .i = i, .j = j }; + k += 1; + } + } + if (center.j < 135) { + const i = center.i; + const j = center.j + 1; + if (self.map[i][j] <= height + 1) { + buffer[k] = .{ .i = i, .j = j }; + k += 1; + } + } + return buffer[0..k]; + } +}; + +pub fn main() !void { + const stdout = io.getStdOut().writer(); + + var gpa: heap.GeneralPurposeAllocator(.{}) = .{}; + defer _ = gpa.deinit(); + const alloc = gpa.allocator(); + + var args = process.args(); + _ = args.next(); + const filename = args.next() orelse @panic("error: missing input arg."); + + var buffer: [41 * 137]u8 = undefined; + const content = try fs.cwd().readFile(filename, &buffer); + + var search = try Search.init(alloc); + defer search.deinit(); + + for (search.map) |*row, i| { + const offset = i * 137; + mem.copy(u8, row, content[offset .. offset + 136]); + } + + const start = search.findPoint('S') orelse unreachable; + const goal = search.findPoint('E') orelse unreachable; + + search.map[start.i][start.j] = 'a'; + search.map[goal.i][goal.j] = 'z'; + + const result1 = try search.findDistance(start, goal); + try stdout.print("solution 1: {d}\n", .{result1}); + + var result2 = result1; + for (search.map) |row, i| { + for (row) |height, j| { + if (height == 'a') { + const begin: Point = .{ .i = i, .j = j }; + const dist = try search.findDistance(begin, goal); + if (dist != 0 and dist < result2) result2 = dist; + } + } + } + try stdout.print("solution 2: {d}\n", .{result2}); +} diff --git a/build.zig b/build.zig index f79daff..e19118e 100644 --- a/build.zig +++ b/build.zig @@ -54,6 +54,7 @@ pub fn build(builder: *Builder) !void { .{ .year = "2022", .day = "09" }, .{ .year = "2022", .day = "10" }, .{ .year = "2022", .day = "11" }, + .{ .year = "2022", .day = "12" }, }; for (problems) |*problem| { -- 2.45.2