solve day 3
This commit is contained in:
parent
59ac1720b9
commit
b863e1b2aa
146
src/day3.zig
Normal file
146
src/day3.zig
Normal 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);
|
||||||
|
}
|
@ -21,7 +21,8 @@ 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"))
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() !u8 {
|
pub fn main() !u8 {
|
||||||
@ -98,4 +99,5 @@ pub fn main() !u8 {
|
|||||||
test {
|
test {
|
||||||
_ = @import("day1.zig");
|
_ = @import("day1.zig");
|
||||||
_ = @import("day2.zig");
|
_ = @import("day2.zig");
|
||||||
|
_ = @import("day3.zig");
|
||||||
}
|
}
|
||||||
|
12
src/point.zig
Normal file
12
src/point.zig
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user