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.

175 lines
4.4 KiB

const std = @import("std");
fn StackList(comptime T: type, comptime capacity_type: type, comptime capacity: capacity_type) type {
return struct {
const Self = @This();
mem: [capacity]T,
length: capacity_type,
fn add(self: *Self, value: T) void {
self.mem[self.length] = value;
self.length += 1;
}
fn has(self: *Self, needle: T) bool {
for (0..self.length) |i| {
if (self.mem[i] == needle) {
return true;
}
}
return false;
}
fn getMutableSlice(self: *Self) []T {
return (&self.mem)[0..self.length];
}
fn getSlice(self: *const Self) []const T {
return self.mem[0..self.length];
}
fn init() Self {
return Self{
.mem = undefined,
.length = 0,
};
}
};
}
fn addDigit(result: anytype, digit: u8) void {
result.* = (result.* * 10) + (digit - '0');
}
fn canStartWithGroup(springs: []const u8, group_size: usize) bool {
if (springs.len < group_size) {
return false;
}
if (springs.len > group_size and springs[group_size] == '#') {
return false;
}
var i: usize = 0;
while (i < group_size) : (i += 1) {
if (springs[i] == '.') {
return false;
}
}
return true;
}
const State = [128][32]u64;
fn solve(springs: []const u8, groups: []const usize, state: *State) u64 {
if (state[springs.len][groups.len] != std.math.maxInt(u64)) {
return state[springs.len][groups.len];
}
if (groups.len == 0) {
for (springs) |char| {
if (char == '#') {
state[springs.len][groups.len] = 0;
return 0;
}
}
state[springs.len][groups.len] = 1;
return 1;
}
const first_group_size = groups[0];
if (first_group_size > springs.len) {
state[springs.len][groups.len] = 0;
return 0;
}
const last_check_index = springs.len + 1 - first_group_size;
var i: usize = 0;
var result: u64 = 0;
while (i < last_check_index) : (i += 1) {
switch (springs[i]) {
'.' => {},
'#' => {
if (canStartWithGroup(springs[i..], first_group_size)) {
result += solve(springs[@min(springs.len, i + first_group_size + 1)..], groups[1..], &(state.*));
}
break;
},
'?' => {
if (canStartWithGroup(springs[i..], first_group_size)) {
result += solve(springs[@min(springs.len, i + first_group_size + 1)..], groups[1..], &(state.*));
}
},
else => unreachable,
}
}
state[springs.len][groups.len] = result;
return result;
}
fn solveLine(line: []const u8) u64 {
var i: usize = 0;
while (line[i] != ' ') : (i += 1) {}
var springs = line[0..i];
i += 1;
var groups = StackList(usize, usize, 31).init();
while (i < line.len) {
var number: usize = 0;
while (i < line.len and line[i] != ',') : (i += 1) {
addDigit(&number, line[i]);
}
groups.add(number);
i += 1;
}
const groups_length = groups.length;
for (0..4) |j| {
_ = j;
for (0..groups_length) |k| {
groups.add(groups.mem[k]);
}
}
var all_springs = StackList(u8, usize, 120).init();
for (0..5) |j| {
if (j != 0) {
all_springs.add('?');
}
for (springs) |char| {
all_springs.add(char);
}
}
var state: State = undefined;
for (&state) |*row| {
for (row) |*cell| {
cell.* = std.math.maxInt(u64);
}
}
return solve(all_springs.getSlice(), groups.getSlice(), &state);
}
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 result: u64 = 0;
var line_buffer: [1000]u8 = undefined;
var line_number: usize = 0;
while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |line| {
result += solveLine(line);
line_number += 1;
}
try stdout.print("{d}\n", .{result});
}