solve day 11

This commit is contained in:
Rokas Puzonas 2024-01-16 23:27:15 +02:00
parent 6e6cd59ea4
commit 08222a641e
2 changed files with 219 additions and 0 deletions

217
src/day11.zig Normal file
View File

@ -0,0 +1,217 @@
const std = @import("std");
const aoc = @import("./aoc.zig");
const Allocator = std.mem.Allocator;
const Point = @import("./point.zig").Point(u32);
const ArrayList = std.ArrayList;
const Tile = enum {
Empty,
Galaxy,
fn to_char(self: Tile) u8 {
return switch (self) {
.Empty => '.',
.Galaxy => '#',
};
}
fn from_char(char: u8) ?Tile {
return switch (char) {
'.' => .Empty,
'#' => .Galaxy,
else => null
};
}
};
const GalaxyMap = struct {
allocator: Allocator,
width: u32,
height: u32,
tiles: []Tile,
fn deinit(self: GalaxyMap) void {
self.allocator.free(self.tiles);
}
fn print(self: GalaxyMap) void {
for (0..self.height) |y| {
for (0..self.width) |x| {
const idx = y * self.width + x;
std.debug.print("{c}", .{self.tiles[idx].to_char()});
}
std.debug.print("\n", .{});
}
}
};
fn parse_input(allocator: Allocator, lines: []const []const u8) !GalaxyMap {
var height: u32 = @intCast(lines.len);
var width: u32 = @intCast(lines[0].len);
var tile_map = try allocator.alloc(Tile, width * height);
errdefer allocator.free(tile_map);
for (0.., lines) |y, line| {
for (0.., line) |x, char| {
const idx = width * y + x;
tile_map[idx] = Tile.from_char(char) orelse .Empty;
}
}
return GalaxyMap{
.allocator = allocator,
.width = width,
.height = height,
.tiles = tile_map
};
}
fn list_galaxies(allocator: Allocator, map: GalaxyMap) !ArrayList(Point) {
var points = ArrayList(Point).init(allocator);
errdefer points.deinit();
for (0..map.height) |y| {
for (0..map.width) |x| {
const idx = y * map.width + x;
if (map.tiles[idx] != .Galaxy) continue;
try points.append(Point{
.x = @intCast(x),
.y = @intCast(y)
});
}
}
return points;
}
fn is_row_empty(map: GalaxyMap, y: u32) bool {
for (0..map.width) |x| {
const idx = map.width * y + x;
if (map.tiles[idx] != .Empty) return false;
}
return true;
}
fn is_column_empty(map: GalaxyMap, x: u32) bool {
for (0..map.height) |y| {
const idx = map.width * y + x;
if (map.tiles[idx] != .Empty) return false;
}
return true;
}
fn list_empty_rows(allocator: Allocator, map: GalaxyMap) !ArrayList(u32) {
var rows = ArrayList(u32).init(allocator);
errdefer rows.deinit();
for (0..map.height) |y| {
if (is_row_empty(map, @intCast(y))) {
try rows.append(@intCast(y));
}
}
return rows;
}
fn list_empty_columns(allocator: Allocator, map: GalaxyMap) !ArrayList(u32) {
var columns = ArrayList(u32).init(allocator);
errdefer columns.deinit();
for (0..map.width) |x| {
if (is_column_empty(map, @intCast(x))) {
try columns.append(@intCast(x));
}
}
return columns;
}
fn expand_points(allocator: Allocator, points: []Point, map: GalaxyMap, amount: u32) !void {
const empty_rows = try list_empty_rows(allocator, map);
defer empty_rows.deinit();
const empty_columns = try list_empty_columns(allocator, map);
defer empty_columns.deinit();
for (points) |*p| {
var expand_by: u32 = 0;
for (empty_rows.items) |y| {
if (y < p.y) {
expand_by += 1;
}
}
p.y += expand_by*amount;
}
for (points) |*p| {
var expand_by: u32 = 0;
for (empty_columns.items) |x| {
if (x < p.x) {
expand_by += 1;
}
}
p.x += amount*expand_by;
}
}
fn sum_min_distances(points: []Point) u64 {
var result: u64 = 0;
for (0..(points.len-1)) |i| {
const p1 = points[i];
for ((i+1)..points.len) |j| {
const p2 = points[j];
const dx = @as(i64, @intCast(p1.x)) - @as(i64, @intCast(p2.x));
const dy = @as(i64, @intCast(p1.y)) - @as(i64, @intCast(p2.y));
result += std.math.absCast(dx) + std.math.absCast(dy);
}
}
return result;
}
pub fn part1(input: *aoc.Input) !aoc.Result {
const allocator = input.allocator;
const parsed = try parse_input(allocator, input.lines);
defer parsed.deinit();
var galaxies = try list_galaxies(allocator, parsed);
defer galaxies.deinit();
try expand_points(allocator, galaxies.items, parsed, 1);
return .{ .uint = sum_min_distances(galaxies.items) };
}
pub fn part2(input: *aoc.Input) !aoc.Result {
const allocator = input.allocator;
const parsed = try parse_input(allocator, input.lines);
defer parsed.deinit();
var galaxies = try list_galaxies(allocator, parsed);
defer galaxies.deinit();
try expand_points(allocator, galaxies.items, parsed, 1000000 - 1);
return .{ .uint = sum_min_distances(galaxies.items) };
}
const example_input = [_][]const u8{
"...#......",
".......#..",
"#.........",
"..........",
"......#...",
".#........",
".........#",
"..........",
".......#..",
"#...#....."
};
test "part 1 example" {
try aoc.expectAnswerUInt(part1, 374, &example_input);
}
test "part 2 example" {
try aoc.expectAnswerUInt(part2, 82000210, &example_input);
}

View File

@ -31,6 +31,7 @@ const Days = [_]aoc.Day{
create_day(@import("day8.zig")),
create_day(@import("day9.zig")),
create_day(@import("day10.zig")),
create_day(@import("day11.zig")),
};
fn kilobytes(count: u32) u32 {
@ -185,4 +186,5 @@ test {
_ = @import("day8.zig");
_ = @import("day9.zig");
_ = @import("day10.zig");
_ = @import("day11.zig");
}