|
|
|
@ -1,20 +1,27 @@ |
|
|
|
|
const std = @import("std"); |
|
|
|
|
|
|
|
|
|
fn isSymbol(char: u8) bool { |
|
|
|
|
return switch (char) { |
|
|
|
|
'0'...'9' => false, |
|
|
|
|
'.' => false, |
|
|
|
|
else => true, |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
const Char = enum(u4) { |
|
|
|
|
Zero = 0, |
|
|
|
|
One = 1, |
|
|
|
|
Two = 2, |
|
|
|
|
Three = 3, |
|
|
|
|
Four = 4, |
|
|
|
|
Five = 5, |
|
|
|
|
Six = 6, |
|
|
|
|
Seven = 7, |
|
|
|
|
Eight = 8, |
|
|
|
|
Nine = 9, |
|
|
|
|
Dot = 12, |
|
|
|
|
Symbol = 13, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const CharInfo = struct { |
|
|
|
|
adjacents: [8]u8, |
|
|
|
|
this: u8, |
|
|
|
|
adjacents: [8]Char, |
|
|
|
|
this: Char, |
|
|
|
|
|
|
|
|
|
fn isAdjacentToSymbol(self: *const CharInfo) bool { |
|
|
|
|
for (0..8) |i| { |
|
|
|
|
if (isSymbol(self.adjacents[i])) { |
|
|
|
|
if (self.adjacents[i] == .Symbol) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -28,7 +35,7 @@ const State = struct { |
|
|
|
|
is_adjacent_to_symbol: bool = false, |
|
|
|
|
|
|
|
|
|
fn addDigit(self: *State, char_info: CharInfo) void { |
|
|
|
|
self.number = self.number * 10 + (char_info.this - '0'); |
|
|
|
|
self.number = self.number * 10 + @intFromEnum(char_info.this); |
|
|
|
|
self.is_adjacent_to_symbol = self.is_adjacent_to_symbol or char_info.isAdjacentToSymbol(); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
@ -42,10 +49,10 @@ fn solve(engine: [][]const CharInfo) u32 { |
|
|
|
|
for (line) |char_info| { |
|
|
|
|
//std.debug.print("handling: {s}({s})\n", .{ [_]u8{char_info.this}, char_info.adjacents }); |
|
|
|
|
switch (char_info.this) { |
|
|
|
|
'0'...'9' => { |
|
|
|
|
.Zero, .One, .Two, .Three, .Four, .Five, .Six, .Seven, .Eight, .Nine => { |
|
|
|
|
current_state.addDigit(char_info); |
|
|
|
|
}, |
|
|
|
|
else => { |
|
|
|
|
.Dot, .Symbol => { |
|
|
|
|
if (current_state.is_adjacent_to_symbol) { |
|
|
|
|
//std.debug.print("adding: {d}\n", .{current_state.number}); |
|
|
|
|
result += current_state.number; |
|
|
|
@ -67,21 +74,21 @@ fn solve(engine: [][]const CharInfo) u32 { |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn charLinesToCharInfoLines(allocator: std.mem.Allocator, char_lines: [][]const u8) ![][]const CharInfo { |
|
|
|
|
fn charLinesToCharInfoLines(allocator: std.mem.Allocator, char_lines: [][]const Char) ![][]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 '.', |
|
|
|
|
if (i > 0 and j > 0) char_lines[i - 1][j - 1] else .Dot, |
|
|
|
|
if (i > 0) char_lines[i - 1][j] else .Dot, |
|
|
|
|
if (i > 0 and j + 1 < char_line.len) char_lines[i - 1][j + 1] else .Dot, |
|
|
|
|
if (j > 0) char_line[j - 1] else .Dot, |
|
|
|
|
if (j + 1 < char_line.len) char_line[j + 1] else .Dot, |
|
|
|
|
if (i + 1 < char_lines.len and j > 0) char_lines[i + 1][j - 1] else .Dot, |
|
|
|
|
if (i + 1 < char_lines.len) char_lines[i + 1][j] else .Dot, |
|
|
|
|
if (i + 1 < char_lines.len and j + 1 < char_line.len) char_lines[i + 1][j + 1] else .Dot, |
|
|
|
|
} }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -91,11 +98,18 @@ fn charLinesToCharInfoLines(allocator: std.mem.Allocator, char_lines: [][]const |
|
|
|
|
return char_info_lines; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn readInput(allocator: std.mem.Allocator, reader: anytype) ![][]const u8 { |
|
|
|
|
var lines = std.ArrayList([]u8).init(allocator); |
|
|
|
|
fn readInput(allocator: std.mem.Allocator, reader: anytype) ![][]const Char { |
|
|
|
|
var lines = std.ArrayList([]Char).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); |
|
|
|
|
var line = try allocator.alloc(Char, line_ref.len); |
|
|
|
|
for (line_ref, line) |raw_char, *char| { |
|
|
|
|
char.* = switch (raw_char) { |
|
|
|
|
'0'...'9' => @enumFromInt(raw_char - '0'), |
|
|
|
|
'.' => .Dot, |
|
|
|
|
else => .Symbol, |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
try lines.append(line); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|