Compare commits
No commits in common. "96a2a09620cecced3ceb7dc37fdaf17ccb6e16f3" and "b5583ca46effb46d3b9fcc3a7dc04b8a650f401f" have entirely different histories.
96a2a09620
...
b5583ca46e
155
src/day11.zig
155
src/day11.zig
@ -1,155 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const util = @import("util.zig");
|
|
||||||
const mem = std.mem;
|
|
||||||
|
|
||||||
pub fn main() !void {
|
|
||||||
const input = @embedFile("data/day11.txt");
|
|
||||||
const sln = try solve(util.gpa, input);
|
|
||||||
std.debug.print("{d}\n", .{sln.a});
|
|
||||||
std.debug.print("{d}\n", .{sln.b});
|
|
||||||
}
|
|
||||||
|
|
||||||
const Solution = struct {
|
|
||||||
a: usize,
|
|
||||||
b: usize,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn Point(comptime T: type) type {
|
|
||||||
return struct { x: T, y: T };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn findGaps(comptime T: type, alloc: mem.Allocator, occupied: std.AutoHashMap(T, void)) ![]T {
|
|
||||||
var it = occupied.keyIterator();
|
|
||||||
var sorted_occupied = try std.ArrayList(T).initCapacity(alloc, occupied.count());
|
|
||||||
defer sorted_occupied.deinit();
|
|
||||||
while (it.next()) |item| {
|
|
||||||
try sorted_occupied.append(item.*);
|
|
||||||
}
|
|
||||||
mem.sort(T, sorted_occupied.items, {}, std.sort.asc(T));
|
|
||||||
|
|
||||||
var gaps = std.ArrayList(T).init(alloc);
|
|
||||||
errdefer gaps.deinit();
|
|
||||||
|
|
||||||
var gap: T = 0;
|
|
||||||
var i: usize = 0;
|
|
||||||
const max_occ = if (sorted_occupied.items.len != 0) std.mem.max(T, sorted_occupied.items) else 0;
|
|
||||||
while (gap < max_occ and i < sorted_occupied.items.len) : (gap += 1) {
|
|
||||||
if (sorted_occupied.items[i] != gap) {
|
|
||||||
try gaps.append(gap);
|
|
||||||
} else {
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return gaps.toOwnedSlice();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expand(comptime T: type, alloc: mem.Allocator, galaxies: []Point(T), scale: T) !void {
|
|
||||||
var seen_cols = std.AutoHashMap(T, void).init(alloc);
|
|
||||||
defer seen_cols.deinit();
|
|
||||||
var seen_rows = std.AutoHashMap(T, void).init(alloc);
|
|
||||||
defer seen_rows.deinit();
|
|
||||||
|
|
||||||
for (galaxies) |galaxy| {
|
|
||||||
try seen_cols.put(galaxy.x, {});
|
|
||||||
try seen_rows.put(galaxy.y, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
var gap_cols = try findGaps(T, alloc, seen_cols);
|
|
||||||
defer alloc.free(gap_cols);
|
|
||||||
var gap_rows = try findGaps(T, alloc, seen_rows);
|
|
||||||
defer alloc.free(gap_rows);
|
|
||||||
|
|
||||||
for (0..galaxies.len) |i| {
|
|
||||||
const galaxy = galaxies[i];
|
|
||||||
|
|
||||||
var col_offset: T = 0;
|
|
||||||
for (gap_cols) |gap| {
|
|
||||||
if (gap > galaxy.x) break;
|
|
||||||
col_offset += scale - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var row_offset: T = 0;
|
|
||||||
for (gap_rows) |gap| {
|
|
||||||
if (gap > galaxy.y) break;
|
|
||||||
row_offset += scale - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
galaxies[i] = Point(T){ .x = galaxy.x + col_offset, .y = galaxy.y + row_offset };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn absDiff(comptime T: type, a: T, b: T) T {
|
|
||||||
return @max(a, b) - @min(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn solvePart(alloc: mem.Allocator, input: []const u8, scale: usize) !usize {
|
|
||||||
var galaxies = std.ArrayList(Point(usize)).init(alloc);
|
|
||||||
defer galaxies.deinit();
|
|
||||||
|
|
||||||
var it = util.splitLines(input);
|
|
||||||
var y: usize = 0;
|
|
||||||
while (it.next()) |line| {
|
|
||||||
if (line.len == 0) continue;
|
|
||||||
var x: usize = 0;
|
|
||||||
for (line) |char| {
|
|
||||||
switch (char) {
|
|
||||||
'.' => {},
|
|
||||||
'#' => try galaxies.append(Point(usize){ .x = x, .y = y }),
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
x += 1;
|
|
||||||
}
|
|
||||||
y += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
try expand(usize, alloc, galaxies.items, scale);
|
|
||||||
|
|
||||||
var distance: usize = 0;
|
|
||||||
for (galaxies.items, 0..) |a, i| {
|
|
||||||
for (galaxies.items[i + 1 .. galaxies.items.len]) |b| {
|
|
||||||
const d = absDiff(usize, a.x, b.x) + absDiff(usize, a.y, b.y);
|
|
||||||
distance += d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn solve(alloc: mem.Allocator, input: []const u8) !Solution {
|
|
||||||
return .{ .a = try solvePart(alloc, input, 2), .b = try solvePart(alloc, input, 1_000_000) };
|
|
||||||
}
|
|
||||||
|
|
||||||
test "silver" {
|
|
||||||
const input =
|
|
||||||
\\...#......
|
|
||||||
\\.......#..
|
|
||||||
\\#.........
|
|
||||||
\\..........
|
|
||||||
\\......#...
|
|
||||||
\\.#........
|
|
||||||
\\.........#
|
|
||||||
\\..........
|
|
||||||
\\.......#..
|
|
||||||
\\#...#.....
|
|
||||||
;
|
|
||||||
const sln = try solvePart(std.testing.allocator, input, 2);
|
|
||||||
try std.testing.expectEqual(@as(usize, 374), sln);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "gold" {
|
|
||||||
const input =
|
|
||||||
\\...#......
|
|
||||||
\\.......#..
|
|
||||||
\\#.........
|
|
||||||
\\..........
|
|
||||||
\\......#...
|
|
||||||
\\.#........
|
|
||||||
\\.........#
|
|
||||||
\\..........
|
|
||||||
\\.......#..
|
|
||||||
\\#...#.....
|
|
||||||
;
|
|
||||||
try std.testing.expectEqual(@as(usize, 1030), try solvePart(std.testing.allocator, input, 10));
|
|
||||||
try std.testing.expectEqual(@as(usize, 8410), try solvePart(std.testing.allocator, input, 100));
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user