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.

144 lines
4.6 KiB

7 months ago
const std = @import("std");
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,
};
7 months ago
const CharInfo = struct {
adjacents: [8]Char,
this: Char,
7 months ago
fn isAdjacentToSymbol(self: *const CharInfo) bool {
for (0..8) |i| {
if (self.adjacents[i] == .Symbol) {
7 months ago
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 + @intFromEnum(char_info.this);
7 months ago
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) {
.Zero, .One, .Two, .Three, .Four, .Five, .Six, .Seven, .Eight, .Nine => {
7 months ago
current_state.addDigit(char_info);
},
.Dot, .Symbol => {
7 months ago
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 Char) ![][]const CharInfo {
7 months ago
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 .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,
7 months ago
} };
}
char_info_lines[i] = char_info_line;
}
return char_info_lines;
}
fn readInput(allocator: std.mem.Allocator, reader: anytype) ![][]const Char {
var lines = std.ArrayList([]Char).init(allocator);
7 months ago
var line_buffer: [1000]u8 = undefined;
while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |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,
};
}
7 months ago
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});
}