day 9
This commit is contained in:
159
09/src/main.zig
Normal file
159
09/src/main.zig
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user