From 2e516f62129b485bb1c234b4ec5de32c7e3507f6 Mon Sep 17 00:00:00 2001 From: Martin Ashby Date: Fri, 8 Dec 2023 22:31:30 +0000 Subject: Day 6 --- day6.zig | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 day6.zig (limited to 'day6.zig') diff --git a/day6.zig b/day6.zig new file mode 100644 index 0000000..94023a0 --- /dev/null +++ b/day6.zig @@ -0,0 +1,68 @@ +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 +; \ No newline at end of file -- cgit v1.2.3-ZIG