From ec56f69ecdcd9c79a18ef4a9c26c490ab873fa86 Mon Sep 17 00:00:00 2001 From: Moritz Gmeiner Date: Tue, 3 Dec 2024 16:45:21 +0100 Subject: [PATCH] day 3 done also fixed up a bunch of stuff on day 1 and day 2 --- Day01/build.zig | 91 --- Day01/build.zig.zon | 72 -- Day01/src/main.zig | 157 ----- Day01/src/root.zig | 10 - day1.zig | 227 ++++++ day2.zig | 240 +++++++ day3.zig | 282 ++++++++ Day01/input1.txt => inputs/day1.txt | 0 inputs/day2.txt | 1000 +++++++++++++++++++++++++++ inputs/day3.txt | 6 + utils.zig | 152 ++++ 11 files changed, 1907 insertions(+), 330 deletions(-) delete mode 100644 Day01/build.zig delete mode 100644 Day01/build.zig.zon delete mode 100644 Day01/src/main.zig delete mode 100644 Day01/src/root.zig create mode 100644 day1.zig create mode 100644 day2.zig create mode 100644 day3.zig rename Day01/input1.txt => inputs/day1.txt (100%) create mode 100644 inputs/day2.txt create mode 100644 inputs/day3.txt create mode 100644 utils.zig diff --git a/Day01/build.zig b/Day01/build.zig deleted file mode 100644 index fafca6f..0000000 --- a/Day01/build.zig +++ /dev/null @@ -1,91 +0,0 @@ -const std = @import("std"); - -// Although this function looks imperative, note that its job is to -// declaratively construct a build graph that will be executed by an external -// runner. -pub fn build(b: *std.Build) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard optimization options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not - // set a preferred release mode, allowing the user to decide how to optimize. - const optimize = b.standardOptimizeOption(.{}); - - const lib = b.addStaticLibrary(.{ - .name = "Day01", - // In this case the main source file is merely a path, however, in more - // complicated build scripts, this could be a generated file. - .root_source_file = b.path("src/root.zig"), - .target = target, - .optimize = optimize, - }); - - // This declares intent for the library to be installed into the standard - // location when the user invokes the "install" step (the default step when - // running `zig build`). - b.installArtifact(lib); - - const exe = b.addExecutable(.{ - .name = "Day01", - .root_source_file = b.path("src/main.zig"), - .target = target, - .optimize = optimize, - }); - - // This declares intent for the executable to be installed into the - // standard location when the user invokes the "install" step (the default - // step when running `zig build`). - b.installArtifact(exe); - - // This *creates* a Run step in the build graph, to be executed when another - // step is evaluated that depends on it. The next line below will establish - // such a dependency. - const run_cmd = b.addRunArtifact(exe); - - // By making the run step depend on the install step, it will be run from the - // installation directory rather than directly from within the cache directory. - // This is not necessary, however, if the application depends on other installed - // files, this ensures they will be present and in the expected location. - run_cmd.step.dependOn(b.getInstallStep()); - - // This allows the user to pass arguments to the application in the build - // command itself, like this: `zig build run -- arg1 arg2 etc` - if (b.args) |args| { - run_cmd.addArgs(args); - } - - // This creates a build step. It will be visible in the `zig build --help` menu, - // and can be selected like this: `zig build run` - // This will evaluate the `run` step rather than the default, which is "install". - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - // Creates a step for unit testing. This only builds the test executable - // but does not run it. - const lib_unit_tests = b.addTest(.{ - .root_source_file = b.path("src/root.zig"), - .target = target, - .optimize = optimize, - }); - - const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests); - - const exe_unit_tests = b.addTest(.{ - .root_source_file = b.path("src/main.zig"), - .target = target, - .optimize = optimize, - }); - - const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests); - - // Similar to creating the run step earlier, this exposes a `test` step to - // the `zig build --help` menu, providing a way for the user to request - // running the unit tests. - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&run_lib_unit_tests.step); - test_step.dependOn(&run_exe_unit_tests.step); -} diff --git a/Day01/build.zig.zon b/Day01/build.zig.zon deleted file mode 100644 index 73c3e90..0000000 --- a/Day01/build.zig.zon +++ /dev/null @@ -1,72 +0,0 @@ -.{ - // This is the default name used by packages depending on this one. For - // example, when a user runs `zig fetch --save `, this field is used - // as the key in the `dependencies` table. Although the user can choose a - // different name, most users will stick with this provided value. - // - // It is redundant to include "zig" in this name because it is already - // within the Zig package namespace. - .name = "Day01", - - // This is a [Semantic Version](https://semver.org/). - // In a future version of Zig it will be used for package deduplication. - .version = "0.0.0", - - // This field is optional. - // This is currently advisory only; Zig does not yet do anything - // with this value. - //.minimum_zig_version = "0.11.0", - - // This field is optional. - // Each dependency must either provide a `url` and `hash`, or a `path`. - // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. - // Once all dependencies are fetched, `zig build` no longer requires - // internet connectivity. - .dependencies = .{ - // See `zig fetch --save ` for a command-line interface for adding dependencies. - //.example = .{ - // // When updating this field to a new URL, be sure to delete the corresponding - // // `hash`, otherwise you are communicating that you expect to find the old hash at - // // the new URL. - // .url = "https://example.com/foo.tar.gz", - // - // // This is computed from the file contents of the directory of files that is - // // obtained after fetching `url` and applying the inclusion rules given by - // // `paths`. - // // - // // This field is the source of truth; packages do not come from a `url`; they - // // come from a `hash`. `url` is just one of many possible mirrors for how to - // // obtain a package matching this `hash`. - // // - // // Uses the [multihash](https://multiformats.io/multihash/) format. - // .hash = "...", - // - // // When this is provided, the package is found in a directory relative to the - // // build root. In this case the package's hash is irrelevant and therefore not - // // computed. This field and `url` are mutually exclusive. - // .path = "foo", - - // // When this is set to `true`, a package is declared to be lazily - // // fetched. This makes the dependency only get fetched if it is - // // actually used. - // .lazy = false, - //}, - }, - - // Specifies the set of files and directories that are included in this package. - // Only files and directories listed here are included in the `hash` that - // is computed for this package. Only files listed here will remain on disk - // when using the zig package manager. As a rule of thumb, one should list - // files required for compilation plus any license(s). - // Paths are relative to the build root. Use the empty string (`""`) to refer to - // the build root itself. - // A directory listed here means that all files within, recursively, are included. - .paths = .{ - "build.zig", - "build.zig.zon", - "src", - // For example... - //"LICENSE", - //"README.md", - }, -} diff --git a/Day01/src/main.zig b/Day01/src/main.zig deleted file mode 100644 index 46fbdfc..0000000 --- a/Day01/src/main.zig +++ /dev/null @@ -1,157 +0,0 @@ -const std = @import("std"); - -pub fn main() !void { - // // Prints to stderr (it's a shortcut based on `std.io.getStdErr()`) - // std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); - - // // stdout is for the actual output of your application, for example if you - // // are implementing gzip, then only the compressed bytes should be sent to - // // stdout, not any debugging messages. - // const stdout_file = std.io.getStdOut().writer(); - // var bw = std.io.bufferedWriter(stdout_file); - // const stdout = bw.writer(); - - // try stdout.print("Run `zig build test` to run the tests.\n", .{}); - - // try bw.flush(); // don't forget to flush! - - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - const alloc = gpa.allocator(); - - try part1(alloc); - try part2(alloc); -} - -fn range(comptime n: u32) [n]usize { - var array: [n]usize = undefined; - - for (0.., &array) |i, *elem| { - elem.* = i; - } - - return array; -} - -fn argsort_cmp(comptime T: type, comptime lessThanFn: fn (ctx: void, lhs: T, rhs: T) bool) (fn ([]T, usize, usize) bool) { - return struct { - fn cmp(array: []T, left_idx: usize, right_idx: usize) bool { - return lessThanFn({}, array[left_idx], array[right_idx]); - } - }.cmp; -} - -fn part1(alloc: std.mem.Allocator) !void { - const filename = "input1.txt"; - - const num_lines = 1_000; - - const file = try std.fs.cwd().openFile(filename, .{}); - defer file.close(); - - var left_list: [num_lines]u32 = undefined; - var right_list: [num_lines]u32 = undefined; - - const file_reader = file.reader(); - var buf_reader = std.io.BufferedReader(4096, @TypeOf(file_reader)){ .unbuffered_reader = file_reader }; - - const reader = std.io.Reader(@TypeOf(&buf_reader), std.fs.File.Reader.Error, @TypeOf(buf_reader).read){ .context = &buf_reader }; - - var line_buf = std.ArrayList(u8).init(alloc); - defer line_buf.deinit(); - - for (0..(num_lines + 1)) |i| { - reader.streamUntilDelimiter(line_buf.writer(), '\n', 4096) catch |err| switch (err) { - error.EndOfStream => break, - else => return err, - }; - - const left = try std.fmt.parseUnsigned(u32, line_buf.items[0..5], 10); - const right = try std.fmt.parseUnsigned(u32, line_buf.items[8..13], 10); - - left_list[i] = left; - right_list[i] = right; - - try line_buf.resize(0); - } - - var left_idxs = range(num_lines); - var right_idxs = range(num_lines); - - std.debug.assert(left_list.len == left_idxs.len); - std.debug.assert(right_list.len == right_idxs.len); - - for (0..1000) |i| { - std.debug.assert(left_idxs[i] == i); - std.debug.assert(right_idxs[i] == i); - } - - const cmp = argsort_cmp(u32, std.sort.asc(u32)); - - std.mem.sort(usize, &left_idxs, @as([]u32, &left_list), cmp); - std.mem.sort(usize, &right_idxs, @as([]u32, &right_list), cmp); - - for (0..(num_lines - 1)) |i| { - std.debug.assert(left_list[left_idxs[i]] <= left_list[left_idxs[i + 1]]); - std.debug.assert(right_list[right_idxs[i]] <= right_list[right_idxs[i + 1]]); - } - - var sum: u64 = 0; - - for (left_idxs, right_idxs) |left_idx, right_idx| { - sum += @abs(@as(i64, left_list[left_idx]) - @as(i64, right_list[right_idx])); - } - - std.debug.print("Day 1, part 1: {}\n", .{sum}); -} - -fn part2(alloc: std.mem.Allocator) !void { - const filename = "input1.txt"; - - const num_lines = 1_000; - - const file = try std.fs.cwd().openFile(filename, .{}); - defer file.close(); - - var left_list: [num_lines]u32 = undefined; - - var right_map = std.AutoHashMap(u32, u32).init(alloc); - defer right_map.deinit(); - - const file_reader = file.reader(); - var buf_reader = std.io.BufferedReader(4096, @TypeOf(file_reader)){ .unbuffered_reader = file_reader }; - - const reader = std.io.Reader(@TypeOf(&buf_reader), std.fs.File.Reader.Error, @TypeOf(buf_reader).read){ .context = &buf_reader }; - - var line_buf = std.ArrayList(u8).init(alloc); - defer line_buf.deinit(); - - for (0..(num_lines + 1)) |i| { - reader.streamUntilDelimiter(line_buf.writer(), '\n', 4096) catch |err| switch (err) { - error.EndOfStream => break, - else => return err, - }; - - const left = try std.fmt.parseUnsigned(u32, line_buf.items[0..5], 10); - const right = try std.fmt.parseUnsigned(u32, line_buf.items[8..13], 10); - - left_list[i] = left; - - if (right_map.get(right)) |count| { - try right_map.put(right, count + 1); - } else { - try right_map.put(right, 1); - } - - try line_buf.resize(0); - } - - var sum: u64 = 0; - - for (left_list) |x| { - if (right_map.get(x)) |count| { - sum += count * x; - } - } - - std.debug.print("Day 1, part 2: {}\n", .{sum}); -} diff --git a/Day01/src/root.zig b/Day01/src/root.zig deleted file mode 100644 index ecfeade..0000000 --- a/Day01/src/root.zig +++ /dev/null @@ -1,10 +0,0 @@ -const std = @import("std"); -const testing = std.testing; - -export fn add(a: i32, b: i32) i32 { - return a + b; -} - -test "basic add functionality" { - try testing.expect(add(3, 7) == 10); -} diff --git a/day1.zig b/day1.zig new file mode 100644 index 0000000..ea8bcd6 --- /dev/null +++ b/day1.zig @@ -0,0 +1,227 @@ +const std = @import("std"); + +const utils = @import("utils.zig"); + +pub fn main() !void { + // // Prints to stderr (it's a shortcut based on `std.io.getStdErr()`) + // std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); + + // // stdout is for the actual output of your application, for example if you + // // are implementing gzip, then only the compressed bytes should be sent to + // // stdout, not any debugging messages. + // const stdout_file = std.io.getStdOut().writer(); + // var bw = std.io.bufferedWriter(stdout_file); + // const stdout = bw.writer(); + + // try stdout.print("Run `zig build test` to run the tests.\n", .{}); + + // try bw.flush(); // don't forget to flush! + + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const alloc = gpa.allocator(); + + const filename = "inputs/day1.txt"; + + { + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part1(alloc, file_reader.reader()); + + try std.io.getStdOut().writer().print("Day 1, part 1: {}\n", .{result}); + } + + { + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part2(alloc, file_reader.reader()); + + try std.io.getStdOut().writer().print("Day 1, part 1: {}\n", .{result}); + } +} + +fn rangeConst(comptime n: usize) [n]usize { + var array: [n]usize = undefined; + + for (0.., &array) |i, *elem| { + elem.* = i; + } + + return array; +} + +fn range(alloc: std.mem.Allocator, n: usize) ![]usize { + var array = try alloc.alloc(usize, n); + + for (0..n) |i| { + array[i] = i; + } + + return array; +} + +fn argsort_cmp(comptime T: type, comptime lessThanFn: fn (ctx: void, lhs: T, rhs: T) bool) (fn ([]const T, usize, usize) bool) { + return struct { + fn cmp(array: []const T, left_idx: usize, right_idx: usize) bool { + return lessThanFn({}, array[left_idx], array[right_idx]); + } + }.cmp; +} + +fn part1(alloc: std.mem.Allocator, reader: anytype) !u64 { + var left_list = std.ArrayList(u32).init(alloc); + var right_list = std.ArrayList(u32).init(alloc); + defer left_list.deinit(); + defer right_list.deinit(); + + var line_reader = utils.lineReader(alloc, reader); + defer line_reader.deinit(); + + while (try line_reader.next()) |line| { + var number_parser = utils.numberParser(u32, line); + + const left = (try number_parser.next()).?; + const right = (try number_parser.next()).?; + + std.debug.assert((try number_parser.next()) == null); + + try left_list.append(left); + try right_list.append(right); + } + + const num_lines = left_list.items.len; + + std.debug.assert(right_list.items.len == num_lines); + + const left_idxs = try range(alloc, num_lines); + const right_idxs = try range(alloc, num_lines); + defer alloc.free(left_idxs); + defer alloc.free(right_idxs); + + std.debug.assert(left_list.items.len == left_idxs.len); + std.debug.assert(right_list.items.len == right_idxs.len); + + for (0..num_lines) |i| { + std.debug.assert(left_idxs[i] == i); + std.debug.assert(right_idxs[i] == i); + } + + const cmp = argsort_cmp(u32, std.sort.asc(u32)); + + std.mem.sort(usize, left_idxs, left_list.items, cmp); + std.mem.sort(usize, right_idxs, right_list.items, cmp); + + for (0..(num_lines - 1)) |i| { + std.debug.assert(left_list.items[left_idxs[i]] <= left_list.items[left_idxs[i + 1]]); + std.debug.assert(right_list.items[right_idxs[i]] <= right_list.items[right_idxs[i + 1]]); + } + + var sum: u64 = 0; + + for (left_idxs, right_idxs) |left_idx, right_idx| { + sum += @abs(@as(i64, left_list.items[left_idx]) - @as(i64, right_list.items[right_idx])); + } + + return sum; +} + +fn part2(alloc: std.mem.Allocator, reader: anytype) !u64 { + var left_list = std.ArrayList(u32).init(alloc); + defer left_list.deinit(); + + var right_map = std.AutoHashMap(u32, u32).init(alloc); + defer right_map.deinit(); + + var line_reader = utils.lineReader(alloc, reader); + defer line_reader.deinit(); + + while (try line_reader.next()) |line| { + var number_parser = utils.numberParser(u32, line); + + const left = (try number_parser.next()).?; + const right = (try number_parser.next()).?; + + try left_list.append(left); + + if (right_map.get(right)) |count| { + try right_map.put(right, count + 1); + } else { + try right_map.put(right, 1); + } + } + + var sum: u64 = 0; + + for (left_list.items) |x| { + if (right_map.get(x)) |count| { + sum += count * x; + } + } + + return sum; +} + +test "part1 example" { + const alloc = std.testing.allocator; + + const example = + \\3 4 + \\4 3 + \\2 5 + \\1 3 + \\3 9 + \\3 3 + ; + + var stream = std.io.fixedBufferStream(example); + + const result = try part1(alloc, stream.reader()); + + try std.testing.expect(result == 11); +} + +test "part1 input" { + const alloc = std.testing.allocator; + + const filename = "inputs/day1.txt"; + + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part1(alloc, file_reader.reader()); + + try std.testing.expect(result == 1506483); +} + +test "part2 example" { + const alloc = std.testing.allocator; + + const example = + \\3 4 + \\4 3 + \\2 5 + \\1 3 + \\3 9 + \\3 3 + ; + + var stream = std.io.fixedBufferStream(example); + + const result = try part2(alloc, stream.reader()); + + try std.testing.expect(result == 31); +} + +test "part2 input" { + const alloc = std.testing.allocator; + + const filename = "inputs/day1.txt"; + + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part2(alloc, file_reader.reader()); + + try std.testing.expect(result == 23126924); +} diff --git a/day2.zig b/day2.zig new file mode 100644 index 0000000..98c7080 --- /dev/null +++ b/day2.zig @@ -0,0 +1,240 @@ +const std = @import("std"); + +const utils = @import("utils.zig"); + +fn Chain(comptime T: type) type { + return struct { + slice1: []const T, + slice2: []const T, + + fn len(self: *const @This()) usize { + return self.slice1.len + self.slice2.len; + } + + fn get(self: *const @This(), i: usize) T { + var idx = i; + + if (idx < self.slice1.len) { + return self.slice1[idx]; + } + + idx -= self.slice1.len; + + if (idx < self.slice2.len) { + return self.slice2[idx]; + } + + unreachable; + } + }; +} + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const alloc = gpa.allocator(); + + const filename = "inputs/day2.txt"; + + { + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part1(alloc, file_reader.reader()); + + try std.io.getStdOut().writer().print("Day 2, part 1: {}\n", .{result}); + } + + { + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part2(alloc, file_reader.reader()); + + try std.io.getStdOut().writer().print("Day 2, part 2: {}\n", .{result}); + } +} + +fn check(report: []const i32) bool { + var window = std.mem.window(i32, report, 2, 1); + + if (report[0] < report[1]) { + while (window.next()) |x| { + std.debug.assert(x.len == 2); + + const diff = x[1] - x[0]; + + if (diff < 1 or diff > 3) { + return false; + } + } + } else if (report[0] > report[1]) { + while (window.next()) |x| { + std.debug.assert(x.len == 2); + + const diff = x[0] - x[1]; + + if (diff < 1 or diff > 3) { + return false; + } + } + } else { + return false; + } + + return true; +} + +fn check_with_skip(report: []const i32, skip_idx: usize) bool { + const chain = Chain(i32){ .slice1 = report[0..skip_idx], .slice2 = report[skip_idx + 1 ..] }; + + if (chain.get(0) < chain.get(1)) { + for (0..(chain.len() - 1)) |i| { + const diff = chain.get(i + 1) - chain.get(i); + + if (diff < 1 or diff > 3) { + return false; + } + } + } else if (chain.get(0) > chain.get(1)) { + for (0..(chain.len() - 1)) |i| { + const diff = chain.get(i) - chain.get(i + 1); + + if (diff < 1 or diff > 3) { + return false; + } + } + } else { + return false; + } + + return true; +} + +fn part1(alloc: std.mem.Allocator, reader: anytype) !u32 { + var line_reader = utils.lineReader(alloc, reader); + defer line_reader.deinit(); + + var report = std.ArrayList(i32).init(alloc); + defer report.deinit(); + + var num_safe_reports: u32 = 0; + + while (try line_reader.next()) |line| { + report.clearRetainingCapacity(); + + var number_parser = utils.numberParser(i32, line); + + while (try number_parser.next()) |n| { + try report.append(n); + } + + if (check(report.items)) { + num_safe_reports += 1; + } + } + + return num_safe_reports; +} + +fn part2(alloc: std.mem.Allocator, reader: anytype) !u32 { + var line_reader = utils.lineReader(alloc, reader); + defer line_reader.deinit(); + + var report = std.ArrayList(i32).init(alloc); + defer report.deinit(); + + var num_safe_reports: u32 = 0; + + report_loop: while (try line_reader.next()) |line| { + report.clearRetainingCapacity(); + + // var it = std.mem.tokenizeScalar(u8, line, ' '); + + var number_parser = utils.numberParser(i32, line); + + while (try number_parser.next()) |n| { + try report.append(n); + } + + if (report.items.len < 2) { + return error.ReportTooSmall; + } + + if (check(report.items)) { + num_safe_reports += 1; + } else { + for (0..report.items.len) |skip_idx| { + if (check_with_skip(report.items, skip_idx)) { + num_safe_reports += 1; + continue :report_loop; + } + } + } + } + + return num_safe_reports; +} + +test "part1 example" { + const alloc = std.testing.allocator; + + const example = + \\7 6 4 2 1 + \\1 2 7 8 9 + \\9 7 6 2 1 + \\1 3 2 4 5 + \\8 6 4 4 1 + \\1 3 6 7 9 + ; + + var stream = std.io.fixedBufferStream(example); + + const result = try part1(alloc, stream.reader()); + + try std.testing.expect(result == 2); +} + +test "part1 input" { + const alloc = std.testing.allocator; + + const filename = "inputs/day2.txt"; + + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part1(alloc, file_reader.reader()); + + try std.testing.expect(result == 549); +} + +test "part2 example" { + const alloc = std.testing.allocator; + + const example = + \\7 6 4 2 1 + \\1 2 7 8 9 + \\9 7 6 2 1 + \\1 3 2 4 5 + \\8 6 4 4 1 + \\1 3 6 7 9 + ; + + var stream = std.io.fixedBufferStream(example); + + const result = try part2(alloc, stream.reader()); + + try std.testing.expect(result == 4); +} + +test "part2 input" { + const alloc = std.testing.allocator; + + const filename = "inputs/day2.txt"; + + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part2(alloc, file_reader.reader()); + + try std.testing.expect(result == 589); +} diff --git a/day3.zig b/day3.zig new file mode 100644 index 0000000..53ac959 --- /dev/null +++ b/day3.zig @@ -0,0 +1,282 @@ +const std = @import("std"); + +const utils = @import("utils.zig"); + +const isDigit = std.ascii.isDigit; + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const alloc = gpa.allocator(); + + const filename = "inputs/day3.txt"; + + { + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part1(alloc, file_reader.reader()); + + try std.io.getStdOut().writer().print("Day 2, part 1: {}\n", .{result}); + } + + { + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part2(alloc, file_reader.reader()); + + try std.io.getStdOut().writer().print("Day 2, part 2: {}\n", .{result}); + } +} + +fn part1(alloc: std.mem.Allocator, reader: anytype) !u64 { + const input = try reader.readAllAlloc(alloc, std.math.maxInt(u64)); + defer alloc.free(input); + + const mul_prefix = "mul("; + + std.debug.assert(mul_prefix.len == 4); + + var total: u64 = 0; + + var idx: usize = 0; + var i: usize = 0; + + outer: while (idx < input.len) : (idx += @max(i, 1)) { + const rest = input[idx..]; + + i = 0; + + while (i < mul_prefix.len) : (i += 1) { + if (rest[i] != mul_prefix[i]) { + continue :outer; + } + } + + // parse first number + + var start: usize = i; + + // next char must be a digit + if (isDigit(rest[i])) { + i += 1; + } else { + continue; + } + + // consume up to 2 more digits + for (0..2) |_| { + if (isDigit(rest[i])) { + i += 1; + } + } + + // already validated we're parsing a valid number + const left = std.fmt.parseUnsigned(u32, rest[start..i], 10) catch unreachable; + + if (rest[i] != ',') { + continue; + } + + // consume ',' + i += 1; + + // parse second number + + start = i; + + // next char must be a digit + if (isDigit(rest[i])) { + i += 1; + } else { + continue; + } + + // consume up to 2 more digits + for (0..2) |_| { + if (isDigit(rest[i])) { + i += 1; + } + } + + // already validated we're parsing a valid number + const right = std.fmt.parseUnsigned(u32, rest[start..i], 10) catch unreachable; + + if (rest[i] != ')') { + continue; + } + + // consume ')' + i += 1; + + total += left * right; + } + + return total; +} + +fn part2(alloc: std.mem.Allocator, reader: anytype) !u64 { + const input = try reader.readAllAlloc(alloc, std.math.maxInt(u64)); + defer alloc.free(input); + + // std.debug.print("{s}\n", .{input}); + + // var tok_it = std.mem.tokenizeSequence(u8, input, "mul("); + + const mul_prefix = "mul("; + const do = "do()"; + const dont = "don't()"; + + var total: u64 = 0; + + var idx: usize = 0; + var i: usize = 0; + + var enabled = true; + + outer: while (idx < input.len) : (idx += @max(i, 1)) { + const rest = input[idx..]; + + i = 0; + + if (!enabled) { + while (i < do.len) : (i += 1) { + if (rest[i] != do[i]) { + continue :outer; + } + } + + enabled = true; + continue; + } + + if (rest[i] == 'd') { + i += 1; + + while (i < do.len) : (i += 1) { + if (rest[i] != dont[i]) { + continue :outer; + } + } + + enabled = false; + continue; + } + + while (i < mul_prefix.len) : (i += 1) { + if (rest[i] != mul_prefix[i]) { + continue :outer; + } + } + + // parse first number + + var start: usize = i; + + // next char must be a digit + if (isDigit(rest[i])) { + i += 1; + } else { + continue; + } + + // consume up to 2 more digits + for (0..2) |_| { + if (isDigit(rest[i])) { + i += 1; + } + } + + // already validated we're parsing a valid number + const left = std.fmt.parseUnsigned(u32, rest[start..i], 10) catch unreachable; + + if (rest[i] != ',') { + continue; + } + + // consume ',' + i += 1; + + // parse second number + + start = i; + + // next char must be a digit + if (isDigit(rest[i])) { + i += 1; + } else { + continue; + } + + // consume up to 2 more digits + for (0..2) |_| { + if (isDigit(rest[i])) { + i += 1; + } + } + + // already validated we're parsing a valid number + const right = std.fmt.parseUnsigned(u32, rest[start..i], 10) catch unreachable; + + if (rest[i] != ')') { + continue; + } + + // consume ')' + i += 1; + + total += left * right; + } + + return total; +} + +test "part1 example" { + const alloc = std.testing.allocator; + + const example = "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"; + + var stream = std.io.fixedBufferStream(example); + + const result = try part1(alloc, stream.reader()); + + try std.testing.expect(result == 161); +} + +test "part1 input" { + const alloc = std.testing.allocator; + + const filename = "inputs/day3.txt"; + + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part1(alloc, file_reader.reader()); + + try std.testing.expect(result == 156388521); +} + +test "part2 example" { + const alloc = std.testing.allocator; + + const example = "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"; + + var stream = std.io.fixedBufferStream(example); + + const result = try part2(alloc, stream.reader()); + + try std.testing.expect(result == 48); +} + +test "part2 input" { + const alloc = std.testing.allocator; + + const filename = "inputs/day3.txt"; + + const file_reader = try utils.FileReader.init(alloc, filename); + defer file_reader.deinit(); + + const result = try part2(alloc, file_reader.reader()); + + try std.testing.expect(result == 75920122); +} diff --git a/Day01/input1.txt b/inputs/day1.txt similarity index 100% rename from Day01/input1.txt rename to inputs/day1.txt diff --git a/inputs/day2.txt b/inputs/day2.txt new file mode 100644 index 0000000..5845f85 --- /dev/null +++ b/inputs/day2.txt @@ -0,0 +1,1000 @@ +1 4 5 8 11 12 9 +7 8 9 10 12 15 17 17 +17 20 23 25 27 31 +55 57 58 61 63 64 70 +39 42 45 43 44 +84 85 86 87 90 89 86 +33 34 35 36 35 37 38 38 +8 9 11 8 10 11 13 17 +34 35 37 39 38 40 45 +47 50 50 51 53 54 +54 55 58 58 59 56 +95 98 99 99 99 +53 54 54 57 61 +65 68 71 71 73 78 +19 20 23 27 28 30 33 36 +78 79 81 85 83 +24 25 27 29 30 32 36 36 +78 79 80 83 86 90 93 97 +30 31 35 38 40 42 49 +61 63 66 71 74 75 +77 80 82 83 89 87 +58 61 68 70 71 74 75 75 +20 23 24 25 28 35 36 40 +25 28 35 36 38 40 46 +47 46 49 52 55 +78 76 78 79 81 78 +14 13 15 17 19 21 21 +77 74 77 79 80 84 +91 89 91 93 94 99 +65 64 63 65 66 67 70 +49 48 51 53 56 54 52 +29 28 30 33 31 34 34 +70 69 71 70 74 +41 38 39 41 43 41 46 +88 85 88 90 90 92 +37 34 36 37 37 39 42 40 +57 55 58 61 61 61 +46 44 46 46 50 +78 75 77 78 79 79 82 89 +86 83 86 87 91 92 95 +17 14 16 17 21 18 +34 32 36 39 39 +60 59 62 66 68 70 73 77 +59 58 60 61 63 65 69 75 +41 40 42 45 46 49 55 58 +4 3 4 5 8 15 16 14 +5 4 10 11 11 +15 14 17 24 26 30 +59 56 59 60 67 69 70 77 +38 38 39 41 43 +78 78 81 84 85 88 85 +24 24 25 27 29 30 31 31 +51 51 54 55 56 58 61 65 +30 30 32 35 40 +84 84 85 82 83 +45 45 48 49 46 43 +60 60 59 60 61 62 62 +35 35 36 33 36 39 43 +47 47 44 45 52 +85 85 86 86 88 91 94 +55 55 55 57 56 +24 24 24 27 29 31 32 32 +47 47 50 52 52 54 55 59 +41 41 41 43 49 +7 7 10 12 16 19 20 23 +28 28 30 34 37 38 40 39 +72 72 74 77 80 84 86 86 +25 25 27 29 32 36 39 43 +15 15 18 22 28 +79 79 82 89 92 93 +55 55 60 61 59 +23 23 24 31 33 33 +58 58 64 65 69 +76 76 83 84 87 89 92 97 +50 54 55 57 59 +23 27 28 30 31 32 33 31 +8 12 14 17 20 20 +31 35 37 40 42 43 46 50 +51 55 57 58 63 +37 41 44 47 45 46 +23 27 28 31 29 32 29 +68 72 75 72 72 +39 43 45 47 44 45 47 51 +20 24 21 24 30 +74 78 79 80 80 81 82 83 +58 62 64 64 67 68 69 67 +17 21 23 23 26 26 +21 25 27 29 30 30 34 +86 90 92 92 98 +23 27 29 30 33 37 39 40 +33 37 38 42 44 43 +29 33 36 37 40 44 44 +21 25 27 28 32 35 39 +56 60 62 66 67 73 +69 73 80 82 83 85 87 +22 26 31 34 35 38 41 39 +40 44 50 52 52 +45 49 54 57 58 60 64 +41 45 46 49 51 58 63 +46 53 55 56 59 62 +10 16 18 20 21 22 21 +19 24 26 29 29 +28 34 36 39 42 44 48 +10 17 20 21 23 26 32 +79 86 88 87 88 +8 13 14 15 13 16 13 +18 25 26 28 31 32 29 29 +19 24 21 22 26 +41 48 50 47 53 +58 65 68 68 69 72 74 75 +84 90 90 93 95 93 +63 68 68 69 69 +77 84 84 86 89 93 +9 14 16 16 17 20 27 +17 22 25 29 32 35 37 40 +76 83 87 89 86 +30 37 39 41 42 46 46 +76 83 84 85 89 91 95 +76 82 86 87 88 89 96 +68 75 80 81 83 85 88 +1 7 10 11 16 15 +82 87 90 96 96 +70 75 77 82 85 89 +18 25 27 30 33 39 41 46 +23 20 18 17 14 11 8 9 +98 96 95 92 91 90 90 +78 77 76 74 73 69 +52 51 50 47 44 42 39 33 +82 80 82 79 78 77 74 +41 38 39 37 40 +35 32 34 32 32 +81 78 75 72 73 71 68 64 +64 63 62 61 60 61 55 +19 17 16 13 13 10 +23 22 20 20 21 +52 50 49 48 45 45 44 44 +19 16 15 12 10 10 6 +25 24 24 23 22 20 13 +95 92 91 89 87 86 82 79 +54 51 49 46 42 44 +73 71 69 67 63 61 61 +82 80 77 73 72 70 66 +23 20 17 13 12 11 6 +33 30 29 22 21 +18 16 9 8 6 5 7 +89 86 85 80 80 +54 52 47 46 45 41 +73 71 70 68 66 65 59 53 +57 58 57 54 51 +88 89 86 84 82 79 76 78 +42 45 42 41 39 38 38 +74 77 76 74 70 +21 23 22 19 14 +15 18 17 20 18 17 16 13 +49 50 52 51 48 50 +21 23 20 22 19 16 16 +61 62 60 61 59 58 54 +94 97 94 93 94 88 +91 94 94 91 90 +43 46 45 45 47 +33 35 35 33 33 +63 65 62 60 60 56 +27 29 28 27 25 22 22 16 +80 83 79 77 75 72 +66 68 67 63 62 61 64 +31 33 32 28 28 +73 76 72 71 68 65 61 +62 65 64 63 59 57 51 +24 26 23 22 21 19 12 11 +23 24 19 18 15 14 16 +87 90 84 81 78 77 77 +80 82 80 74 70 +37 39 36 30 24 +66 66 64 61 60 59 +9 9 8 7 4 2 5 +30 30 28 27 25 25 +59 59 56 54 52 48 +27 27 25 23 20 17 10 +41 41 44 42 41 38 37 +92 92 91 94 92 94 +53 53 52 51 50 52 51 51 +29 29 30 29 26 22 +48 48 47 44 41 44 37 +60 60 57 57 54 +25 25 22 19 19 16 19 +39 39 38 35 32 32 30 30 +92 92 90 90 88 86 82 +86 86 86 84 81 80 79 72 +95 95 92 89 85 84 81 80 +30 30 27 23 20 18 15 16 +96 96 94 91 88 85 81 81 +77 77 75 74 70 68 66 62 +46 46 43 42 41 37 30 +67 67 60 57 55 54 52 51 +35 35 33 26 27 +79 79 76 74 68 66 65 65 +67 67 66 59 55 +51 51 48 43 40 33 +32 28 27 25 24 +39 35 32 31 30 29 31 +49 45 43 40 39 39 +45 41 39 37 36 32 +46 42 41 38 37 34 31 24 +85 81 82 81 80 +20 16 18 17 15 14 12 15 +71 67 65 62 65 62 60 60 +87 83 84 81 77 +9 5 8 7 6 1 +54 50 49 49 47 46 44 +98 94 93 93 92 91 94 +94 90 87 85 85 83 83 +79 75 75 72 68 +88 84 81 80 80 75 +43 39 35 32 31 29 +40 36 32 29 28 25 22 25 +62 58 57 53 53 +71 67 66 63 61 57 55 51 +53 49 45 42 37 +36 32 29 26 24 21 14 13 +96 92 89 86 84 79 78 79 +45 41 39 37 31 28 28 +93 89 84 81 79 76 74 70 +60 56 55 52 47 44 41 36 +55 48 45 43 41 39 36 +39 32 31 29 28 30 +80 73 71 69 67 65 63 63 +22 17 16 15 12 10 6 +92 86 84 81 79 76 74 69 +29 23 22 21 19 21 19 +70 64 61 58 61 60 58 61 +33 26 23 20 22 20 17 17 +57 50 53 50 48 45 44 40 +61 56 59 57 51 +30 25 23 23 22 +59 53 53 51 48 51 +19 13 10 9 7 7 7 +53 46 45 42 39 39 35 +17 11 11 9 6 1 +73 67 65 64 60 57 56 53 +69 63 59 57 58 +34 27 25 22 21 17 17 +53 47 43 41 40 36 +51 45 44 42 41 37 34 29 +60 55 52 51 48 46 40 39 +21 15 12 10 5 8 +26 19 13 12 11 9 7 7 +63 56 54 49 45 +38 31 25 23 21 19 13 +70 63 63 61 60 57 54 56 +68 64 63 62 59 59 57 +98 94 91 91 88 85 83 79 +49 51 53 54 57 62 65 71 +53 57 63 64 67 71 +30 34 35 39 42 43 43 +69 76 79 79 82 83 87 +66 66 63 60 60 59 55 +21 28 31 34 33 34 +85 84 83 80 79 79 79 +62 62 62 59 56 +91 90 87 82 79 79 +61 60 59 55 52 +71 69 70 72 74 76 79 76 +95 93 92 88 85 84 83 83 +86 82 80 77 76 69 +25 29 31 33 34 34 35 39 +23 23 24 21 20 19 15 +71 75 75 78 79 +88 86 89 89 92 +35 35 37 40 38 38 +59 59 58 54 52 48 +43 38 35 32 30 24 22 21 +64 69 69 72 74 +67 68 67 64 63 59 62 +71 71 65 63 60 56 +53 56 57 55 57 59 60 58 +75 78 75 72 74 71 68 68 +80 79 82 85 82 86 +79 73 73 72 72 +70 70 69 63 61 54 +31 37 44 46 47 49 52 51 +70 69 70 73 72 69 +31 31 28 31 30 27 25 18 +28 22 20 19 16 12 +60 55 52 52 49 47 46 42 +39 35 32 32 31 28 31 +16 20 21 25 24 +8 7 8 10 11 10 11 +78 81 84 87 87 88 +82 83 80 78 74 +2 7 9 12 13 17 19 18 +45 47 50 53 56 59 59 +21 21 23 21 23 +14 16 11 10 5 +86 89 88 87 86 84 82 82 +50 46 45 38 34 +16 19 21 23 20 22 +57 57 60 63 66 66 65 +75 74 75 79 83 +86 83 84 82 79 78 80 +65 65 62 61 63 61 59 59 +73 76 80 81 83 85 89 +99 92 93 91 90 83 +41 45 48 51 54 55 61 +85 79 72 71 69 70 +20 17 18 20 23 30 31 31 +62 63 64 66 66 70 +70 73 77 78 85 +66 65 68 70 76 78 82 +35 39 41 44 41 42 44 +12 19 22 25 28 30 32 37 +80 77 76 75 73 72 65 +93 86 80 79 75 +58 54 48 46 43 41 +29 27 30 33 30 31 34 41 +31 32 33 35 37 37 36 +34 35 33 27 26 25 24 +81 83 85 86 88 90 92 90 +47 46 44 40 38 41 +37 37 37 36 33 26 +85 85 79 78 75 74 72 73 +30 30 27 21 21 +42 42 40 36 36 +21 21 23 27 30 +69 75 76 78 78 78 +89 87 85 82 82 +58 54 52 53 52 49 46 48 +98 96 95 93 96 92 +45 44 42 40 33 28 +8 8 11 10 9 11 +82 77 76 73 66 63 58 +33 35 35 32 29 28 26 27 +50 47 45 45 43 40 38 34 +66 68 65 62 65 67 +13 8 6 5 1 2 +10 10 13 16 18 20 22 22 +76 77 80 82 80 80 +28 24 21 24 22 16 +68 64 61 60 59 56 53 55 +26 27 26 27 30 33 35 40 +61 67 67 68 71 78 +34 41 42 45 48 52 54 54 +71 74 75 73 74 78 +62 62 61 60 57 +41 35 33 30 29 27 25 19 +41 42 45 46 47 51 48 +25 25 28 31 33 31 35 +58 62 68 71 74 76 79 82 +67 73 76 80 82 84 86 +40 40 37 36 38 36 +88 84 81 76 73 70 70 +35 31 30 29 25 +42 35 32 28 23 +24 28 25 28 31 29 +25 29 32 36 41 +5 10 13 15 20 24 +9 9 11 12 13 15 18 15 +50 46 43 41 40 36 34 +40 38 38 39 40 44 +24 24 27 28 30 34 36 40 +46 48 50 47 45 42 37 +99 95 92 90 91 89 85 +3 9 10 12 14 18 +39 33 31 32 33 +73 70 72 76 77 80 80 +18 16 19 22 24 30 +27 27 24 22 19 16 12 5 +29 22 19 16 13 10 4 4 +14 16 13 9 4 +68 64 62 61 59 57 55 52 +22 26 28 29 29 +70 74 74 75 77 80 80 +85 85 82 80 79 77 75 75 +32 36 39 38 40 43 48 +54 55 55 57 60 62 62 +68 68 71 71 74 76 +24 28 31 32 33 +85 82 83 85 88 90 94 +80 82 87 89 90 89 +64 61 59 57 52 51 47 +64 70 73 75 72 +40 44 46 51 50 +48 53 56 58 55 56 56 +94 92 89 88 85 87 81 +24 19 16 13 12 9 7 7 +1 2 4 4 9 +94 93 92 95 93 91 89 +74 68 68 65 62 59 52 +4 7 5 7 5 +27 23 20 16 16 +56 54 56 59 59 +65 65 65 67 68 70 72 72 +66 68 73 74 74 +62 62 64 66 68 +65 69 66 69 71 72 72 +83 90 89 90 94 +56 56 57 57 59 61 68 +93 90 86 85 82 77 +34 30 30 29 26 26 +34 39 43 45 47 54 +12 13 12 10 7 1 +59 63 65 64 68 +14 14 16 17 21 +6 3 4 11 12 19 +76 74 71 70 67 67 66 68 +50 56 58 60 63 67 71 +55 49 46 45 44 43 42 44 +78 73 70 68 65 63 59 56 +89 86 89 89 91 93 91 +65 66 68 69 76 79 81 82 +22 21 18 17 16 14 7 4 +20 20 23 24 29 31 31 +45 50 53 59 61 62 64 71 +61 61 60 57 54 53 55 +73 69 66 64 63 60 60 +60 60 57 56 55 55 57 +78 76 76 79 80 83 90 +4 4 5 7 13 +73 73 73 71 69 69 +50 45 44 40 37 33 +3 4 7 10 13 16 19 23 +86 83 79 76 72 +85 84 85 87 90 97 99 +17 16 19 22 23 27 28 +87 81 78 81 78 76 75 72 +22 26 28 30 32 36 +38 33 30 29 27 +54 56 53 51 47 44 41 38 +43 43 44 47 48 52 59 +95 92 93 94 95 97 +46 46 49 53 54 57 59 57 +34 36 36 34 34 +39 36 34 34 33 +62 58 56 55 57 57 +80 83 81 81 79 77 72 +34 38 44 47 48 50 53 59 +24 19 17 15 15 13 +13 17 18 22 23 +10 8 9 12 16 18 17 +22 18 17 17 10 +75 80 79 80 83 84 86 84 +59 55 54 53 49 45 +34 39 45 46 46 +26 22 21 20 13 10 8 9 +16 15 13 11 10 9 10 +11 13 10 6 4 4 +59 61 59 56 53 49 45 +57 59 58 51 48 48 +33 29 27 26 22 17 +85 87 86 80 81 +56 56 59 65 67 70 69 +86 84 87 93 96 98 96 +54 57 60 62 65 +52 54 55 58 59 61 63 +73 72 71 68 67 +45 47 50 51 53 54 56 +24 23 22 20 19 +73 70 69 68 66 64 +30 32 33 35 37 39 40 +7 9 10 13 14 17 18 20 +67 66 64 61 59 +31 28 26 25 24 22 20 18 +20 17 14 13 11 +18 21 23 26 29 32 35 +53 54 57 60 62 +68 71 72 74 77 78 81 84 +22 24 25 26 29 31 34 +15 18 20 21 24 26 29 32 +41 39 38 35 34 31 +63 65 68 70 72 74 75 76 +97 94 92 89 86 84 81 80 +71 72 74 77 80 81 +54 51 49 48 47 45 42 +68 67 66 65 62 +24 26 29 30 31 32 34 +25 26 29 32 35 36 37 +88 86 83 80 77 76 75 74 +62 60 57 54 52 50 49 +64 62 59 58 56 +54 55 57 60 63 66 +28 30 31 32 34 +63 62 60 57 56 54 51 49 +83 85 86 88 89 91 92 +1 4 5 7 10 13 15 +32 31 30 28 26 24 23 20 +84 86 88 90 92 94 95 +24 23 21 20 19 18 +92 91 88 85 84 +23 26 27 28 31 32 33 36 +36 38 39 40 43 45 47 49 +29 26 24 21 20 17 +12 10 9 7 4 3 2 +25 23 21 19 17 15 13 12 +38 37 35 32 31 +11 12 15 18 19 +99 96 95 93 90 +39 37 36 33 30 +35 37 39 40 43 +79 76 74 73 70 68 +40 37 34 33 30 28 +71 70 68 67 65 64 63 62 +95 92 91 89 86 83 +45 44 43 40 39 36 +29 26 25 23 22 21 +67 68 71 73 75 78 79 82 +95 92 89 88 86 85 +6 7 10 11 12 14 +46 45 43 41 38 36 +31 29 27 26 25 22 +47 50 53 55 57 +70 71 73 76 77 +13 16 17 19 22 25 26 28 +40 42 43 44 47 50 51 52 +40 41 42 45 47 50 +70 71 74 76 78 +65 68 71 73 76 +23 26 29 30 33 +48 51 53 56 57 58 +69 70 73 74 77 78 80 81 +28 30 32 35 36 +67 68 69 71 73 76 +93 90 87 85 82 80 +67 65 64 62 60 +38 35 33 31 30 27 24 23 +98 96 94 92 89 86 +14 11 9 8 7 4 +71 72 73 76 77 79 82 83 +80 79 78 75 73 72 69 +10 8 6 5 3 +85 84 82 79 76 74 73 72 +60 57 56 55 54 +67 66 64 61 58 57 55 +56 59 62 63 65 66 69 70 +49 52 55 56 57 58 59 61 +98 96 94 92 89 86 83 81 +62 64 65 68 69 +33 35 36 37 38 41 43 +76 79 81 84 86 +22 23 26 29 32 34 36 +38 36 33 31 28 +77 75 74 73 72 69 67 +49 52 55 56 57 60 62 +92 91 88 86 85 83 80 +60 58 57 56 53 51 48 +34 37 40 43 44 47 49 +19 18 17 15 12 11 +86 83 81 79 76 75 +63 61 60 59 56 +62 63 66 68 70 73 74 77 +53 56 58 60 63 64 65 67 +4 6 8 9 10 +73 76 78 80 81 +66 64 61 59 58 57 54 +82 80 79 77 75 +14 15 18 21 23 +10 11 14 17 19 +32 34 37 40 43 +67 68 71 74 76 78 +85 83 80 79 77 76 73 +24 21 19 17 15 14 11 +24 23 20 17 15 13 11 +55 58 59 60 63 65 66 68 +37 36 33 30 28 +56 53 52 49 47 46 43 +76 73 71 69 67 64 63 +86 83 82 81 79 76 74 +74 75 77 80 82 83 85 87 +65 68 70 71 72 75 77 +51 48 45 42 39 +45 43 41 39 37 34 +14 16 19 21 23 25 +39 41 44 45 48 50 53 +51 50 49 46 45 43 42 39 +34 31 28 26 25 23 22 +55 57 60 62 64 66 67 +66 64 63 61 59 56 53 +33 35 38 41 42 44 46 +38 36 33 32 31 30 27 +26 27 30 31 32 35 +24 25 26 29 32 33 +65 64 63 61 58 +22 25 27 30 32 35 37 38 +33 32 30 27 25 +71 74 75 76 77 +82 81 80 79 78 76 75 74 +49 48 46 44 43 41 39 +41 42 44 46 47 +81 83 86 89 92 93 +12 14 16 18 20 23 +89 86 84 82 79 76 75 +75 76 77 78 79 81 +79 77 74 73 70 68 65 62 +12 14 17 18 19 20 +6 7 9 10 13 16 19 22 +66 65 64 62 61 +61 60 57 56 54 51 48 47 +69 67 65 63 62 60 58 +23 21 19 18 17 +20 23 25 27 28 +29 28 27 24 23 21 18 +68 66 65 64 63 61 +64 61 58 55 52 50 47 +70 67 64 61 60 57 +37 35 32 31 28 27 25 +59 60 62 65 68 69 72 75 +46 44 43 42 41 38 35 +19 21 24 26 27 28 31 +27 28 29 31 34 36 37 39 +80 78 75 73 70 69 68 65 +36 33 31 29 28 +88 85 82 79 77 74 +9 12 15 18 19 +16 14 11 10 8 5 4 3 +97 95 94 92 91 89 +47 48 50 52 54 55 58 61 +44 47 48 49 50 51 +50 51 53 56 58 +53 54 55 57 60 63 66 +18 21 22 23 25 27 +93 90 87 84 82 80 79 +60 63 64 66 69 72 75 77 +94 92 90 87 85 84 81 +37 39 42 45 48 +63 66 69 70 71 72 +46 47 50 52 54 57 60 +2 4 7 10 12 +41 38 37 34 33 31 +18 21 23 25 28 31 +16 15 14 12 11 10 7 5 +30 32 34 37 40 42 45 46 +1 3 4 6 9 10 +87 84 83 81 80 77 +49 51 54 55 57 58 60 62 +19 18 16 14 11 9 +1 2 3 4 5 8 +68 70 72 73 74 +35 32 31 29 26 23 22 20 +51 53 56 59 62 63 65 67 +79 81 84 85 87 90 93 +51 54 55 56 57 58 +21 23 24 25 28 29 +35 34 31 29 28 27 26 +30 27 25 23 20 17 16 14 +30 28 26 24 22 21 20 17 +18 21 22 25 28 31 32 34 +81 78 77 75 74 +72 75 78 81 83 +84 85 88 89 92 94 95 96 +15 17 18 20 21 23 +80 78 76 74 73 70 68 65 +54 51 50 48 46 45 +85 84 83 80 79 78 77 +34 31 30 28 26 23 +69 72 75 76 77 78 81 +52 54 55 57 59 +82 79 76 73 71 68 65 62 +72 74 75 76 79 80 +12 9 7 6 4 3 2 1 +50 51 52 53 55 58 59 60 +20 22 25 28 29 +67 70 73 75 76 +22 25 26 29 30 +48 50 53 56 57 59 62 63 +70 71 72 75 77 80 82 +87 84 81 79 77 +93 92 90 89 87 +69 70 71 73 74 77 +11 14 17 19 21 24 25 28 +85 88 89 92 94 +61 64 65 68 69 71 72 +6 7 9 12 14 +49 52 53 54 57 58 59 +57 54 51 49 48 47 45 +66 63 61 58 57 54 53 52 +25 24 22 19 16 15 12 11 +43 41 40 37 34 33 32 +93 91 88 86 84 82 81 78 +40 43 46 47 49 50 +56 53 51 48 47 +42 45 48 50 52 55 +62 60 57 54 52 51 +51 48 45 44 43 42 40 +28 26 23 22 19 16 13 11 +67 64 62 61 58 57 +80 83 84 87 88 89 +51 52 55 57 60 63 66 +13 10 7 5 3 +68 71 73 76 79 81 82 +91 89 86 85 82 81 80 +31 29 28 27 24 22 21 +21 18 17 14 11 10 9 8 +72 75 78 80 83 85 +55 57 58 61 63 66 69 +50 48 47 46 45 +76 79 82 85 87 88 +49 48 46 44 42 40 39 38 +68 69 71 74 76 +22 21 19 16 13 +27 24 23 22 19 18 +19 18 16 14 13 12 11 +79 81 84 86 89 +4 6 7 8 9 10 +20 23 26 28 29 30 +84 87 88 90 92 +31 33 34 37 39 41 43 +31 28 27 25 23 20 +49 52 55 58 60 62 65 +75 77 78 81 83 84 85 86 +56 53 51 50 47 44 42 39 +26 29 30 33 35 36 37 40 +63 66 67 69 72 73 74 +6 7 10 11 13 14 16 +67 66 63 62 61 60 59 58 +60 61 63 64 66 68 70 +19 17 16 15 13 12 9 6 +88 85 82 79 77 76 74 +15 14 12 11 9 +3 4 5 8 10 12 +14 12 9 7 6 4 +40 37 36 34 33 31 +28 31 34 36 37 39 40 +30 32 33 35 36 37 +62 60 58 57 55 54 51 +60 58 55 52 50 +57 58 61 63 66 69 70 72 +81 80 77 76 75 73 +72 70 69 66 64 62 59 +84 81 78 77 75 74 73 +79 82 84 87 89 92 +84 87 88 90 92 94 +28 25 23 22 21 +57 56 53 52 51 50 48 +25 27 29 31 32 35 36 +20 22 25 27 28 31 +41 40 37 34 32 30 28 +52 55 58 59 60 62 65 +57 55 54 52 50 48 45 +81 78 75 74 71 +73 76 78 80 82 +26 25 22 20 19 16 15 13 +68 67 65 62 60 58 56 +43 41 39 37 35 +70 73 74 77 79 80 +88 85 83 80 77 74 72 +82 79 76 73 70 +56 53 52 49 46 43 40 +45 42 40 39 38 35 32 +21 23 24 27 30 31 32 35 +28 30 31 32 33 34 35 37 +66 69 71 73 74 75 +56 57 60 61 64 +81 79 77 76 73 71 +81 79 78 75 72 70 +55 56 57 59 62 65 67 +55 52 50 48 45 +9 7 4 3 2 1 +27 28 31 33 35 36 +89 88 86 85 83 82 81 78 +4 7 10 11 12 14 16 19 +49 51 53 56 57 59 62 +30 29 26 23 21 18 16 15 +67 66 64 61 60 +62 61 59 56 55 +57 59 62 64 67 +71 72 75 77 78 79 81 +45 47 50 52 54 56 +21 23 26 28 30 33 36 38 +54 55 58 61 63 65 67 70 +50 49 48 47 45 43 +70 71 72 73 75 77 +22 24 27 30 32 33 36 37 +83 86 89 91 93 94 97 +32 31 29 27 24 +68 69 72 75 78 80 +64 65 66 67 70 73 +37 35 32 29 26 +39 37 34 33 30 27 +15 16 17 18 20 +75 73 72 70 69 68 65 63 +45 47 48 51 54 56 +29 28 27 25 22 19 18 15 +4 7 8 9 12 13 16 17 +62 65 66 69 70 72 +26 24 21 18 15 13 10 7 +2 5 6 9 12 13 +70 69 67 66 65 62 +37 40 42 45 48 +92 90 89 88 86 83 80 79 +72 70 69 66 63 +35 33 31 30 29 28 +56 58 60 61 63 65 +58 56 55 52 50 +35 32 29 28 27 24 21 +99 96 95 92 89 +15 16 19 21 22 23 25 +1 3 4 7 10 13 14 17 +89 88 87 85 84 82 81 78 +29 30 32 33 36 37 +73 75 78 79 80 82 84 +67 69 72 75 77 +45 42 41 38 37 35 34 +40 43 46 48 49 +54 56 58 59 60 63 64 66 +24 26 29 32 33 +95 93 90 87 84 +71 68 65 63 62 61 +53 51 50 48 47 +32 30 28 27 24 23 +46 49 52 53 55 57 58 +54 57 60 62 63 65 67 +12 13 14 17 20 22 25 28 +36 38 40 42 45 46 48 +84 85 86 87 89 +64 62 59 57 56 53 50 48 +54 57 59 62 65 66 69 70 +82 81 80 79 77 75 +21 22 24 26 27 30 33 +52 49 46 45 44 41 +47 49 51 52 54 56 59 60 +67 68 70 71 73 75 +13 15 17 19 21 22 23 +25 27 28 31 34 36 38 39 +23 20 17 16 13 10 9 8 +78 80 82 85 86 89 91 94 +82 85 87 89 90 93 94 +51 48 47 44 41 38 35 +17 20 23 25 27 +19 22 23 25 28 31 34 +76 74 73 71 68 +49 52 53 55 57 58 59 61 +52 54 56 59 62 +73 70 68 66 64 62 61 60 +92 89 88 87 85 +21 24 27 28 29 +23 20 19 16 14 +44 45 48 51 52 +44 41 39 38 35 +42 41 38 35 32 31 +17 18 19 20 21 23 +27 30 32 34 36 38 41 44 +9 11 12 13 16 17 +16 13 10 8 5 4 2 +52 53 56 58 59 60 61 +29 32 34 36 39 41 44 +77 78 81 84 87 +61 59 56 53 51 49 48 45 +52 53 55 56 58 60 63 +24 25 28 31 32 35 38 40 +20 22 25 27 30 +65 67 68 71 74 75 +45 48 50 51 53 54 56 +70 69 66 64 63 62 +30 29 27 26 24 22 +53 55 58 59 61 62 +31 29 27 26 24 22 20 18 +2 4 7 9 12 13 +39 38 37 35 34 31 29 +60 58 56 53 51 49 48 +4 7 8 10 12 14 +40 38 35 32 29 28 26 24 +90 88 86 83 82 79 +56 57 58 61 64 66 69 72 +80 82 83 85 87 89 90 +39 38 36 33 30 29 +33 30 29 27 24 22 21 18 +54 57 58 59 60 62 +81 84 86 87 90 92 93 96 +22 23 26 28 31 +70 68 67 66 63 +29 27 25 23 22 20 +25 27 28 31 32 35 38 39 +77 76 73 70 68 67 +61 59 58 57 56 +40 41 43 46 48 +31 28 26 23 22 21 20 17 +45 43 41 38 35 +46 48 49 51 54 55 +50 52 53 54 55 58 61 64 +16 13 11 10 9 7 4 1 +34 37 38 40 42 +97 95 94 93 90 89 88 87 +30 32 34 36 38 39 41 43 +73 70 67 66 64 63 62 +82 80 79 76 73 72 +53 50 47 45 44 41 40 39 +81 83 86 88 91 93 94 +24 22 20 17 16 15 +55 56 58 59 60 63 65 67 +9 12 14 17 18 19 22 +19 16 15 13 10 7 5 +97 95 94 92 91 89 88 87 +78 80 82 83 85 86 88 90 +45 48 51 52 53 54 +54 53 52 50 48 47 46 45 +55 54 53 52 50 +38 35 34 33 30 27 26 +65 62 61 59 58 55 +33 35 36 38 41 42 43 45 +35 32 29 28 27 26 23 +39 37 35 32 31 28 26 24 +2 3 4 6 7 10 12 15 +17 19 22 23 25 28 +53 55 58 60 63 65 68 +64 67 70 72 75 +78 75 72 70 68 67 +56 54 51 50 47 44 +21 18 15 12 11 9 +56 54 51 49 48 45 42 39 +50 47 44 42 41 39 37 +72 75 77 78 81 83 84 +85 84 83 82 79 76 +83 81 78 75 72 +80 82 84 87 90 93 95 +81 83 84 87 89 90 +68 71 72 74 77 78 79 +70 71 72 75 78 81 83 84 +20 19 16 15 13 +12 9 8 7 6 5 2 +22 23 25 26 28 29 31 32 +32 30 28 25 22 20 +35 32 31 28 25 23 +36 39 40 41 44 46 48 50 +52 55 56 59 62 +50 48 45 43 40 39 37 36 +36 35 33 32 31 28 +50 48 47 44 43 41 38 36 +6 5 4 2 1 +19 16 14 12 9 7 4 +28 30 32 33 35 +75 73 70 68 65 +25 23 20 18 17 14 12 +67 70 72 73 76 77 78 +73 75 76 79 82 83 +37 35 34 31 29 +99 97 95 93 91 89 +8 9 10 11 12 15 +60 59 56 55 52 49 48 47 +54 53 51 50 48 47 +32 35 37 39 40 42 +79 78 77 76 75 +43 42 40 37 34 31 +22 23 25 28 31 +98 96 93 92 89 88 85 +60 59 56 54 52 50 48 47 +71 72 73 74 77 78 81 +37 34 32 30 28 27 +18 21 22 23 24 +29 31 33 35 36 39 42 44 +36 33 30 29 26 23 21 18 +44 46 47 49 50 53 55 57 +69 66 65 62 59 +80 81 83 84 87 +62 65 68 71 74 +56 53 52 50 47 +36 39 42 43 45 47 49 +68 65 64 62 60 57 54 +78 75 73 71 69 67 65 63 +50 52 54 55 57 59 60 +73 72 71 70 69 67 +99 96 93 90 87 +34 32 31 28 27 24 22 +78 81 82 84 85 87 88 +37 35 34 33 30 +70 69 68 65 63 62 +85 82 80 77 75 74 72 69 +33 35 38 41 42 +67 64 62 60 58 +38 36 35 34 31 30 +64 67 69 71 74 77 +89 86 83 80 79 77 +80 77 75 74 71 +76 79 82 83 86 +92 89 86 85 84 82 79 77 +14 17 20 22 25 28 +23 26 27 29 32 35 36 +99 98 96 93 90 87 84 +41 43 44 47 49 52 53 56 +25 24 21 19 16 13 11 +46 49 52 54 56 +68 65 62 61 58 +73 70 68 65 62 61 60 +42 43 45 48 49 +61 64 67 70 72 74 +71 72 73 74 75 76 +89 86 84 81 79 76 73 72 +48 46 45 42 39 36 34 32 +66 63 61 59 56 55 53 +18 20 22 24 27 30 33 +50 49 47 46 44 +69 70 71 74 75 78 79 +18 16 13 12 11 8 7 +57 59 60 62 64 67 +25 27 29 32 35 +71 68 67 65 64 61 58 +21 22 24 26 29 32 34 37 +89 87 85 82 79 78 75 +91 89 87 85 82 81 78 +77 79 81 82 85 86 +59 61 62 65 67 68 +94 93 92 91 90 87 85 83 +50 52 53 54 56 57 58 61 diff --git a/inputs/day3.txt b/inputs/day3.txt new file mode 100644 index 0000000..9541bbe --- /dev/null +++ b/inputs/day3.txt @@ -0,0 +1,6 @@ +where(536,162)~'what()what()how(220,399){ mul(5,253);mul(757,101)$where()@why()who()&when()from()mul(394,983)why()!&'how()mul(924,201)] mul(44,185)[]what()?${{}#,mul(116,356):~(from()]when()'mul(557,491)<+select()]'mul(584,228)don't()*?#how()'where()&;@mul(58,115),where()?why()]]+:>mul(263,869)# %()from()[>mul(820,89);;#?when(),mul(553,296)where()(what()-mul(846,467){mul(436,71)}@$mul(553,611)do()where()<^select():+*'mul(411,428)-]?mul(722,379)}%'who(),>mul(471,731)*)+/what()@mul(729,484)/mul(672,572)'mul(375,937)who() ~how()%who()select()>;>don't(){mul(117,155)what()['why()}mul(946,797)why())^);where()%;}mul(387,438)'))mul(691,206)]when()+%>select()mul(182,238)how()' mul(522,434)where()mul(22,857)%mul(134,598)mul(689,301)-why()mul(7,725)^select()<,how()'%mul(632,167)}?*how()!mul(328,251)+mul(168,813)who()^when()why()mul(696,552)where()where()mul(177,527)%}$]%}from()]mul(600,612)select()&<&mul(5,789)where()*/{who()why()do()*[when()}^]when()/mul(327,459)/&where()(mul(227,420)@(:[do()>mul(696,517)*mul(843,490)from(638,892)why()how()who()@mul(653,546)?how()when()^&]why()?mul(121,726)[where()-]}^?)>/mul(792,224)%+what()-/+mul(835,136)!{!'@)do()what()@#:*$*from()$mul(597,336)-?+^<']^]mul(222,657)('select()#!what()!mul(501,306):~+~@#'from()++mul(660,306)who()how();mul(884,257)why()when()what();:&$:!mul(180,820)]%who()-who()%(mul(770,324)~&]:?-mul(9,372 $)mul(987,378)from()select()where()mul(248,646)who(601,171)select()/>%[{$-mul(185,819) what() + :mul(442,907)--*)who()mul(541where(884,926)$mul(549,388)&^why(37,524)!?]!?from()don't()select(),%+ ?when(975,750)%}who()mul(262,401)<,/,from()mul(139,806)!;**);%+^;mul(76,978)'(what(){/mul!select()!mul(990,777)mul(188,545)(!what()/from()mul(272,32)from()^why()+#*mul(977,807):/^mul(266,744)select()from()*^select()!!,&who()mul(225,754)from()^#%^mul(513,969)why():mul(288,8)'who(331,621)@~~!@&mul(738,701)how()'@ where()don't(){>&>what()why()#(mul(744,683)@-from(498,125)when()don't()mul(773select()$mul(919,685)+where()mul(305,573)how()how(563,86)+,}who()~mul(291,852)%^from()mul(647,3)$+&:^-+/who()'mul(174,156){(mul(590select() -~*when()#^[mul(679,740)${;mul(463,30)$; (when()mul(875,270)who()/^#;~]!{mul(890(mul(224,108)#:!@mul <>^ where(),&who()^-$}mul(752,792)select() #/!how()@mul(213,376)(do()[why()%>?mul(771,799)^{&:/mul(382,131)how()^)}mul(412,25)?]]&^select()what()(mul(616,919)~}who()# ){who()when(263,342)^mul(946,363) +}?~who()select()-mul(316,505)&%*how()mul(363,589)>?%-:)where()~{{mul(38,452)select()%>[{]%>%mul(445,9)select()select()where()who(809,10)select()'&mul(505,640):>where()--mul(899,766)^where(){from()@*mul(954,818)<{]$select(491,929)$mul(469,330);,'mul(709,381)>mul(692,607)select()(]/?don't()~from()what()<-&'[from()mul(20,147)who()&why()$(mul(482how(887,305)<&#how()!<[&/mul(964,713)~what(){what()^}}select()mul(37'**)]$what())mul(573,765)?where()#where()mul(861,190)what()what():~#?mul(149,843)<,-mul(705:^^~mul(134,719)})mul(22,371):}'when()how()}how()&do()-!mul(148,678)mul(801,30) what(),mul&{?mul(184,545){}#select(448,839)+~+mul(986,322) what())/!<+mul(581,609)where()who()how()/mul(434,891))mul(728,525)[,'@@+mul(552,165);^:>)where() '?mul(23,400)mul(167,183)/*how() how()why()*mul(157,343)!?when()@;(~?mul(796,355)where()~<:$mul(312,781){why()who()-:mul(440,283)select()how()how()mul(288,757)@how()mul(421,123)mul(589,921)how())?>) mul(455,905)-# who()mul(955,7-select();>when()mul(599,748):*!!##!>-(mul(273,990):{)!:mul(974,159)why(451,105)where()-$mul(696,260)~{ mul(216,455);when(912,287){mul(928,316)from()'#select()+who()> mul(890,212)[(why()/;mul(766,534)why()*>]select()why()from()from()mul(170,736)&when()#}mul(645,679))-where()$% mul(864,397)when()&%#mul(155,481))from()[-mul(160,707)mul(807,746)/where(779,210)mul(261,877)'[,$:what()mul(922,680)#what(972,646),how()where()%when()((why()mul(894,377)&]how()why(755,527)mul(48,266)(when()$what()mul(361,771)}select()[)mul(332,827)who()$^:)$>do()*;@[mul(690,51)?$mul(55,840)>[^,'#from()mul(863,343)@select()$mul(425,648)^why(208,282)mul(763,181)from()mul(794,818)+]''(^]mul(213,528):( ~'*^don't()!what()(mul(314,669)*,^!++!!,mul(641,237)](mul(440,591)}*mul(460,11)where()^*mul(708,915)where(911,272)'mul(894,309)~+%@#}@#why()mul(330,296)what()mul(707,884)mul;&}<{>where()$why()]mul(609,787)*!/@who()+!,mul(342,89)::from()}#from()]:,/mul(102,723)select()^@when()who()mul(903,945)don't(),^)what()]mul(80,130)~+~[&@^,from()<,mul(983,403);why()mul(936,199)&+:*who()@why()from():+~mul(402,74)!>how()}+mul(642,782)mul(714,667)+])mul(925,432,]~>mul(283,331)why()/*where()where()select()when()mul(243,952)/?{!!(mul(915,41);>(when()$#%mul(947,866)where()mul(221,297) select()>where()select()^$%mul(332,570)%]]mul(158,640)]don't()what(145,439)where() /-what()~ mul(800,255)mul(262,849)>}what()(how()why()^when()>mul(531,160)>(!;;from()mul(204,760)mul(513,132) ]why(657,793)[;>@[who()mul(884,112)-#/mul(29,581),when()[)'}:&mul(252,198)<select()?where()}$,~mul(814,493)!^where()?who() ][why()mul(654,203):&{]where()($[mul(635,667)%${}&$',mul(427,557) ~[{ %-mul(924,456)from(){^select()how()+mul(91,270)-<;>>don't()$?how()#<>{;mul(388how()?)mul(437,372),what()^/} !?when(423,466)-mul(413,767)+%!select()mul(404,30)]-,:when()when()mul(83,621)$mul(163,330)*when()!$?^^)${do()mul(836,70)how(146,272)*<-(+who(75,343)>}mul(326,92)]~())$(-!mul(377,382)mul(183,94)why()when()&from()don't();who()(? ?where()<from()!;+?why()mul(766,106)how()*@;$mul(26,169)what()why()mul(407,336)select()mul(781,609)mul(567,131)%[when()<}mul(842,16)+(-~*}why(75,75)((mul(404,299)'];('select()&}(>mul(980,817),mul(759,27)when()$'mul(816,327)*&how()where()?*how(410,340)^mul(10,377)[mul#-<(+@mul(60,556)what()%;from() '%why()who()mul(71,194)]]@mul(54,618)when()['select()+(who()(~mul(615,986)] /how():+(&~mul(360,511)&how()don't()where()who()mul(387,887)?where()}#/what()what() mul(565,98)-!^?where()from(516,387)-}where()mul(852,909)~@where()%%why()}&-mul(964,784)#mul(351,184):)&mul(752,380)>mul(565,263));]mul(176,301)>^mul(724,532){how()~*,,{-mul(983,550){[select()>)mul(512}(]}-why()/why()mul(942,275),why()how()$;how()who()-?mul(111,602)where() ,)/{mul(647,51when()mul(752,155)]])]%/select()select(601,543)how(422,122)-mul(327,205)mul(108,233)select()how():do()},- when():mul(436,39) ?>:why()when()how()@?mul(544,861)]when()% mul(171,396)$who()@'mul(98,466)-why()+-~#mul(202,977)mul(65,156)what()mul(916,837)select()']?>*$'>}mul(248,949)}']%who()where(44,472)&;why()how(272,628)don't()%):,where()select()what()how()when()%mul(119,722)*when()/'[?mul(235,988):what()($?}$how()-mul(401,478)#:why()'{}what()#mul(760,203)<;#[:mul(594,881)%# (when()[where()/#!/usr/bin/perl,@;mul(794,217)select():'])select()mul(801,192)why()&]why()/:]*#mul(319,363^:]when()^?[when()do()!%!/:#^select()mul(189,908what():mul(439,753)~+>mul(889,297)$#-select()$mul(665,576)/@do()when()@@<*?mul(783,215)how()%what()where(259,619)(who()((mul(101,739)@from():,)?'who()-when()mul(935,345)why():,~:[;why();mul(344,351)#from()who()where()~)when()what()/mul(349,325)?%*~~-select()]mul(677,728)from()$mul(34,791)when()/what()(mul(162,982)%+!why()!how())when()mul(352,740))%when()why()mul(409,310)mul(969,23)what()when()(>[who()why() @mul(6,54)>-what()from(58,461)'mul(465,807)(mul(526,458)how()}{:;*[&mul(396,93)([]who()]*mul(719,44)?what()}mul(144[}&'#,where()mul(404,362)[$/who()^mul(402,634)-who()+mul(210,882)~select(){+where()mul(113,5)/]mul(686,939)why()why()?$?where()mul(893,419)how()mul(522,816)why()'&];don't()mul(564,983)),mul(752,484)~}!from(),mul(794,228)mul(666,12)!>[who()why()%:mul(942,336),%^%don't()mul(974,403)}()<^{@ mul(34~?')+ ^where()what(438,775)mul(398,351)%;#*mul(608,425)-how();what(581,569)/}(where()mul(657,344)mul(952,983):mul(563,153))##~*<('who(910,367)mul(597,553)]) +}&/,mul(42,25)^-where()- {&?>mul(243,985)(where()what()mul(748,181)why()<*how()~ ]why()mul(513,836)^mul(528,931)^from()%mul(394,906)>&what()why()}select()mul(748,101)@{:mul(588,99)+^<]select()what()mul(762,499)*who()}mul(115,70)::$%>}mul(358,497)*$%how()mul(4from()>!]*>$)#how()from()don't()[{when()#where()why()where()why()mul(673,980)who(449,344)/@mul(632,452)from()where()*how()}?)][[mul(827,726)@~from()-mul(248,669)mul(745,698){mul(701<:how()what()mul(507,429)}when(638,137)mul(205,534)what(),{mul(98,543)do(),/*when()mul(242,591)#where()+mul(727,599);who()mul(127,428)'why()[';mul(731,342)%:$who()what()$+do()*mul(739,211):'' !what()?,&]mul(87,206)+,who()>/&^~select(648,639)!,mul(262,674) +,+who():mul(327,845)/ >@[>@}}mul(86,371)!~&&~how(79,334)mul(637,103)why()mul(358,845)-#~?why(243,672)select()+why()from()~mul(216,782)&mul(111,955);what()~mul(677,376)select()when()mul(576,14)!}mul(70,850)^::select()what()mul(705,544)how(707,500)-where()how()what()mul(830,398)who()!do()mul(626,675)+where()<}who():mul(574,508)!;mul(306,829)&+)>what()@<{[~mul(795who()#*'where()who()?mul(548,420)*) %:when()when()mul(332,202)when()'where()^mul(72,648)]mul(866,929)mul(444,217}#mul(563,200)*select(581,639)!}who()/how()$mul(584,32)select(27,591)[#'mul(401,424)>,),mul(781&select()do()}what()#what()@what()<;mul(897,939)+where(),why()%mulhow()%where(203,705)mul(389,118)-what()select()&how())*@ $mul(316,546);]when()^-mul(730when()why()'+:*mul(433,570);-/]:select()(*#who()mul(12,582)[from()(how()!who()?)&,mul(474,681)mul(288,311)mul(281,240what()select(){!mul(564,631)@'<[how()mul(972,373)mul(188,118)mul(630,960),/mul(105,916)how()#/mul(215,263)when():mul(257,474)[what()mul(565,99)*mul(195,386)[mul(695,513)from()#mulhow()mul(354,472)%-^when()%:}mul(420,822)]&mul(409,240)@where()!mul(65,591)mul(2,270)-]))from()mul(895,507){-what()^?#~ mul(13,268):why(919,274)]mul(37,808)}])why()+#+mul(19,585)from()how()%:$(where()mul(457,746)]mul(715,809)]+mul(542,65)@/):how(169,336)?when()~mul(871,498)]/{~~who()mul(438,984)what()from(289,777)/*}:*$%mul(176,297)&mul(404,56))mul(617,647)!when(){^what()why()}<^mul(412,110)where())#how()#;where()%&,mul(158,588) ~ from()'-^[select()mul(383,762)mul(215,479)%/:where()#[)who(567,411)mul(618,506)'from()}/how() )'~{mul(597,824)mul(130,88)when()-*how(891,580)mul(673,686);what()';,mul(404,486)-:when():&:$/??mul(335,183)/select()#why()what()who(396,219)mul(209,514)->)when()>;!>/from()mul(290,830) /what()~,mul(127,362)[%select()!mul(218,584)**}%'where()mul(806,757)when()>select()!why(343,900)(mul(416,926),&don't()#mul(140,136)(^mul(586,293)'from()~;)$mul(465,127)mul(50,37)select()from()how() )when()@/select()when()mul(268,549)~from()#)]why()^;?mul(928,48)where()&!mul(238,685)(/,mul(868,701)'* why()what()how()<%<-mul(147,775)(%%from();;mul(485,402){select()~,%]^mul(497,239)why()(mul(483,579)!mul(633,187)from(){how()'-[;$-mul(351,722)from()mul(376,405)mul(773,301)mul(714,478)&'&( mul(15,892)from()/when()}/^;>#,mul(416,32)~?@(*>'when():who()where()mul(550,92)mul(706,856){from()*from()mul(129,641)*from())where()mul(361,904)>why()mul(556,900)#/;,how()?mul(820,572) +where()#{*,!?:$mul(204,279)what()!{ what()mul(117,94)!select()>:mul(665,432)#don't()!!]{mulwhen()'+{mul(533,772)why(708,386)mul(985,538)how()where()<%@;*mul(541,123)*/when()do()*@mul(689,5)]from()]~{@<[mul(624,102)how()*select()['?what()},;mul(689,339)when(),from()where()how(741,43)what()when()mul(976,335)$^mul(488,361)how()'?*$:don't()-/>%:why():from()+mul(273,731)?$?*what(312,921);{->mul(258,938)'mul(744,815)~!who()>[who()@(who()mul@select()when()&mul(244,475)@mul(642,298)'>when()+from()<{mul(73,293)do()what()}??when()from()mul(989,486)what()^mul(353,226)?%where()}]%,mul(452,316):~mul(156,967)?!mul(19,394)!,},when()<@mul-[>,mul(174,673):>#mul(874,712)from()])what(),'@how(667,413)(;mul(241,907)mul(320,563#{how()(mul(124,628)^!select()from(935,468)@when()when()-'how(466,423);mul(279,559)why()!$what(){:{why()from()mul(649,790);,?%&'/why()^&mul(534,924)>-!?when(){~$mul(158,17?#mul(968,123)what()who()>mul(250,420)mul(337,422)}(how()>-{*- do()+(}~(,>who()mul(76,293);mul(293,210)*+?mul(438,928)]%~,%/#@[mul(183,794)+how() ;>}who()mul(332,416),why(801,76),+%don't())select(){where()what();-who()-mul(606,374)mul(534,560)$:~who()/ )%mul(51,112)%[<];-(mul(713,297)how()mul(865,283)when()?[!;from()^%mul(852,418)mul(981,822)+&/{from()}{]what(134,416)when()mul(106,954)@who()>]why(){')&mul(638,435))! where(256,980)/from()?mul(742,736)mul(178,260)!select()do()!~mul(235,409)mul(4,876)&#:/how()how())mul(779,7)who()[]mul(257,563)who()from()mul(269,328):don't()^;?who()&how() mul(940,691)*'+how()%&mul(207,615)mul(22,730)}){;what(777,379)~who()~!mul(304,887)!$how()mul(897,888)?>*when()]/mul(28,168)when()+^:*}>mul(383,29)mul(467,873)@/-, ]-from()%*mul(520,584)-how()(select()>^{$:(][-mul(866,764):[@,;?*}*@]when()mul(702,803)mul(417,62)from()-mul(405,512){)]/from()&mul(680,378)from()mul(272,215)-mul(678,155)]:why()who()@/how():@mul(327,946)!#when()+mul(484,853)!+? diff --git a/utils.zig b/utils.zig new file mode 100644 index 0000000..e913053 --- /dev/null +++ b/utils.zig @@ -0,0 +1,152 @@ +const std = @import("std"); + +// pub const LineReader = struct { +// const FileReader = std.fs.File.Reader; +// const BufferedReader = std.io.BufferedReader(4096, FileReader); +// const Reader = std.io.Reader(*BufferedReader, std.fs.File.Reader.Error, BufferedReader.read); + +// alloc: std.mem.Allocator, + +// file: std.fs.File, + +// line_buf: std.ArrayList(u8), + +// buf_reader: *BufferedReader, +// reader: Reader, + +// pub fn init(alloc: std.mem.Allocator, filename: []const u8) !LineReader { +// const file = try std.fs.cwd().openFile(filename, .{}); + +// const file_reader = file.reader(); + +// const buf_reader = try alloc.create(BufferedReader); +// buf_reader.* = std.io.bufferedReader(file_reader); + +// const reader: Reader = Reader{ .context = buf_reader }; + +// const line_buf = std.ArrayList(u8).init(alloc); + +// return .{ +// .alloc = alloc, +// .file = file, +// .line_buf = line_buf, +// .buf_reader = buf_reader, +// .reader = reader, +// }; +// } + +// pub fn deinit(self: *LineReader) void { +// self.file.close(); + +// self.line_buf.deinit(); + +// self.alloc.destroy(self.buf_reader); +// } + +// pub fn next(self: *LineReader) !?[]u8 { +// self.line_buf.clearRetainingCapacity(); + +// self.reader.streamUntilDelimiter(self.line_buf.writer(), '\n', 4096) catch |err| switch (err) { +// error.EndOfStream => return null, +// else => return err, +// }; + +// return self.line_buf.items; +// } +// }; + +pub const FileReader = struct { + const BufferedReader = std.io.BufferedReader(4096, std.fs.File.Reader); + const Reader = std.io.Reader(*BufferedReader, std.fs.File.Reader.Error, BufferedReader.read); + + alloc: std.mem.Allocator, + + file: std.fs.File, + + buf_reader_ptr: *BufferedReader, + + pub fn init(alloc: std.mem.Allocator, filename: []const u8) !FileReader { + const file = try std.fs.cwd().openFile(filename, .{}); + + const file_reader = file.reader(); + + const buf_reader_ptr = try alloc.create(BufferedReader); + buf_reader_ptr.* = std.io.bufferedReader(file_reader); + + return .{ + .alloc = alloc, + .file = file, + .buf_reader_ptr = buf_reader_ptr, + }; + } + + pub fn deinit(self: FileReader) void { + self.file.close(); + + self.alloc.destroy(self.buf_reader_ptr); + } + + pub fn reader(self: FileReader) Reader { + return Reader{ .context = self.buf_reader_ptr }; + } +}; + +pub fn LineReader(comptime ReaderType: type) type { + return struct { + const Self = @This(); + + reader: ReaderType, + + line_buf: std.ArrayList(u8), + + pub fn init(alloc: std.mem.Allocator, reader: ReaderType) Self { + const line_buf = std.ArrayList(u8).init(alloc); + + return .{ + .reader = reader, + .line_buf = line_buf, + }; + } + + pub fn deinit(self: *Self) void { + self.line_buf.deinit(); + } + + pub fn next(self: *Self) !?[]u8 { + self.line_buf.clearRetainingCapacity(); + + self.reader.streamUntilDelimiter(self.line_buf.writer(), '\n', 4096) catch |err| switch (err) { + error.EndOfStream => if (self.line_buf.items.len == 0) { + // the first time we get an EndOfStream we return the content of the line_buf, + // the second time we're finished + return null; + }, + else => return err, + }; + + return self.line_buf.items; + } + }; +} + +pub fn lineReader(alloc: std.mem.Allocator, reader: anytype) LineReader(@TypeOf(reader)) { + return LineReader(@TypeOf(reader)).init(alloc, reader); +} + +pub fn NumberParser(comptime T: type) type { + return struct { + token_it: std.mem.TokenIterator(u8, .scalar), + + pub fn next(self: *@This()) !?T { + if (self.token_it.next()) |tok| { + return try std.fmt.parseUnsigned(T, tok, 10); + } + + return null; + } + }; +} + +pub fn numberParser(comptime T: type, input: []const u8) NumberParser(T) { + return NumberParser(T){ .token_it = std.mem.tokenizeScalar(u8, input, ' ') }; +}