This commit is contained in:
2024-12-09 01:08:30 -06:00
parent 066411cb2d
commit d5bd0322c7
3 changed files with 298 additions and 0 deletions

159
09/src/main.zig Normal file
View File

@@ -0,0 +1,159 @@
// okay zig is fine. ig.
// i'm just bad at code, almost all the problems this time were
// logic errors, not just me trying to figure the language out
const std = @import("std");
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
const alloc = arena.allocator();
const test_data = @embedFile("test");
const input_data = @embedFile("input");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const value1 = try run1(input_data);
try stdout.print("{d}\n", .{value1});
const value2 = try run2(input_data);
try stdout.print("{d}\n", .{value2});
}
test "test input part 1" {
std.debug.print("\n", .{});
const value = try run1(test_data);
std.debug.print("{d}\n", .{value});
try std.testing.expectEqual(1928, value);
}
test "test input part 2" {
std.debug.print("\n",.{});
const value = try run2(test_data);
std.debug.print("{d}\n", .{value});
try std.testing.expectEqual(2858, value);
}
fn parseIntFromReader(reader: anytype) anyerror!u64 {
const f = try reader.readByte();
if (f < '0' or f > '9') return error.BadCharacter;
var v: u64 = f - '0';
while (true) {
const c = try reader.readByte();
if (c < '0' or c > '9') {
break;
} else {
v = (v * 10) + (c - '0');
}
}
return v;
}
// messy
fn run2(input: []const u8) !u64 {
var copy = std.ArrayList(u8).init(alloc);
try copy.appendSlice(input);
var s = copy.items;
var last_nonzero = s.len-1;
if (last_nonzero&1==1) last_nonzero -= 1;
var start: usize = 0;
var position: usize = 0;
var total: u64 = 0;
var used_l = std.ArrayList(u8).init(alloc);
try used_l.appendNTimes('0', s.len);
var used = used_l.items;
while (start < s.len) {
// s[start] is used blocks
used: {
if (s[start] == '0') {
const endpos = position + used[start] - '0';
while (position < endpos) : (position += 1) {
}
break :used;
}
const endpos = position + s[start] - '0';
const id = start/2;
while (position < endpos) : (position += 1) {
total += position * id;
}
}
// s[start] is free blocks
start += 1;
free: { if (start < last_nonzero) {
const endpos = position + s[start] - '0';
while (position < endpos) {
const rem_size = endpos - position + '0';
// s[last_nonzero] is last used blocks
var t = last_nonzero;
while (s[t] == '0') { t -= 2; last_nonzero -= 2; }
while (s[t] == '0' or (s[t] > rem_size and t > start)) { t -= 2; }
if (t <= start) {
for ('0'..rem_size) |_| {
}
position = endpos;
break :free;
}
const id = t/2;
const this_endpos = position + s[t] - '0';
while (position < this_endpos) : (position += 1) {
total += position * id;
}
used[t] = s[t];
s[t] = '0';
}
} }
// next used block
start += 1;
}
return total;
}
fn run1(input: []const u8) !u64 {
var copy = std.ArrayList(u8).init(alloc);
try copy.appendSlice(input);
var s = copy.items;
var start: usize = 0;
var end: usize = s.len-1;
if (end&1==1) end -= 1;
var position: usize = 0;
var total: u64 = 0;
calc: while (start < end) {
// s[start] is used blocks
{
const endpos = position + s[start] - '0';
const id = start/2;
while (position < endpos) : (position += 1) {
total += position * id;
}
}
// s[start] is free blocks
start += 1;
{
const endpos = position + s[start] - '0';
// s[end] is last used blocks
var id = end/2;
while (position < endpos) : (position += 1) {
while (s[end] == '0') { end -= 2; id -= 1; if (end < start) break :calc; }
total += position * id;
s[end] -= 1;
}
}
// next used block
start += 1;
}
// any remaining i'm lazy
{
const endpos = position + s[start] - '0';
const id = start/2;
while (position < endpos) : (position += 1) {
total += position * id;
}
}
return total;
}