You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.2 KiB
129 lines
4.2 KiB
const std = @import("std");
|
|
|
|
fn isSymbol(char: u8) bool {
|
|
return switch (char) {
|
|
'0'...'9' => false,
|
|
'.' => false,
|
|
else => true,
|
|
};
|
|
}
|
|
|
|
const CharInfo = struct {
|
|
adjacents: [8]u8,
|
|
this: u8,
|
|
|
|
fn isAdjacentToSymbol(self: *const CharInfo) bool {
|
|
for (0..8) |i| {
|
|
if (isSymbol(self.adjacents[i])) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const State = struct {
|
|
number: u32 = 0,
|
|
is_adjacent_to_symbol: bool = false,
|
|
|
|
fn addDigit(self: *State, char_info: CharInfo) void {
|
|
self.number = self.number * 10 + (char_info.this - '0');
|
|
self.is_adjacent_to_symbol = self.is_adjacent_to_symbol or char_info.isAdjacentToSymbol();
|
|
}
|
|
};
|
|
|
|
fn solve(engine: [][]const CharInfo) u32 {
|
|
var result: u32 = 0;
|
|
var current_state = State{};
|
|
|
|
for (engine) |line| {
|
|
//std.debug.print("handling new line\n", .{});
|
|
for (line) |char_info| {
|
|
//std.debug.print("handling: {s}({s})\n", .{ [_]u8{char_info.this}, char_info.adjacents });
|
|
switch (char_info.this) {
|
|
'0'...'9' => {
|
|
current_state.addDigit(char_info);
|
|
},
|
|
else => {
|
|
if (current_state.is_adjacent_to_symbol) {
|
|
//std.debug.print("adding: {d}\n", .{current_state.number});
|
|
result += current_state.number;
|
|
}
|
|
|
|
current_state = State{};
|
|
},
|
|
}
|
|
}
|
|
|
|
if (current_state.is_adjacent_to_symbol) {
|
|
//std.debug.print("end of line; adding: {d}\n", .{current_state.number});
|
|
result += current_state.number;
|
|
}
|
|
|
|
current_state = State{};
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
fn charLinesToCharInfoLines(allocator: std.mem.Allocator, char_lines: [][]const u8) ![][]const CharInfo {
|
|
var char_info_lines = try allocator.alloc([]CharInfo, char_lines.len);
|
|
for (0..char_lines.len) |i| {
|
|
const char_line = char_lines[i];
|
|
var char_info_line = try allocator.alloc(CharInfo, char_line.len);
|
|
for (0..char_line.len) |j| {
|
|
char_info_line[j] = CharInfo{ .this = char_line[j], .adjacents = .{
|
|
if (i > 0 and j > 0) char_lines[i - 1][j - 1] else '.',
|
|
if (i > 0) char_lines[i - 1][j] else '.',
|
|
if (i > 0 and j + 1 < char_line.len) char_lines[i - 1][j + 1] else '.',
|
|
if (j > 0) char_line[j - 1] else '.',
|
|
if (j + 1 < char_line.len) char_line[j + 1] else '.',
|
|
if (i + 1 < char_lines.len and j > 0) char_lines[i + 1][j - 1] else '.',
|
|
if (i + 1 < char_lines.len) char_lines[i + 1][j] else '.',
|
|
if (i + 1 < char_lines.len and j + 1 < char_line.len) char_lines[i + 1][j + 1] else '.',
|
|
} };
|
|
}
|
|
|
|
char_info_lines[i] = char_info_line;
|
|
}
|
|
|
|
return char_info_lines;
|
|
}
|
|
|
|
fn readInput(allocator: std.mem.Allocator, reader: anytype) ![][]const u8 {
|
|
var lines = std.ArrayList([]u8).init(allocator);
|
|
var line_buffer: [1000]u8 = undefined;
|
|
while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |line_ref| {
|
|
const line = try allocator.dupe(u8, line_ref);
|
|
try lines.append(line);
|
|
}
|
|
|
|
return lines.items;
|
|
}
|
|
|
|
pub fn main() !void {
|
|
const stdout = std.io.getStdOut().writer();
|
|
|
|
const raw_in = std.io.getStdIn();
|
|
var buffered_reader = std.io.bufferedReader(raw_in.reader());
|
|
var reader = buffered_reader.reader();
|
|
|
|
var allocator_buffer: [1_000_000]u8 = undefined;
|
|
var fba = std.heap.FixedBufferAllocator.init(&allocator_buffer);
|
|
var allocator = fba.allocator();
|
|
|
|
var lines_arena = std.heap.ArenaAllocator.init(allocator);
|
|
const lines_allocator = lines_arena.allocator();
|
|
const char_lines = try readInput(lines_allocator, reader);
|
|
|
|
var info_lines_arena = std.heap.ArenaAllocator.init(allocator);
|
|
const info_lines_allocator = info_lines_arena.allocator();
|
|
const info_lines = try charLinesToCharInfoLines(info_lines_allocator, char_lines);
|
|
lines_arena.deinit();
|
|
|
|
const result = solve(info_lines);
|
|
info_lines_arena.deinit();
|
|
|
|
try stdout.print("{d}\n", .{result});
|
|
}
|
|
|