solve day 3

This commit is contained in:
Rokas Puzonas 2023-12-08 22:03:02 +02:00
parent 59ac1720b9
commit b863e1b2aa
3 changed files with 161 additions and 1 deletions

146
src/day3.zig Normal file
View File

@ -0,0 +1,146 @@
const aoc = @import("./aoc.zig");
const std = @import("std");
const Point = @import("./point.zig").Point;
const PointU32 = Point(u32);
const PointList = std.ArrayList(PointU32);
fn find_number_start(line: []const u8, from: u32) u32 {
var i = from;
while (i > 0) : (i -= 1) {
if (!std.ascii.isDigit(line[i-1])) { break; }
}
return i;
}
fn find_number_end(line: []const u8, from: u32) u32 {
var i = from;
while (i < line.len-1) : (i += 1) {
if (!std.ascii.isDigit(line[i+1])) { break; }
}
return i+1;
}
fn append_unique(list: *PointList, point: PointU32) !void {
for (list.items) |item| {
if (item.eql(&point)) { return; }
}
try list.append(point);
}
fn find_neighbouring_numbers(found_list: *PointList, lines: [][]const u8, x: usize, y: usize) !void {
const neighbours = .{
.{ -1, -1 }, .{ 0, -1 }, .{ 1, -1 },
.{ -1, 0 }, .{ 1, 0 },
.{ -1, 1 }, .{ 0, 1 }, .{ 1, 1 },
};
inline for (neighbours) |offset| {
const nx = @as(i32, @intCast(x)) + offset[0];
const ny = @as(i32, @intCast(y)) + offset[1];
if ((nx >= 0 or ny >= 0 or nx < lines[y].len or ny < lines.len)) {
const nx_u32: u32 = @intCast(nx);
const ny_u32: u32 = @intCast(ny);
if (std.ascii.isDigit(lines[ny_u32][nx_u32])) {
const number_start = find_number_start(lines[ny_u32], nx_u32);
try append_unique(found_list, .{ .x = number_start, .y = ny_u32 });
}
}
}
}
pub fn part1(input: *aoc.Input) !aoc.Result {
const lines = input.lines;
const allocator = input.allocator;
var numbers = PointList.init(allocator);
defer numbers.deinit();
for (lines, 0..) |line, y| {
for (line, 0..) |c, x| {
if (std.ascii.isDigit(c) or c == '.') { continue; }
try find_neighbouring_numbers(&numbers, lines, x, y);
}
}
var sum: u32 = 0;
for (numbers.items) |number_pos| {
const line = lines[number_pos.y];
const number_end = find_number_end(line, number_pos.x);
const number_str = line[number_pos.x..number_end];
sum += try std.fmt.parseInt(u32, number_str, 10);
}
return .{ .uint = sum };
}
pub fn part2(input: *aoc.Input) !aoc.Result {
const lines = input.lines;
const allocator = input.allocator;
var sum: u32 = 0;
for (lines, 0..) |line, y| {
for (line, 0..) |c, x| {
if (c != '*') { continue; }
var numbers = PointList.init(allocator);
defer numbers.deinit();
try find_neighbouring_numbers(&numbers, lines, x, y);
if (numbers.items.len != 2) continue;
var gear_ratio: u32 = 1;
for (numbers.items) |number_pos| {
const number_line = lines[number_pos.y];
const number_end = find_number_end(number_line, number_pos.x);
const number_str = number_line[number_pos.x..number_end];
const number = try std.fmt.parseInt(u32, number_str, 10);
gear_ratio *= number;
}
sum += gear_ratio;
}
}
return .{ .uint = sum };
}
test "part 1 example" {
var lines = [_][]const u8{
"467..114..",
"...*......",
"..35..633.",
"......#...",
"617*......",
".....+.58.",
"..592.....",
"......755.",
"...$.*....",
".664.598.."
};
var input = aoc.Input{ .lines = &lines, .allocator = std.testing.allocator };
var actual = try part1(&input);
var expected: u32 = 4361;
try std.testing.expectEqual(expected, actual.uint);
}
test "part 2 example" {
var lines = [_][]const u8{
"467..114..",
"...*......",
"..35..633.",
"......#...",
"617*......",
".....+.58.",
"..592.....",
"......755.",
"...$.*....",
".664.598.."
};
var input = aoc.Input{ .lines = &lines, .allocator = std.testing.allocator };
var actual = try part2(&input);
var expected: u32 = 467835;
try std.testing.expectEqual(expected, actual.uint);
}

View File

@ -21,7 +21,8 @@ fn create_day(comptime module: anytype) aoc.Day {
const Days = [_]aoc.Day{
create_day(@import("day1.zig")),
create_day(@import("day2.zig"))
create_day(@import("day2.zig")),
create_day(@import("day3.zig"))
};
pub fn main() !u8 {
@ -98,4 +99,5 @@ pub fn main() !u8 {
test {
_ = @import("day1.zig");
_ = @import("day2.zig");
_ = @import("day3.zig");
}

12
src/point.zig Normal file
View File

@ -0,0 +1,12 @@
pub fn Point(comptime T: type) type {
return struct {
const Self = @This();
x: T,
y: T,
pub fn eql(self: *const Self, other: *const Self) bool {
return self.x == other.x and self.y == other.y;
}
};
}