const std = @import("std");
const builtin = @import("builtin");
fn readInputFile(allocator: std.mem.Allocator, filename: []const u8) anyerror![]u32 {
var result = std.ArrayList(u32).init(allocator);
const file = try std.fs.cwd().openFile(filename, .{ .read = true });
defer file.close();
const reader = file.reader();
var line: []u8 = undefined;
if (builtin.os.tag == .windows) {
// NOTE: Read another byte on windows due to two-byte eol.
line = reader.readUntilDelimiterAlloc(allocator, '\r', 1024) catch unreachable;
_ = try reader.readByte();
} else {
line = reader.readUntilDelimiterAlloc(allocator, '\n', 1024) catch unreachable;
}
defer allocator.free(line);
var it = std.mem.split(u8, line, ",");
while (it.next()) |slice| {
const value = try std.fmt.parseUnsigned(u32, slice, 10);
try result.append(value);
}
return result.items;
}
pub fn task1(allocator: std.mem.Allocator, iterations: u32, initial_fish: []u32) !u32 {
var result: u32 = 0;
var lantern_fish = std.ArrayList(u32).init(allocator);
defer lantern_fish.deinit();
try lantern_fish.appendSlice(initial_fish);
std.log.info("initial: {any}", .{lantern_fish.items});
var i: u32 = 0;
while (i < iterations) : (i += 1) {
var new_fish: u32 = 0;
for (lantern_fish.items) |*fish| {
if (fish.* == 0) {
fish.* = 6;
new_fish += 1;
} else {
fish.* -= 1;
}
}
try lantern_fish.appendNTimes(8, new_fish);
std.log.info("{}: {}", .{ i, lantern_fish.items.len });
}
result = @intCast(u32, lantern_fish.items.len);
return result;
}
pub fn task2(iterations: u32, initial_fish: []u32) u64 {
var result: u64 = 0;
var buckets: [9]u64 = [_]u64{0} ** 9;
for (initial_fish) |fish| {
buckets[fish] += 1;
}
std.log.info("buckets: {any}", .{buckets});
var i: u32 = 0;
while (i < iterations) : (i += 1) {
const spawn = buckets[0];
std.mem.rotate(u64, &buckets, 1);
buckets[6] += spawn;
var num_fish: u64 = 0;
for (buckets) |bucket| {
num_fish += bucket;
}
std.log.info("{}: {}", .{ i, num_fish });
}
for (buckets) |bucket| {
result += bucket;
}
return result;
}
pub fn main() anyerror!void {
var buffer: [2000000]u8 = undefined;
var fixed_buffer = std.heap.FixedBufferAllocator.init(&buffer);
const allocator = fixed_buffer.allocator();
const input = try readInputFile(allocator, "input.txt");
const task_1_result = try task1(allocator, 80, input);
std.log.info("Task 1 result: {}", .{task_1_result});
const task_2_result = task2(256, input);
std.log.info("Task 2 result: {}", .{task_2_result});
}