const std = @import("std"); const path = "data/day03/input.txt"; const retSize = u24; const lineSize = getLineSize(); pub fn second(allocator: ?std.mem.Allocator) anyerror!retSize { const input = @embedFile(path); var lines = std.mem.tokenize(u8, input, "\n"); var lines_array = std.ArrayList(retSize).init(allocator.?); defer lines_array.deinit(); var lines_array2 = std.ArrayList(retSize).init(allocator.?); defer lines_array2.deinit(); while (lines.next()) |line| { try lines_array.append(try std.fmt.parseUnsigned(retSize, line, 2)); try lines_array2.append(try std.fmt.parseUnsigned(retSize, line, 2)); } const ox = try getOxigenRating(allocator.?, &lines_array); const co = try getCO2Rating(allocator.?, &lines_array2); return ox * co; } fn getOxigenRating(allocator: std.mem.Allocator, oxigen: *std.ArrayList(retSize)) anyerror!retSize { var to_remove = std.ArrayList(usize).init(allocator); defer to_remove.deinit(); var idx: usize = lineSize; while (oxigen.items.len > 1) : (idx -= 1) { var ones: retSize = 0; var zeros: retSize = 0; // count ones and zeros for (oxigen.items) |line| { if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) { ones += 1; } else { zeros += 1; } } // std.debug.print("{d} {d} {d}", .{ones, zeros, idx-1}); for (oxigen.items) |line, i| { if (ones >= zeros) { if ((line & (@as(retSize, 1) <<| idx - 1)) == 0) { try to_remove.append(i); } } else { if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) { try to_remove.append(i); } } } std.sort.sort(usize, to_remove.items, {}, comptime std.sort.desc(usize)); for (to_remove.items) |i| { _ = oxigen.swapRemove(i); } try to_remove.resize(0); // std.debug.print("{d}\n", .{oxigen.items.len}); } return oxigen.items[0]; } fn getCO2Rating(allocator: std.mem.Allocator, co2: *std.ArrayList(retSize)) anyerror!retSize { var to_remove = std.ArrayList(usize).init(allocator); defer to_remove.deinit(); var idx: usize = lineSize; while (co2.items.len > 1) : (idx -= 1) { var ones: retSize = 0; var zeros: retSize = 0; // count ones and zeros for (co2.items) |line| { if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) { ones += 1; } else { zeros += 1; } } // std.debug.print("{d} {d} {d}", .{ones, zeros, idx-1}); for (co2.items) |line, i| { if (zeros <= ones) { if ((line & (@as(retSize, 1) <<| idx - 1)) != 0) { try to_remove.append(i); } } else { if ((line & (@as(retSize, 1) <<| idx - 1)) == 0) { try to_remove.append(i); } } } std.sort.sort(usize, to_remove.items, {}, comptime std.sort.desc(usize)); for (to_remove.items) |i| { _ = co2.swapRemove(i); } try to_remove.resize(0); // std.debug.print("{d}\n", .{co2.items.len}); } return co2.items[0]; } fn getLineSize() usize { const input = @embedFile(path); var ret: usize = 0; for (input) |bit, idx| { if (bit == '\n') { ret = idx; break; } } return ret; } pub fn main() anyerror!void { var buffer: [1000 * lineSize * 100]u8 = undefined; var fba = std.heap.FixedBufferAllocator.init(&buffer); var timer = try std.time.Timer.start(); const ret = try second(fba.allocator()); const s = timer.lap() / 1000; try std.testing.expectEqual(ret, @as(retSize, 4105235)); std.debug.print("Day 3b result: {d} \t\ttime: {d}us\n", .{ ret, s }); } test "day03b" { try std.testing.expectEqual(@as(retSize, 4105235), try second(std.testing.allocator)); }