solve day 11
This commit is contained in:
parent
6e6cd59ea4
commit
08222a641e
217
src/day11.zig
Normal file
217
src/day11.zig
Normal 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);
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user