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', 4096) catch unreachable;
_ = try reader.readByte();
} else {
line = reader.readUntilDelimiterAlloc(allocator, '\n', 4096) 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;
}
const asc_u32 = std.sort.asc(u32);
pub fn task1(crabs: []u32) u32 {
var result: u32 = 999999;
const min = std.sort.min(u32, crabs, {}, asc_u32).?;
const max = std.sort.max(u32, crabs, {}, asc_u32).?;
var i = min;
while (i <= max) : (i += 1) {
var fuel_required: u32 = 0;
for (crabs) |crab_pos| {
fuel_required += if (i <= crab_pos) crab_pos - i else i - crab_pos;
}
std.log.debug("{}: {} required", .{ i, fuel_required });
if (fuel_required < result) {
result = fuel_required;
}
}
return result;
}
fn calculateFuel(target_position: u32, crabs: []u32) u32 {
var result: u32 = 0;
for (crabs) |crab_pos| {
const distance = if (target_position <= crab_pos) crab_pos - target_position else target_position - crab_pos;
var cost: u32 = 0;
var i: u32 = 0;
while (i <= distance) : (i += 1) {
cost += i;
}
result += cost;
}
return result;
}
pub fn task2(crabs: []u32) u64 {
var result: u64 = 9999999999;
const min = std.sort.min(u32, crabs, {}, asc_u32).?;
const max = std.sort.max(u32, crabs, {}, asc_u32).?;
var i = min;
while (i <= max) : (i += 1) {
const fuel_required = calculateFuel(i, crabs);
std.log.debug("{}: {} required", .{ i, fuel_required });
if (fuel_required < result) {
result = fuel_required;
}
}
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 = task1(input);
std.log.info("Task 1 result: {}", .{task_1_result});
const task_2_result = task2(input);
std.log.info("Task 2 result: {}", .{task_2_result});
}