const std = @import("std"); const test_input = \\11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124 \\ ; test part1 { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); try std.testing.expectEqual(1227775554, try part1(allocator, try parse(allocator, test_input))); } test part2 { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); try std.testing.expectEqual(4174379265, try part2(allocator, try parse(allocator, test_input))); } const Input = []struct { from: u64, to: u64, }; pub fn parse(allocator: std.mem.Allocator, input: []const u8) !Input { var spans = std.mem.splitScalar(u8, input, ','); var parsed = try std.ArrayList(@typeInfo(Input).pointer.child).initCapacity(allocator, 0); while (spans.next()) |span_| { var span = if (std.mem.endsWith(u8, span_, "\n")) span_[0 .. span_.len - 1] else span_; const dash = std.mem.indexOfScalar(u8, span, '-') orelse return error.InvalidInput; const from = try std.fmt.parseInt(u64, span[0..dash], 10); const to = try std.fmt.parseInt(u64, span[dash + 1 ..], 10); try parsed.append(allocator, .{ .from = from, .to = to }); } return parsed.toOwnedSlice(allocator); } pub fn part1(allocator: std.mem.Allocator, input: Input) !usize { var allocating_writer = std.io.Writer.Allocating.init(allocator); const writer = &allocating_writer.writer; var answer: usize = 0; for (input) |span| { for (span.from..span.to + 1) |n| { allocating_writer.clearRetainingCapacity(); try writer.print("{}", .{n}); const written = allocating_writer.written(); if (written.len % 2 == 1) continue; const len = written.len / 2; if (!std.mem.eql(u8, written[0..len], written[len..])) continue; // std.debug.print("{}\n", .{n}); answer += n; } } return answer; } pub fn part2(allocator: std.mem.Allocator, input: Input) !usize { var allocating_writer = std.io.Writer.Allocating.init(allocator); const writer = &allocating_writer.writer; var answer: usize = 0; for (input) |span| { n: for (span.from..span.to + 1) |n| { allocating_writer.clearRetainingCapacity(); try writer.print("{}", .{n}); const written = allocating_writer.written(); for (2..written.len + 1) |repetitions| { if (written.len % repetitions != 0) continue; const len = written.len / repetitions; const first = written[0..len]; var windows = std.mem.window(u8, written, len, len); while (windows.next()) |window| { if (!std.mem.eql(u8, first, window)) break; } else { // all were equal answer += n; continue :n; } } } } return answer; }