Solutions of most (39 out of 50 so far) puzzles in Zig (system language, alternative for C). My first experience with it.
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.

130 lines
4.2 KiB

10 months ago
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});
}