aoc2023

Advent of Code 2023
Log | Files | Refs | README

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 ;