const std = @import("std"); pub fn main() !void { try std.fmt.format(std.io.getStdOut().writer(), "day6 pt1: {}\n", .{try solve_pt1(std.heap.page_allocator, puzzle_input)}); try std.fmt.format(std.io.getStdOut().writer(), "day6 pt2: {}\n", .{try solve_pt1(std.heap.page_allocator, puzzle_input2)}); } fn readnums(a: std.mem.Allocator, input: []const u8) ![]u64 { var toks = std.mem.tokenize(u8, input, " "); _ = toks.next() orelse return error.NoLabel; var al = std.ArrayList(u64).init(a); defer al.deinit(); while (toks.next()) |tok| { try al.append(try std.fmt.parseInt(u64, tok, 10)); } return try al.toOwnedSlice(); } fn solve_pt1(a: std.mem.Allocator, input: []const u8) !u64 { var spl = std.mem.split(u8, input, "\n"); const times = try readnums(a, spl.first()); defer a.free(times); const distances = try readnums(a, spl.next() orelse return error.NoDistance); defer a.free(distances); var sum: ?u64 = null; for (times, distances) |time, distance| { const ftime: f64 = @floatFromInt(time); const fdistance: f64 = @floatFromInt(distance); const disc = (std.math.pow(f64, ftime, 2)) - 4 * fdistance; if (disc <= 0) { // std.log.warn("discriminant {}, no possible solutions", .{disc}); continue; } const x_low: f64 = ((ftime) - @sqrt(disc)) / 2 ; const x_high: f64 = ((ftime) + @sqrt(disc)) / 2 ; // std.log.warn("x_low {} x_high {}", .{x_low, x_high}); // So these are _strict_ bounds. I want the next integer _strictly_ greater than x_low // and the next integer _strictly_ less than x_high const x_low_i: u64 = if (@ceil(x_low) == x_low) (@as(u64, @intFromFloat(x_low)) + 1) else @intFromFloat(@ceil(x_low)); const x_high_i: u64 = if (@floor(x_high) == x_high) (@as(u64, @intFromFloat(x_high)) - 1) else @intFromFloat(@floor(x_high)); const diff = (x_high_i + 1) - x_low_i; // inclusive range if (sum) |s| { sum = s * diff; } else { sum = diff; } } return sum orelse error.NoRaces; } test "pt1" { try std.testing.expectEqual(@as(u64, 288), try solve_pt1(std.testing.allocator, test_input)); } const test_input = \\Time: 7 15 30 \\Distance: 9 40 200 ; const puzzle_input = \\Time: 49 97 94 94 \\Distance: 263 1532 1378 1851 ; const puzzle_input2 = \\Time: 49979494 \\Distance: 263153213781851 ;