aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--day6.zig68
1 files changed, 68 insertions, 0 deletions
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