aoc/day7/src/main.zig

78 lines
2.3 KiB
Zig

const std = @import("std");
pub fn main() anyerror!void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const alloc = &arena.allocator;
// Read our input
var f = try std.fs.cwd().openFile("input", .{});
defer f.close();
var contents = try f.readToEndAlloc(alloc, std.math.maxInt(u32));
defer alloc.free(contents);
var values = std.ArrayList(u16).init(alloc);
defer values.deinit();
var it = std.mem.tokenize(contents, "\n");
while (it.next()) |line| {
var lit = std.mem.tokenize(line, ",");
while (lit.next()) |value| {
try values.append(try std.fmt.parseInt(u16, value, 10));
}
}
//std.log.debug("{} items", .{values.items.len});
std.sort.sort(u16, values.items, {}, comptime std.sort.asc(u16));
//std.log.debug("{any}", .{values.items});
// Try the median
var median = values.items[values.items.len/2];
std.log.debug("Median position {}, value: {}",
.{values.items.len/2, median});
var fuel_required: u64 = 0;
for (values.items) |v| {
if (v < median) {
fuel_required += @as(u64, median - v);
}
else {
fuel_required += @as(u64, v - median);
}
}
std.log.info("[Part 1] {} fuel required to get to median {}",
.{fuel_required, median});
var i = values.items[0];
const max = values.items[values.items.len-1];
fuel_required = std.math.maxInt(u32);
var best_position: u16 = 0;
while (i <= max) : (i += 1) {
var fu = calculate_fuel_to_pos(i, values.items[0..]);
if (fu < fuel_required) {
fuel_required = fu;
best_position = 1;
}
}
std.log.info("[Part 2] {} fuel required to get to best pos {}",
.{fuel_required, best_position});
}
// move 1: 1 = 1
// move 2: 1 + 2 = 3
// move 3: 1 + 2 + 3 = 6
// move 4: (1+2+3)+4 = 10
// move n: (1/2)n * (n+1)
fn calculate_fuel_to_pos(position: u16, crabs: []u16) u64 {
var fuel_required: u64 = 0;
for (crabs) |c| {
var delta: u64 = 0;
if (c < position) {
delta = @as(u64, position - c);
}
else {
delta = @as(u64, c - position);
}
fuel_required += (delta*(delta+1)) / 2;
}
return fuel_required;
}