1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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
;
|