solve day 14
This commit is contained in:
parent
c36f8c6805
commit
31c2a661c2
@ -195,7 +195,7 @@ pub fn part2(input: *aoc.Input) !aoc.Result {
|
|||||||
return .{ .uint = sum_min_distances(galaxies.items) };
|
return .{ .uint = sum_min_distances(galaxies.items) };
|
||||||
}
|
}
|
||||||
|
|
||||||
const example_input = [_][]u8{
|
const example_input = [_][]const u8{
|
||||||
"...#......",
|
"...#......",
|
||||||
".......#..",
|
".......#..",
|
||||||
"#.........",
|
"#.........",
|
||||||
|
@ -208,7 +208,7 @@ pub fn part2(input: *aoc.Input) !aoc.Result {
|
|||||||
return .{ .uint = result };
|
return .{ .uint = result };
|
||||||
}
|
}
|
||||||
|
|
||||||
const example_input = &.{
|
const example_input = [_][]const u8{
|
||||||
"#.##..##.",
|
"#.##..##.",
|
||||||
"..#.##.#.",
|
"..#.##.#.",
|
||||||
"##......#",
|
"##......#",
|
||||||
|
233
src/day14.zig
Normal file
233
src/day14.zig
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const aoc = @import("./aoc.zig");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const PointU32 = @import("./point.zig").Point(u32);
|
||||||
|
|
||||||
|
const Tile = enum {
|
||||||
|
Empty,
|
||||||
|
Rock,
|
||||||
|
Wall
|
||||||
|
};
|
||||||
|
|
||||||
|
const Input = struct {
|
||||||
|
tiles: std.ArrayList(Tile),
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
|
||||||
|
fn init(allocator: Allocator) Input {
|
||||||
|
return Input{
|
||||||
|
.tiles = std.ArrayList(Tile).init(allocator),
|
||||||
|
.width = 0,
|
||||||
|
.height = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(self: Input) void {
|
||||||
|
self.tiles.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_idx(self: Input, x: u32, y: u32) usize {
|
||||||
|
assert(x < self.width);
|
||||||
|
assert(y < self.height);
|
||||||
|
return y * self.width + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(self: Input, x: u32, y: u32) Tile {
|
||||||
|
return self.tiles.items[self.get_idx(x, y)];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(self: Input, x: u32, y: u32, tile: Tile) void {
|
||||||
|
self.tiles.items[self.get_idx(x, y)] = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn in_bounds(self: Input, x: i32, y: i32) bool {
|
||||||
|
return (0 <= x and x < self.width) and (0 <= y and y < self.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print(self: Input) void {
|
||||||
|
for (0..self.height) |y| {
|
||||||
|
for (0..self.height) |x| {
|
||||||
|
const idx = y * self.width + x;
|
||||||
|
const tile = self.tiles.items[idx];
|
||||||
|
const symbol: u8 = switch (tile) {
|
||||||
|
.Empty => '.',
|
||||||
|
.Wall => '#',
|
||||||
|
.Rock => 'O'
|
||||||
|
};
|
||||||
|
|
||||||
|
std.debug.print("{c}", .{symbol});
|
||||||
|
}
|
||||||
|
std.debug.print("\n", .{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn parse_input(allocator: Allocator, lines: []const []const u8) !Input {
|
||||||
|
var parsed = Input.init(allocator);
|
||||||
|
errdefer parsed.deinit();
|
||||||
|
parsed.width = @intCast(lines[0].len);
|
||||||
|
parsed.height = @intCast(lines.len);
|
||||||
|
|
||||||
|
try parsed.tiles.ensureTotalCapacity(parsed.width * parsed.height);
|
||||||
|
|
||||||
|
for (lines) |line| {
|
||||||
|
for (line) |symbol| {
|
||||||
|
const tile = switch (symbol) {
|
||||||
|
'O' => Tile.Rock,
|
||||||
|
'.' => Tile.Empty,
|
||||||
|
'#' => Tile.Wall,
|
||||||
|
else => return error.InvalidTile
|
||||||
|
};
|
||||||
|
|
||||||
|
try parsed.tiles.append(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slide_rock(input: Input, x: u32, y: u32, dir_x: i32, dir_y: i32) void {
|
||||||
|
assert(input.get(x, y) == .Rock);
|
||||||
|
|
||||||
|
var new_x = x;
|
||||||
|
var new_y = y;
|
||||||
|
while (true) {
|
||||||
|
const next_x = @as(i32, @intCast(new_x)) + dir_x;
|
||||||
|
const next_y = @as(i32, @intCast(new_y)) + dir_y;
|
||||||
|
if (!input.in_bounds(next_x, next_y)) break;
|
||||||
|
if (input.get(@intCast(next_x), @intCast(next_y)) != .Empty) break;
|
||||||
|
|
||||||
|
new_x = @intCast(next_x);
|
||||||
|
new_y = @intCast(next_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
input.set(x, y, .Empty);
|
||||||
|
input.set(new_x, new_y, .Rock);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slide_rocks(input: Input, dir_x: i32, dir_y: i32) void {
|
||||||
|
if (dir_y != 0) {
|
||||||
|
// Column-based
|
||||||
|
for (0..input.height) |oy| {
|
||||||
|
for (0..input.width) |ox| {
|
||||||
|
const x: u32 = @intCast(ox);
|
||||||
|
const y: u32 = @intCast(@as(i32, @intCast(oy)) * (-dir_y) + @divExact(dir_y + 1, 2) * @as(i32, @intCast(input.height-1)));
|
||||||
|
if (input.get(x, y) == .Rock) {
|
||||||
|
slide_rock(input, x, y, dir_x, dir_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Row-based
|
||||||
|
for (0..input.width) |ox| {
|
||||||
|
for (0..input.height) |oy| {
|
||||||
|
const x: u32 = @intCast(@as(i32, @intCast(ox)) * (-dir_x) + @divExact(dir_x + 1, 2) * @as(i32, @intCast(input.width-1)));
|
||||||
|
const y: u32 = @intCast(oy);
|
||||||
|
if (input.get(x, y) == .Rock) {
|
||||||
|
slide_rock(input, x, y, dir_x, dir_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cycle_slide(input: Input) void {
|
||||||
|
const dirs = &.{
|
||||||
|
.{ .x = 0, .y = -1 }, // North
|
||||||
|
.{ .x = -1, .y = 0 }, // West
|
||||||
|
.{ .x = 0, .y = 1 }, // South
|
||||||
|
.{ .x = 1, .y = 0 }, // East
|
||||||
|
};
|
||||||
|
|
||||||
|
inline for (dirs) |dir| {
|
||||||
|
slide_rocks(input, dir.x, dir.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_total_load(input: Input) u64 {
|
||||||
|
var result: u64 = 0;
|
||||||
|
for (0..input.height) |y| {
|
||||||
|
var count: u32 = 0;
|
||||||
|
for (0..input.width) |x| {
|
||||||
|
if (input.get(@intCast(x), @intCast(y)) == .Rock) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += count * (input.height - y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part1(input: *aoc.Input) !aoc.Result {
|
||||||
|
const parsed = try parse_input(input.allocator, input.lines);
|
||||||
|
defer parsed.deinit();
|
||||||
|
|
||||||
|
slide_rocks(parsed, 0, -1);
|
||||||
|
|
||||||
|
return .{ .uint = get_total_load(parsed) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(input: *aoc.Input) !aoc.Result {
|
||||||
|
const target_cycle_count = 1000000000;
|
||||||
|
|
||||||
|
const allocator = input.allocator;
|
||||||
|
const parsed = try parse_input(allocator, input.lines);
|
||||||
|
defer parsed.deinit();
|
||||||
|
|
||||||
|
var seen = std.ArrayList(std.ArrayList(Tile)).init(allocator);
|
||||||
|
defer {
|
||||||
|
for (seen.items) |tiles| {
|
||||||
|
tiles.deinit();
|
||||||
|
}
|
||||||
|
seen.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
var cycle_size: u32 = 0;
|
||||||
|
var cycle_start: u32 = 0;
|
||||||
|
var iteration: u32 = 0;
|
||||||
|
outer: while (true) {
|
||||||
|
cycle_slide(parsed);
|
||||||
|
|
||||||
|
for (0.., seen.items) |i, tiles| {
|
||||||
|
if (std.mem.eql(Tile, tiles.items, parsed.tiles.items)) {
|
||||||
|
cycle_start = @intCast(i);
|
||||||
|
cycle_size = @intCast(iteration - i);
|
||||||
|
break :outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try seen.append(try parsed.tiles.clone());
|
||||||
|
|
||||||
|
iteration += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const skipped_map = Input{
|
||||||
|
.tiles = seen.items[@mod((target_cycle_count-1) - cycle_start, cycle_size) + cycle_start],
|
||||||
|
.width = parsed.width,
|
||||||
|
.height = parsed.height
|
||||||
|
};
|
||||||
|
|
||||||
|
return .{ .uint = get_total_load(skipped_map) };
|
||||||
|
}
|
||||||
|
|
||||||
|
const example_input = [_][]const u8{
|
||||||
|
"O....#....",
|
||||||
|
"O.OO#....#",
|
||||||
|
".....##...",
|
||||||
|
"OO.#O....O",
|
||||||
|
".O.....O#.",
|
||||||
|
"O.#..O.#.#",
|
||||||
|
"..O..#O..O",
|
||||||
|
".......O..",
|
||||||
|
"#....###..",
|
||||||
|
"#OO..#....",
|
||||||
|
};
|
||||||
|
|
||||||
|
test "part 1 example" {
|
||||||
|
try aoc.expectAnswerUInt(part1, 136, &example_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "part 2 example" {
|
||||||
|
try aoc.expectAnswerUInt(part2, 64, &example_input);
|
||||||
|
}
|
53
src/main.zig
53
src/main.zig
@ -21,19 +21,20 @@ fn create_day(comptime module: anytype) aoc.Day {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Days = [_]aoc.Day{
|
const Days = [_]aoc.Day{
|
||||||
create_day(@import("day1.zig")),
|
create_day(@import("./day1.zig")),
|
||||||
create_day(@import("day2.zig")),
|
create_day(@import("./day2.zig")),
|
||||||
create_day(@import("day3.zig")),
|
create_day(@import("./day3.zig")),
|
||||||
create_day(@import("day4.zig")),
|
create_day(@import("./day4.zig")),
|
||||||
create_day(@import("day5.zig")),
|
create_day(@import("./day5.zig")),
|
||||||
create_day(@import("day6.zig")),
|
create_day(@import("./day6.zig")),
|
||||||
create_day(@import("day7.zig")),
|
create_day(@import("./day7.zig")),
|
||||||
create_day(@import("day8.zig")),
|
create_day(@import("./day8.zig")),
|
||||||
create_day(@import("day9.zig")),
|
create_day(@import("./day9.zig")),
|
||||||
create_day(@import("day10.zig")),
|
create_day(@import("./day10.zig")),
|
||||||
create_day(@import("day11.zig")),
|
create_day(@import("./day11.zig")),
|
||||||
create_day(@import("day12.zig")),
|
create_day(@import("./day12.zig")),
|
||||||
create_day(@import("day13.zig")),
|
create_day(@import("./day13.zig")),
|
||||||
|
create_day(@import("./day14.zig")),
|
||||||
};
|
};
|
||||||
|
|
||||||
fn kilobytes(count: u32) u32 {
|
fn kilobytes(count: u32) u32 {
|
||||||
@ -178,16 +179,18 @@ pub fn main() !u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
_ = @import("day1.zig");
|
_ = @import("./day1.zig");
|
||||||
_ = @import("day2.zig");
|
_ = @import("./day2.zig");
|
||||||
_ = @import("day3.zig");
|
_ = @import("./day3.zig");
|
||||||
_ = @import("day4.zig");
|
_ = @import("./day4.zig");
|
||||||
_ = @import("day5.zig");
|
_ = @import("./day5.zig");
|
||||||
_ = @import("day6.zig");
|
_ = @import("./day6.zig");
|
||||||
_ = @import("day7.zig");
|
_ = @import("./day7.zig");
|
||||||
_ = @import("day8.zig");
|
_ = @import("./day8.zig");
|
||||||
_ = @import("day9.zig");
|
_ = @import("./day9.zig");
|
||||||
_ = @import("day10.zig");
|
_ = @import("./day10.zig");
|
||||||
_ = @import("day11.zig");
|
_ = @import("./day11.zig");
|
||||||
_ = @import("day12.zig");
|
_ = @import("./day12.zig");
|
||||||
|
_ = @import("./day13.zig");
|
||||||
|
_ = @import("./day14.zig");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user