solve day 13
This commit is contained in:
parent
71d4c1bf17
commit
c36f8c6805
235
src/day13.zig
Normal file
235
src/day13.zig
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const aoc = @import("./aoc.zig");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
const Map = struct {
|
||||||
|
tiles: std.ArrayList(bool),
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
|
||||||
|
fn deinit(self: Map) void {
|
||||||
|
self.tiles.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print(self: Map) void {
|
||||||
|
for (0..self.height) |y| {
|
||||||
|
for (0..self.width) |x| {
|
||||||
|
const idx = y * self.width + x;
|
||||||
|
if (self.tiles.items[idx]) {
|
||||||
|
std.debug.print("#", .{});
|
||||||
|
} else {
|
||||||
|
std.debug.print(".", .{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std.debug.print("\n", .{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(self: Map, x: u32, y: u32) bool {
|
||||||
|
assert(x < self.width);
|
||||||
|
assert(y < self.height);
|
||||||
|
return self.tiles.items[y * self.width + x];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Input = struct {
|
||||||
|
maps: std.ArrayList(Map),
|
||||||
|
|
||||||
|
fn init(allocator: Allocator) Input {
|
||||||
|
return Input{
|
||||||
|
.maps = std.ArrayList(Map).init(allocator)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(self: Input) void {
|
||||||
|
for (self.maps.items) |map| {
|
||||||
|
map.deinit();
|
||||||
|
}
|
||||||
|
self.maps.deinit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn parse_map(allocator: Allocator, lines: []const []const u8) !Map {
|
||||||
|
var width: u32 = @intCast(lines[0].len);
|
||||||
|
var height: u32 = @intCast(lines.len);
|
||||||
|
var tiles = try std.ArrayList(bool).initCapacity(allocator, width*height);
|
||||||
|
errdefer tiles.deinit();
|
||||||
|
|
||||||
|
for (lines) |line| {
|
||||||
|
for (line) |tile| {
|
||||||
|
try tiles.append(tile == '#');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Map{
|
||||||
|
.tiles = tiles,
|
||||||
|
.width = width,
|
||||||
|
.height = height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(allocator: Allocator, lines: []const []const u8) !Input {
|
||||||
|
var parsed = Input.init(allocator);
|
||||||
|
errdefer parsed.deinit();
|
||||||
|
|
||||||
|
var first_map_line: usize = 0;
|
||||||
|
for (0.., lines) |i, line| {
|
||||||
|
if (line.len == 0) {
|
||||||
|
const map_lines = lines[first_map_line..i];
|
||||||
|
try parsed.maps.append(try parse_map(allocator, map_lines));
|
||||||
|
first_map_line = i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first_map_line != lines.len) {
|
||||||
|
const map_lines = lines[first_map_line..];
|
||||||
|
try parsed.maps.append(try parse_map(allocator, map_lines));
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_horizontal_reflection(map: Map, reflect_x: u32) bool {
|
||||||
|
assert(reflect_x < map.width-1);
|
||||||
|
const left_start = reflect_x;
|
||||||
|
const right_start = reflect_x + 1;
|
||||||
|
|
||||||
|
const distance_to_edge = @min(map.width - right_start, left_start + 1);
|
||||||
|
for (0..map.height) |y| {
|
||||||
|
for (0..distance_to_edge) |offset| {
|
||||||
|
const left_cursor = left_start - @as(u32, @intCast(offset));
|
||||||
|
const right_cursor = right_start + @as(u32, @intCast(offset));
|
||||||
|
|
||||||
|
const left_tile = map.get(left_cursor , @intCast(y));
|
||||||
|
const right_tile = map.get(right_cursor, @intCast(y));
|
||||||
|
if (left_tile != right_tile) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_horizontal_reflection(map: Map, skip_x: ?u32) ?u32 {
|
||||||
|
for (0..map.width-1) |x| {
|
||||||
|
const x_u32: u32 = @intCast(x);
|
||||||
|
if (x_u32 == skip_x) continue;
|
||||||
|
if (check_horizontal_reflection(map, x_u32)) {
|
||||||
|
return @intCast(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_vertical_reflection(map: Map, reflect_y: u32) bool {
|
||||||
|
assert(reflect_y < map.height-1);
|
||||||
|
const top_start = reflect_y;
|
||||||
|
const bottom_start = reflect_y + 1;
|
||||||
|
|
||||||
|
const distance_to_edge = @min(map.height - bottom_start, top_start + 1);
|
||||||
|
for (0..map.width) |x| {
|
||||||
|
for (0..distance_to_edge) |offset| {
|
||||||
|
const top_cursor = top_start - @as(u32, @intCast(offset));
|
||||||
|
const bottom_cursor = bottom_start + @as(u32, @intCast(offset));
|
||||||
|
|
||||||
|
const top_tile = map.get(@intCast(x), top_cursor);
|
||||||
|
const bottom_tile = map.get(@intCast(x), bottom_cursor);
|
||||||
|
if (top_tile != bottom_tile) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_vertical_reflection(map: Map, skip_y: ?u32) ?u32 {
|
||||||
|
for (0..map.height-1) |y| {
|
||||||
|
const y_u32: u32 = @intCast(y);
|
||||||
|
if (y_u32 == skip_y) continue;
|
||||||
|
if (check_vertical_reflection(map, y_u32)) {
|
||||||
|
return @intCast(y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part1(input: *aoc.Input) !aoc.Result {
|
||||||
|
var parsed = try parse_input(input.allocator, input.lines);
|
||||||
|
defer parsed.deinit();
|
||||||
|
|
||||||
|
var result: u64 = 0;
|
||||||
|
for (parsed.maps.items) |map| {
|
||||||
|
if (find_horizontal_reflection(map, null)) |x| {
|
||||||
|
result += (x+1);
|
||||||
|
}
|
||||||
|
if (find_vertical_reflection(map, null)) |y| {
|
||||||
|
result += 100 * (y+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{ .uint = result };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(input: *aoc.Input) !aoc.Result {
|
||||||
|
var parsed = try parse_input(input.allocator, input.lines);
|
||||||
|
defer parsed.deinit();
|
||||||
|
|
||||||
|
var result: u64 = 0;
|
||||||
|
for (parsed.maps.items) |map| {
|
||||||
|
const original_reflect_x = find_horizontal_reflection(map, null);
|
||||||
|
const original_reflect_y = find_vertical_reflection(map, null);
|
||||||
|
|
||||||
|
var reflect_x: ?u32 = null;
|
||||||
|
var reflect_y: ?u32 = null;
|
||||||
|
const tiles = map.tiles.items;
|
||||||
|
for (0..tiles.len) |i| {
|
||||||
|
tiles[i] = !tiles[i];
|
||||||
|
reflect_x = find_horizontal_reflection(map, original_reflect_x);
|
||||||
|
reflect_y = find_vertical_reflection(map, original_reflect_y);
|
||||||
|
tiles[i] = !tiles[i];
|
||||||
|
|
||||||
|
if (reflect_x != null or reflect_y != null) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(reflect_x != null or reflect_y != null);
|
||||||
|
if (reflect_x) |x| {
|
||||||
|
result += (x+1);
|
||||||
|
}
|
||||||
|
if (reflect_y) |y| {
|
||||||
|
result += 100 * (y+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{ .uint = result };
|
||||||
|
}
|
||||||
|
|
||||||
|
const example_input = &.{
|
||||||
|
"#.##..##.",
|
||||||
|
"..#.##.#.",
|
||||||
|
"##......#",
|
||||||
|
"##......#",
|
||||||
|
"..#.##.#.",
|
||||||
|
"..##..##.",
|
||||||
|
"#.#.##.#.",
|
||||||
|
"",
|
||||||
|
"#...##..#",
|
||||||
|
"#....#..#",
|
||||||
|
"..##..###",
|
||||||
|
"#####.##.",
|
||||||
|
"#####.##.",
|
||||||
|
"..##..###",
|
||||||
|
"#....#..#",
|
||||||
|
};
|
||||||
|
|
||||||
|
test "part 1 example" {
|
||||||
|
try aoc.expectAnswerUInt(part1, 405, &example_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "part 2 example" {
|
||||||
|
try aoc.expectAnswerUInt(part2, 400, &example_input);
|
||||||
|
}
|
@ -33,6 +33,7 @@ const Days = [_]aoc.Day{
|
|||||||
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")),
|
||||||
};
|
};
|
||||||
|
|
||||||
fn kilobytes(count: u32) u32 {
|
fn kilobytes(count: u32) u32 {
|
||||||
|
Loading…
Reference in New Issue
Block a user