day6.zig (2526B)
1 const std = @import("std"); 2 3 pub fn main() !void { 4 try std.fmt.format(std.io.getStdOut().writer(), "day6 pt1: {}\n", .{try solve_pt1(std.heap.page_allocator, puzzle_input)}); 5 try std.fmt.format(std.io.getStdOut().writer(), "day6 pt2: {}\n", .{try solve_pt1(std.heap.page_allocator, puzzle_input2)}); 6 } 7 8 fn readnums(a: std.mem.Allocator, input: []const u8) ![]u64 { 9 var toks = std.mem.tokenize(u8, input, " "); 10 _ = toks.next() orelse return error.NoLabel; 11 var al = std.ArrayList(u64).init(a); 12 defer al.deinit(); 13 while (toks.next()) |tok| { 14 try al.append(try std.fmt.parseInt(u64, tok, 10)); 15 } 16 return try al.toOwnedSlice(); 17 } 18 19 fn solve_pt1(a: std.mem.Allocator, input: []const u8) !u64 { 20 var spl = std.mem.split(u8, input, "\n"); 21 const times = try readnums(a, spl.first()); 22 defer a.free(times); 23 const distances = try readnums(a, spl.next() orelse return error.NoDistance); 24 defer a.free(distances); 25 26 var sum: ?u64 = null; 27 for (times, distances) |time, distance| { 28 const ftime: f64 = @floatFromInt(time); 29 const fdistance: f64 = @floatFromInt(distance); 30 const disc = (std.math.pow(f64, ftime, 2)) - 4 * fdistance; 31 if (disc <= 0) { 32 // std.log.warn("discriminant {}, no possible solutions", .{disc}); 33 continue; 34 } 35 const x_low: f64 = ((ftime) - @sqrt(disc)) / 2 ; 36 const x_high: f64 = ((ftime) + @sqrt(disc)) / 2 ; 37 // std.log.warn("x_low {} x_high {}", .{x_low, x_high}); 38 // So these are _strict_ bounds. I want the next integer _strictly_ greater than x_low 39 // and the next integer _strictly_ less than x_high 40 const x_low_i: u64 = if (@ceil(x_low) == x_low) (@as(u64, @intFromFloat(x_low)) + 1) else @intFromFloat(@ceil(x_low)); 41 const x_high_i: u64 = if (@floor(x_high) == x_high) (@as(u64, @intFromFloat(x_high)) - 1) else @intFromFloat(@floor(x_high)); 42 const diff = (x_high_i + 1) - x_low_i; // inclusive range 43 44 if (sum) |s| { 45 sum = s * diff; 46 } else { 47 sum = diff; 48 } 49 } 50 return sum orelse error.NoRaces; 51 } 52 53 test "pt1" { 54 try std.testing.expectEqual(@as(u64, 288), try solve_pt1(std.testing.allocator, test_input)); 55 } 56 57 const test_input = 58 \\Time: 7 15 30 59 \\Distance: 9 40 200 60 ; 61 const puzzle_input = 62 \\Time: 49 97 94 94 63 \\Distance: 263 1532 1378 1851 64 ; 65 const puzzle_input2 = 66 \\Time: 49979494 67 \\Distance: 263153213781851 68 ;