adventofcode

git clone https://git.ce9e.org/adventofcode.git

commit
9d35807060ab1c4d228c2e59aea4dd280fe11cb9
parent
74ebf5fcd08a57630900202f795bded771607b3c
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2025-12-02 22:25
2025-12-02

Diffstat

A 2025/02/input.txt 1 +
A 2025/02/solution.zig 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A 2025/02/test.txt 1 +

3 files changed, 92 insertions, 0 deletions


diff --git a/2025/02/input.txt b/2025/02/input.txt

@@ -0,0 +1 @@
   -1     1 52-75,71615244-71792700,89451761-89562523,594077-672686,31503-39016,733-976,1-20,400309-479672,458-635,836793365-836858811,3395595155-3395672258,290-391,5168-7482,4545413413-4545538932,65590172-65702074,25-42,221412-256187,873499-1078482,118-154,68597355-68768392,102907-146478,4251706-4487069,64895-87330,8664371543-8664413195,4091-5065,537300-565631,77-115,83892238-83982935,6631446-6694349,1112-1649,7725-9776,1453397-1493799,10240-12328,15873-20410,1925-2744,4362535948-4362554186,3078725-3256936,710512-853550,279817-346202,45515-60928,3240-3952

diff --git a/2025/02/solution.zig b/2025/02/solution.zig

@@ -0,0 +1,90 @@
   -1     1 const std = @import("std");
   -1     2 
   -1     3 const Error = error{IndexError};
   -1     4 
   -1     5 fn splitOnce(s: []u8, sep: u8) ![2][]u8 {
   -1     6     const i = std.mem.indexOfScalar(u8, s, sep) orelse return Error.IndexError;
   -1     7     return .{ s[0..i], s[i + 1 ..] };
   -1     8 }
   -1     9 
   -1    10 fn takeRange(r: *std.Io.Reader) ![]u8 {
   -1    11     const s = r.takeDelimiterInclusive(',') catch |err| switch (err) {
   -1    12         error.EndOfStream => try r.takeDelimiterInclusive('\n'),
   -1    13         else => |e| return e,
   -1    14     };
   -1    15     return s[0 .. s.len - 1];
   -1    16 }
   -1    17 
   -1    18 fn getDigits(i: usize) usize {
   -1    19     const f: f64 = @floatFromInt(i);
   -1    20     const digits = @floor(@log10(f)) + 1;
   -1    21     return @intFromFloat(digits);
   -1    22 }
   -1    23 
   -1    24 fn getMask(digits: usize, repeats: usize) usize {
   -1    25     // examples:
   -1    26     // - a number with 6 digits and 2 repeats has the form 100..999 * 1001
   -1    27     // - a number with 8 digits and 4 repeats has the form 10..99 * 1010101
   -1    28 
   -1    29     var mask: usize = 1;
   -1    30     for (1..repeats) |_| {
   -1    31         mask = mask * std.math.pow(usize, 10, digits / repeats) + 1;
   -1    32     }
   -1    33     return mask;
   -1    34 }
   -1    35 
   -1    36 pub fn main() !void {
   -1    37     const path: [:0]const u8 = std.mem.span(std.os.argv[1]);
   -1    38     var file = try std.fs.cwd().openFile(path, .{});
   -1    39     defer file.close();
   -1    40 
   -1    41     var buffer: [64]u8 = undefined;
   -1    42     var reader = file.reader(&buffer);
   -1    43 
   -1    44     var part1: usize = 0;
   -1    45     var part2: usize = 0;
   -1    46 
   -1    47     while (takeRange(&reader.interface)) |line| {
   -1    48         const s1, const s2 = try splitOnce(line, '-');
   -1    49         const start = try std.fmt.parseInt(usize, s1, 10);
   -1    50         const end = try std.fmt.parseInt(usize, s2, 10);
   -1    51         std.debug.assert(start <= end);
   -1    52 
   -1    53         for (getDigits(start)..getDigits(end) + 1) |digits| {
   -1    54             for (2..digits + 1) |repeats| {
   -1    55                 if (digits % repeats != 0) {
   -1    56                     continue;
   -1    57                 }
   -1    58 
   -1    59                 const mask = getMask(digits, repeats);
   -1    60                 const min = std.math.pow(usize, 10, digits / repeats - 1);
   -1    61                 const minValue = @max(
   -1    62                     min,
   -1    63                     try std.math.divCeil(usize, start, mask),
   -1    64                 );
   -1    65                 const maxValue = @min(
   -1    66                     min * 10 - 1,
   -1    67                     try std.math.divFloor(usize, end, mask),
   -1    68                 );
   -1    69                 valueloop: for (minValue..maxValue + 1) |value| {
   -1    70                     const result = value * mask;
   -1    71                     for (2..repeats) |prevRepeats| {
   -1    72                         if (result % getMask(digits, prevRepeats) == 0) {
   -1    73                             continue :valueloop;
   -1    74                         }
   -1    75                     }
   -1    76                     part2 += result;
   -1    77                     if (repeats == 2) {
   -1    78                         part1 += result;
   -1    79                     }
   -1    80                 }
   -1    81             }
   -1    82         }
   -1    83     } else |err| switch (err) {
   -1    84         error.EndOfStream => {},
   -1    85         else => |e| return e,
   -1    86     }
   -1    87 
   -1    88     std.debug.print("part1: {}\n", .{part1});
   -1    89     std.debug.print("part2: {}\n", .{part2});
   -1    90 }

diff --git a/2025/02/test.txt b/2025/02/test.txt

@@ -0,0 +1 @@
   -1     1 11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124