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; }