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.
182 lines
5.0 KiB
182 lines
5.0 KiB
1 year ago
|
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: *const Self, needle: T) bool {
|
||
|
for (0..self.length) |i| {
|
||
|
if (self.mem[i] == needle) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
fn getSlice(self: *const Self) []const T {
|
||
|
return self.mem[0..self.length];
|
||
|
}
|
||
|
|
||
|
fn reset(self: *Self) void {
|
||
|
self.length = 0;
|
||
|
}
|
||
|
|
||
|
fn init() Self {
|
||
|
return Self{
|
||
|
.mem = undefined,
|
||
|
.length = 0,
|
||
|
};
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
const StateStorage = StackList(u64, u32, 10_000);
|
||
|
|
||
|
const State = struct {
|
||
|
a: StateStorage = StateStorage.init(),
|
||
|
b: StateStorage = StateStorage.init(),
|
||
|
is_a_current: bool = true,
|
||
|
|
||
|
fn getCurrent(self: *State) *StateStorage {
|
||
|
return switch (self.is_a_current) {
|
||
|
true => &self.a,
|
||
|
false => &self.b,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
fn getPrevious(self: *State) *StateStorage {
|
||
|
return switch (self.is_a_current) {
|
||
|
true => &self.b,
|
||
|
false => &self.a,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
fn add(self: *State, value: u64) void {
|
||
|
self.getCurrent().*.add(value);
|
||
|
}
|
||
|
|
||
|
fn addMapping(self: *State, destination_start: u64, source_start: u64, range_length: u64) void {
|
||
|
var current = self.getCurrent();
|
||
|
const previous = self.getPrevious().*;
|
||
|
const source_end = source_start + range_length;
|
||
|
std.debug.print("processing mapping from {d}-{d} (length {d}) to {d}\n", .{ source_start, source_end, range_length, destination_start });
|
||
|
for (previous.getSlice()) |value| {
|
||
|
if (value >= source_start and value < source_end) {
|
||
|
const new_value = (value - source_start) + destination_start;
|
||
|
std.debug.print("adding new value {d}\n", .{new_value});
|
||
|
current.*.add(new_value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn swap(self: *State) void {
|
||
|
self.is_a_current = !self.is_a_current;
|
||
|
self.getCurrent().*.reset();
|
||
|
}
|
||
|
|
||
|
fn getMinCurrentValue(self: *State) u64 {
|
||
|
var current = self.getCurrent().*;
|
||
|
var result: u32 = std.math.maxInt(u32);
|
||
|
for (current.getSlice()) |value| {
|
||
|
result = @min(result, value);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
fn debug(self: *State) void {
|
||
|
std.debug.print("Current state: {any}, previous state: {any}\n", .{ self.getCurrent().*.getSlice(), self.getPrevious().*.getSlice() });
|
||
|
}
|
||
|
};
|
||
|
|
||
|
fn addDigit(result: anytype, digit: u8) void {
|
||
|
result.* = (result.* * 10) + (digit - '0');
|
||
|
}
|
||
|
|
||
|
fn parseFirstLine(line: []const u8) State {
|
||
|
var result = State{};
|
||
|
var current_number: u64 = 0;
|
||
|
|
||
|
var index: usize = 0;
|
||
|
while (index < line.len) : (index += 1) {
|
||
|
const char = line[index];
|
||
|
switch (char) {
|
||
|
'0'...'9' => {
|
||
|
addDigit(¤t_number, char);
|
||
|
},
|
||
|
else => {
|
||
|
if (current_number != 0) {
|
||
|
result.add(current_number);
|
||
|
current_number = 0;
|
||
|
}
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (current_number != 0) {
|
||
|
result.add(current_number);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
fn parseMappingLine(line: []const u8, state: *State) void {
|
||
|
var destination_start: u64 = 0;
|
||
|
var source_start: u64 = 0;
|
||
|
var range_length: u64 = 0;
|
||
|
|
||
|
var index: usize = 0;
|
||
|
while (line[index] != ' ') : (index += 1) {
|
||
|
addDigit(&destination_start, line[index]);
|
||
|
}
|
||
|
|
||
|
index += 1;
|
||
|
while (line[index] != ' ') : (index += 1) {
|
||
|
addDigit(&source_start, line[index]);
|
||
|
}
|
||
|
|
||
|
index += 1;
|
||
|
while (index < line.len) : (index += 1) {
|
||
|
addDigit(&range_length, line[index]);
|
||
|
}
|
||
|
|
||
|
state.addMapping(destination_start, source_start, range_length);
|
||
|
}
|
||
|
|
||
|
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 line_buffer: [1000]u8 = undefined;
|
||
|
const first_line = (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')).?;
|
||
|
var state = parseFirstLine(first_line);
|
||
|
state.debug();
|
||
|
_ = try reader.readUntilDelimiterOrEof(&line_buffer, '\n');
|
||
|
_ = try reader.readUntilDelimiterOrEof(&line_buffer, '\n');
|
||
|
state.swap();
|
||
|
state.debug();
|
||
|
while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |line| {
|
||
|
if (line.len != 0) {
|
||
|
parseMappingLine(line, &state);
|
||
|
} else {
|
||
|
state.debug();
|
||
|
_ = try reader.readUntilDelimiterOrEof(&line_buffer, '\n');
|
||
|
state.swap();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
state.debug();
|
||
|
try stdout.print("{d}\n", .{state.getMinCurrentValue()});
|
||
|
}
|