aoc2023

Advent of Code 2023
Log | Files | Refs | README

day9.zig (2569B)


      1 const std = @import("std");
      2 
      3 pub fn main() !void {
      4     try std.fmt.format(std.io.getStdOut().writer(), "day 9 pt1: {}\n", .{try solve_pt1(std.heap.page_allocator, puzzle_input)});
      5     try std.fmt.format(std.io.getStdOut().writer(), "day 9 pt2: {}\n", .{try solve_pt2(std.heap.page_allocator, puzzle_input)});
      6 }
      7 
      8 fn solve_pt1(a: std.mem.Allocator, input: []const u8) !i64 {
      9     var sum: i64 = 0;
     10     var spl = std.mem.split(u8, input, "\n");
     11     while (spl.next()) |line| {
     12         const nums = try readnums(a, line);
     13         defer nums.deinit();
     14         const nxt = nums.getLast() + try predictNext(a, nums);
     15         // std.log.warn("nxt {}", .{nxt});
     16         sum += nxt;
     17     }
     18     return sum;
     19 }
     20 
     21 // note uses recursion!
     22 fn predictNext(a: std.mem.Allocator, list: std.ArrayList(i64)) !i64 {
     23     if (std.mem.allEqual(i64, list.items, 0)) {
     24         return 0;
     25     }
     26     var sublist = std.ArrayList(i64).init(a);
     27     defer sublist.deinit();
     28     for (1..list.items.len) |ix| {
     29         try sublist.append(list.items[ix] - list.items[ix - 1]);
     30     }
     31     const nxt_diff = try predictNext(a, sublist);
     32     return sublist.getLast() + nxt_diff;
     33 }
     34 
     35 fn readnums(a: std.mem.Allocator, input: []const u8) !std.ArrayList(i64) {
     36     var toks = std.mem.tokenize(u8, input, " ");
     37     var res = std.ArrayList(i64).init(a);
     38     while (toks.next()) |tok| {
     39         try res.append(try std.fmt.parseInt(i64, tok, 10));
     40     }
     41     return res;
     42 }
     43 
     44 test "pt1" {
     45     try std.testing.expectEqual(@as(i64, 114), try solve_pt1(std.testing.allocator, test_input));
     46 }
     47 
     48 fn solve_pt2(a: std.mem.Allocator, input: []const u8) !i64 {
     49     var sum: i64 = 0;
     50     var spl = std.mem.split(u8, input, "\n");
     51     while (spl.next()) |line| {
     52         const nums = try readnums(a, line);
     53         defer nums.deinit();
     54         const prv = nums.items[0] - try predictPrev(a, nums);
     55         // std.log.warn("prv {}", .{prv});
     56         sum += prv;
     57     }
     58     return sum;
     59 }
     60 
     61 // note uses recursion!
     62 fn predictPrev(a: std.mem.Allocator, list: std.ArrayList(i64)) !i64 {
     63     if (std.mem.allEqual(i64, list.items, 0)) {
     64         return 0;
     65     }
     66     var sublist = std.ArrayList(i64).init(a);
     67     defer sublist.deinit();
     68     for (1..list.items.len) |ix| {
     69         try sublist.append(list.items[ix] - list.items[ix - 1]);
     70     }
     71     return sublist.items[0] - try predictPrev(a, sublist);
     72 }
     73 
     74 test "pt2" {
     75     try std.testing.expectEqual(@as(i64, 2), try solve_pt2(std.testing.allocator, test_input));
     76 }
     77 
     78 const test_input =
     79     \\0 3 6 9 12 15
     80     \\1 3 6 10 15 21
     81     \\10 13 16 21 30 45
     82 ;
     83 
     84 const puzzle_input = @embedFile("day9.in");