diff --git a/day1/input-part1 b/day1/input-part1 new file mode 100644 index 0000000..ba38c4a --- /dev/null +++ b/day1/input-part1 @@ -0,0 +1,200 @@ +1322 +1211 +1427 +1428 +1953 +1220 +1629 +1186 +1354 +1776 +1906 +1849 +1327 +1423 +401 +1806 +1239 +1934 +1256 +1223 +1504 +1365 +1653 +1706 +1465 +1810 +1089 +1447 +1983 +1505 +1763 +1590 +1843 +1534 +1886 +1842 +1878 +1785 +1121 +1857 +1496 +1696 +1863 +1944 +1692 +1255 +1572 +1767 +1509 +1845 +1479 +1935 +1507 +1852 +1193 +1797 +1573 +1317 +1266 +1707 +1819 +925 +1976 +1908 +1571 +1646 +1625 +1719 +1980 +1970 +1566 +1679 +1484 +1818 +1985 +1794 +1699 +1530 +1645 +370 +1658 +1345 +1730 +1340 +1281 +1722 +1623 +1148 +1545 +1728 +1325 +1164 +1462 +1893 +1736 +160 +1543 +1371 +1930 +1162 +2010 +1302 +1967 +1889 +1547 +1335 +1416 +1359 +1622 +1682 +1701 +1939 +1697 +1436 +1367 +1119 +1741 +1466 +1997 +1856 +1824 +1323 +1478 +1963 +1832 +1748 +1260 +1244 +1834 +1990 +1567 +1147 +1588 +1694 +1487 +1151 +1347 +1315 +1502 +546 +730 +1742 +1869 +1277 +1224 +1169 +1708 +1661 +174 +1207 +1801 +1880 +1390 +1747 +1215 +1684 +1498 +1965 +1933 +1693 +1129 +1578 +1189 +1251 +1727 +1440 +1178 +746 +1564 +944 +1822 +1225 +1523 +1575 +1185 +37 +1866 +1766 +1737 +1800 +1633 +1796 +1161 +1932 +1583 +1395 +1288 +1991 +229 +1875 +1540 +1876 +1191 +1858 +1713 +1725 +1955 +1250 +1987 +1724 diff --git a/day1/main.zig b/day1/main.zig new file mode 100644 index 0000000..5e01860 --- /dev/null +++ b/day1/main.zig @@ -0,0 +1,94 @@ +const std = @import("std"); + +pub fn main() !void { + var allocator = std.heap.GeneralPurposeAllocator(.{}){}; + var f = std.fs.File { .handle = try std.os.open("input-part1", std.os.O_RDONLY, 0) }; + var buffer : [1024]u8 = undefined; + var expenses = std.ArrayList(u32).init(&allocator.allocator); + defer expenses.deinit(); + + var byte_buffer = std.ArrayList(u8).init(&allocator.allocator); + defer byte_buffer.deinit(); + + var read = try f.read(&buffer); + std.log.info("Read {} bytes", .{read}); + while (read != 0) { + for (buffer) | v, k | { + if (std.ascii.isDigit(v)) { + try byte_buffer.append(v); + } + if (v == '\n') { + var x = atoi(byte_buffer.items[0..]); + //std.log.debug("{}", .{x}); + try expenses.append(x); + // Set the position back to zero, without freeing existing memory + byte_buffer.deinit(); + byte_buffer = std.ArrayList(u8).init(&allocator.allocator); + } + } + read = try f.read(&buffer); + //std.log.info("Read {} bytes", .{read}); + } + //std.log.info("{}", .{expenses.items.len}); + part1(expenses.items[0..]); + part2(expenses.items[0..]); +} + +fn part2(expenses : []u32) void { + var i : u32 = 0; + var elements : [3]u32 = undefined; + while (i < expenses.len) : (i += 1) { + var j : u32 = 0; + while (j < expenses.len) : (j += 1) { + var k : u32 = 0; + while (k < expenses.len) : (k += 1) { + if (k == j or k == 1) { + continue; + } + if (expenses[i] + expenses[j] + expenses[k] == 2020) { + elements[0] = expenses[i]; + elements[1] = expenses[j]; + elements[2] = expenses[k]; + } + } + } + } + std.log.info("{} and {} and {} sum to {} and multiply to {}", + .{elements[0], elements[1], elements[2], elements[0] + elements[1] + elements[2], + elements[0] * elements[1] * elements[2]}); +} + +fn part1(expenses : []u32) void { + var i : u32 = 0; + var elements : [2]u32 = undefined; + while (i < expenses.len) : (i += 1) { + var j : u32 = 0; + while (j < expenses.len) : (j += 1) { + if (i == j) { + continue; + } + if (expenses[i] + expenses[j] == 2020) { + elements[0] = expenses[i]; + elements[1] = expenses[j]; + } + } + } + std.log.info("{} and {} sum to {} and multiply to {}", + .{elements[0], elements[1], elements[0] + elements[1], + elements[0] * elements[1]}); +} + +fn atoi(a: []u8) u32 { + var i : u32 = 0; + for(a) |v, k| { + if (! std.ascii.isDigit(v)) { + std.log.warn("Byte {x} is not a digit", .{v}); + continue; + } + // 48 is '0' in ascii + std.debug.assert(v >= 48 and v < 58); + i += @as(u32, (v - 48) * std.math.pow(u32, 10, @intCast(u32, a.len - k - 1))); + } + //std.log.debug("{x} --> {}", .{a, i}); + return i; +} diff --git a/day10/build.zig b/day10/build.zig new file mode 100644 index 0000000..93d2d11 --- /dev/null +++ b/day10/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day10", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day10/input b/day10/input new file mode 100644 index 0000000..0cf7ad7 --- /dev/null +++ b/day10/input @@ -0,0 +1,94 @@ +138 +3 +108 +64 +92 +112 +44 +53 +27 +20 +23 +77 +119 +62 +121 +11 +2 +37 +148 +34 +83 +24 +10 +79 +96 +98 +127 +7 +115 +19 +16 +78 +133 +61 +82 +91 +145 +39 +33 +13 +97 +55 +141 +1 +134 +40 +71 +54 +103 +101 +26 +47 +90 +72 +126 +124 +110 +131 +58 +12 +142 +105 +63 +75 +50 +95 +69 +25 +68 +144 +86 +132 +89 +128 +135 +65 +125 +76 +116 +32 +18 +6 +38 +109 +111 +30 +70 +143 +104 +102 +120 +31 +41 +17 diff --git a/day10/src/main.zig b/day10/src/main.zig new file mode 100644 index 0000000..f38f631 --- /dev/null +++ b/day10/src/main.zig @@ -0,0 +1,299 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + var it = std.mem.tokenize(contents, "\n"); + var joltages = std.ArrayList(u32).init(gpa); + defer joltages.deinit(); + while (it.next()) |line| { + try joltages.append(atoi(line)); + } + var chain = try JoltageChain.construct_chain(gpa, joltages.items[0..]); + defer chain.deinit(); + std.log.info("Product of one_diffs and three_diffs of joltage chain: {}", + .{chain.part_one()}); + + var permutations = try chain.calculate_permutations(); + std.log.info("{} permutations", .{permutations}); +} + +const Tree = struct { + children : std.ArrayList(*Tree), + allocator: *std.mem.Allocator, + value : u32 = 0, + dirty : bool = true, + perms : u64 = 0, + + fn init(allocator: *std.mem.Allocator, value: u32) !*Tree { + var self = try allocator.create(Tree); + errdefer allocator.destroy(self); + self.allocator = allocator; + self.value = value; + self.children = std.ArrayList(*Tree).init(allocator); + return self; + } + + fn deinit(self: *Tree) void { + self.children.deinit(); + self.allocator.destroy(self); + } + + fn add_child(self: *Tree, child: *Tree) !void { + try self.children.append(child); + self.dirty = true; + } + + fn find_child_by_value(self: *Tree, value: u32) ?*Tree { + if (self.value == value) { + return self; + } + for (self.children.items) |c| { + var t = c.find_child_by_value(value); + if (t) |_t| { + return _t; + } + } + return null; + } + + // caching the calculation of the perm count makes it possible to + // finish reasonbly quickly when revisiting nodes that have already + // been seen + fn perm_count(self: *Tree) u64 { + if (!self.dirty) { + return self.perms; + } + var count : u64 = 0; + if (self.children.items.len == 0) { + count = 0; // No permutation, since have can only go one way + } + else if (self.children.items.len == 1) { + // We only have ourself + count = std.math.max(1, self.children.items[0].perm_count()); + } + else { + for(self.children.items) |c| { + count += std.math.max(1, c.perm_count()); + } + } + self.perms = count; + self.dirty = false; + return count; + } + + fn print_tree(self: *Tree) void { + std.log.warn("{} children:\n", .{self.value}); + for(self.children.items) |c| { + c.print_tree(); + } + } +}; + +const JoltageChain = struct { + allocator: *std.mem.Allocator, + joltages : std.ArrayList(u32), + + pub fn construct_chain(allocator: *std.mem.Allocator, j: []u32) !*JoltageChain { + var self = try allocator.create(JoltageChain); + errdefer allocator.destroy(self); + + self.joltages = std.ArrayList(u32).init(allocator); + self.allocator = allocator; + + // This has a side effect of modifying j... + std.sort.insertionSort(u32, j[0..], {}, comptime std.sort.asc(u32)); + try self.joltages.append(0); // Always start at zero + var last_joltage : u32 = 0; + for (j) |x| { + if ((x-last_joltage)<4) { + try self.joltages.append(x); + last_joltage = x; + } + else { + break; + } + } + try self.joltages.append(last_joltage + 3); + return self; + } + + pub fn deinit(self: *JoltageChain) void { + self.joltages.deinit(); + self.allocator.destroy(self); + } + + pub fn part_one(self: *JoltageChain) u32 { + var one_diffs : u32 = 0; + var three_diffs : u32 = 0; + for (self.joltages.items) |v, k| { + if (k == 0) { + continue; + } + var delta : u32 = v - self.joltages.items[k-1]; + if (delta == 1) { + one_diffs += 1; + } + if (delta == 3) { + three_diffs += 1; + } + } + std.log.debug("Found {} one diffs, and {} three diffs", + .{one_diffs, three_diffs}); + return one_diffs * three_diffs; + } + + // this is a garbage way of doing it and just crushes CPU/memory + // it does work for small datasets though + pub fn calculate_permutations(self: *JoltageChain) !u32 { + var tree = try Tree.init(self.allocator, self.joltages.items[0]); + var current_node : *Tree = undefined; + var count : u32 = 0; + + // Finding in the tree seems v. slow, will use a hash map for lookup + // it is also much easier to try and deinit + var map = std.hash_map.AutoHashMap(u32, *Tree).init(self.allocator); + try map.ensureCapacity(@intCast(u32, self.joltages.items.len)); + map.putAssumeCapacityNoClobber(self.joltages.items[0], tree); + for (self.joltages.items) |v, k| { + var _t = map.get(v); + if (_t) |t| { + current_node = t; + } + else { + unreachable; + } + //std.log.warn("Current node: {}", .{current_node}); + var n : usize = k+1; + while (n < self.joltages.items.len) : (n += 1) { + //std.log.warn("{}", .{n}); + if ((self.joltages.items[n] - v) <= 3) { + var value = self.joltages.items[n]; + _t = map.get(value); + if (_t) |t| { + try current_node.add_child(t); + //std.log.warn("Added existing child {} to {}", .{value, v}); + } + else { + var t = try Tree.init(current_node.allocator, value); + try current_node.add_child(t); + map.putAssumeCapacityNoClobber(value, t); + //std.log.warn("Added new child {} to {}", .{value, v}); + } + } + } + } + std.log.warn("tree count: {}", .{tree.perm_count()}); + // Need to do some cleanup + var it = map.iterator(); + while (it.next()) |kv| { + kv.value.deinit(); + // don't remove from map, since it may modifying the underlying structure? (source?) + // and we're about to deinit it anyway + } + map.deinit(); + return count; + } +}; + +test "joltage_chain" { + var joltages = [_]u32 { + 16, + 10, + 15, + 5, + 1, + 11, + 7, + 19, + 6, + 12, + 4, + }; + var chain = try JoltageChain.construct_chain(std.testing.allocator, joltages[0..]); + var diff = chain.part_one(); + std.testing.expectEqual(diff, 7*5); + var perm = chain.calculate_permutations(); + + chain.deinit(); +} + +test "joltage_chain" { + var joltages = [_]u32 { + 28, + 33, + 18, + 42, + 31, + 14, + 46, + 20, + 48, + 47, + 24, + 23, + 49, + 45, + 19, + 38, + 39, + 11, + 1, + 32, + 25, + 35, + 8, + 17, + 7, + 9, + 4, + 2, + 34, + 10, + 3, + }; + var chain = try JoltageChain.construct_chain(std.testing.allocator, joltages[0..]); + var diff = chain.part_one(); + std.testing.expectEqual(diff, 220); + var perm = chain.calculate_permutations(); + + chain.deinit(); +} + +fn atoi(a: []const u8) u32 { + var i : u32 = 0; + var mul : u32 = 1; + var start : usize = 0; + if (a[0] == '-' or a[0] == '+') { + start = 1; + if (a[0] == '-') { + //mul *= -1; + unreachable; + } + } + for(a[start..]) |v, k| { + if (! std.ascii.isDigit(v)) { + std.log.warn("Byte {x} is not a digit", .{v}); + continue; + } + // 48 is '0' in ascii + std.debug.assert(v >= 48 and v < 58); + i += @as(u32, @as(u32, (v - 48)) * std.math.pow(u32, 10, @intCast(u32, a.len - k - 1 - start))); + } + //std.log.debug("0x{x} --> {}", .{a, i}); + return i * mul; +} + +test "atoi_regular" { + var i = atoi("1234"); + std.testing.expectEqual(i, 1234); +} + +test "atoi_pos" { + var i = atoi("+1234"); + std.testing.expectEqual(i, 1234); +} diff --git a/day11/build.zig b/day11/build.zig new file mode 100644 index 0000000..9731217 --- /dev/null +++ b/day11/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day11", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day11/input b/day11/input new file mode 100644 index 0000000..6a466bd --- /dev/null +++ b/day11/input @@ -0,0 +1,98 @@ +LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +L.L...L...LL.LL.......LL...LL.L...LL..LL..L.......LLLLL.....LL..LLLL.L....L..L...L.LL....LL...L +LLLLL.LLLLL.LLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLL.LL.LLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LL.LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLL.LL.LLLLLLLLL.LLLL.LLLL.LLLL.L.LLLL +LLLLL.LLLL.LLLL.LLL.LLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLL.LLL.LL.LLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +.L.....L.LL..LLL.L..L...L.LLL.L...L.L.L.L.....L..L.......L.LLL...L.......L.LLLL......L.L.L...LL +LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL..LLLLLL.LLLL.LLLL.L.LL.LLLLLLLLL.LLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LL.LLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +.L..LLL.L...LL.....LL......LL...L...LL...L.L..L....L.L.L.LL.L........L....LL......L..LL..LL.... +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLL..LLLL.LLLLLL.LLLLLLLLLLL.LL.LLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL..L.LLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLL.LLLLLLLLLL.LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +L.LLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL +LLLL....L.......L..LLL...........L..L...LL..L.L.LLL...L.....LL..LL..L....L....L..LL..LL.L....L. +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.L.LLLLLLLLLLLL.LLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLL..LLL.LLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLL.L.LLLL.LL.L.LL.LLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +.LL........L.....L.L.L.......LL.L.L.......LLL.........L....LL........L.L..L......L.LL......L..L +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.L.LLLLLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLL +LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.L.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLL..LLLLLL.LLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLL.LL.L.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +.L..L...L........L.......L.L.LL.LLLL...LLL.L.L..L.L....L.................L.L.L.L....L...L...L.. +LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLL +LLLLL.LL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLL...LLL.......LL..L.L.L.L...L........LL..............L.L......L.......L..LL....L....LL...LL. +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLL.L.LLLLLLL.LLLLLLLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLL..LLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.L.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLLL.L.LL.LLLLLL.LLLLLLLLLLL.LL.LLLLLLLLL.LLL.LL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LL.LL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLL.L...LL.......LL..L.....L.LL..L....L.L..L.......L..L......LLLLL..L.L..L......L...L.L...L.L. +LLLLL.LLL..LLLL.LLLLLL.LLLLL.LLL.LLLLL.L.LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLL.LLLLLLLL..LLLLLL +LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +L.L...............L..L.LLLL...L..L...LLL.......LLL.LL........L..LL..L..L...L.L.L.LL..LLLL.L.LL. +LLLLLLLL.L.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL +L.LLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLL.LLLLLLL.LLLL.LLLL.LLLLLL +.L..LL.L.L..L...L....L......LLL......L.LL..L....L.LLLL.LL.....L.L.LL.L.....L......L.LL......... +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLL..LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLL +LLLLL.LLL..LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL..LLL.LLLLLLLLLLLLLLLL +.LLL......L.L.L......L.....LL......L.LLL.LLL..LL...L.L.......L..L.......L....L.....L.......LL.. +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LL...L...........L...L..L......LL...........L...L.LL..LL....L....LLL.LLLL....LLL...LL..L..L...L +LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLL.LLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL +LLLLL.LL.LLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLL..LLLL.LLL..LLLLLLLLLLL +.......L...LL.L.....L.L.....LLL.L.......L.....LL.......L..LLL.....L.LL.L..........LL........... +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLL.LL.LL.LLL.LLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLL..LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL diff --git a/day11/src/main.zig b/day11/src/main.zig new file mode 100644 index 0000000..3da8f89 --- /dev/null +++ b/day11/src/main.zig @@ -0,0 +1,482 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + var gpa = &arena.allocator; + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + + var seatmap = try SeatMap.init(gpa); + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + try seatmap.add_line(line); + } + + var changed : usize = 0; + changed = try seatmap.process_round(); + while (changed != 0) { + //changed = try seatmap.process_round(); + changed = try seatmap.process_round_part2(); + } + std.log.info("{} occupied seats", .{seatmap.count_occupied()}); +} + +const NeighbourState = struct { + count: usize = 0, + occupied: usize = 0, + free: usize = 0, +}; + +const SeatMap = struct { + allocator: *std.mem.Allocator, + data: std.ArrayList(u8), + width: usize = 0, + height: usize = 0, + + pub fn init(a: *std.mem.Allocator) !*SeatMap { + var self = try a.create(SeatMap); + errdefer a.destroy(self); + + // if we use self.* = .{}; then we don't forget + // obligatory fields + // also, when using self.* = .{} the fields with + // defaults are properly initialized!!! it is + // an error to not use it. + self.* = .{ + .allocator = a, + .data = std.ArrayList(u8).init(a), + }; + return self; + } + + pub fn deinit(self: *SeatMap) void { + self.data.deinit(); + self.allocator.destroy(self); + } + + pub fn count_occupied(self: *SeatMap) u64 { + var c: u64 = 0; + for (self.data.items) |i| { + if (i == '#') { + c += 1; + } + } + return c; + } + + pub fn print(self: *SeatMap) !void { + var stdout = std.io.getStdOut(); + var i : usize = 0; + while (i < self.height) : (i += 1) { + _ = try stdout.write(self.get_row(i)); + _ = try stdout.write("\n"); + } + } + + pub fn get_row(self: *SeatMap, row: usize) []u8 { + return self.data.items[self.width*row..(self.width*row)+self.width]; + } + + pub fn add_line(self: *SeatMap, line: []const u8) !void { + if (self.width != 0) { + std.debug.assert(line.len == self.width); + } + else { + self.width = line.len; + } + try self.data.appendSlice(line[0..]); + self.height += 1; + } + + // returns the number of seats changed + pub fn process_round(self: *SeatMap) !u64 { + // First, since operations happen concurrently, + // we mark all of our changes to a temporary buffer + var buffer = try self.allocator.alloc(u8, self.data.items.len); + defer self.allocator.free(buffer); + + // Iterate above (row, col) pairs + var row : usize = 0; + var n_changed : u64 = 0; + while (row < self.height) : (row += 1) { + var col : usize = 0; + while (col < self.width) : (col += 1) { + if (self.index_of(row, col)) |i| { + buffer[i] = self.get_new_seat_state(row, col, i); + if (buffer[i] != self.data.items[i]) { + n_changed += 1; + } + } + } + } + + // Copy buffer to self.data.items + std.mem.copy(u8, self.data.items, buffer); + return n_changed; + } + + pub fn get_new_seat_state(self: *SeatMap, row: usize, col: usize, index: usize) u8 { + // Floor remains unchanged + var c = self.data.items[index]; + var new_c : u8 = undefined; + if (c == '.') { + new_c = '.'; + } + + // this gives us a struct w/ .count, .occupied, .free + var neighbour_state = self.get_neighbour_state(row, col); + if (c == 'L') { + if (neighbour_state.occupied == 0) { + new_c = '#'; + } + else { + new_c = c; + } + } + if (c == '#') { + if (neighbour_state.occupied >= 4) { + new_c = 'L'; + } + else { + new_c = c; + } + } + //std.log.debug("({},{}) was '{c}' and will be '{c}'. {} neighbors, {} occupied", + // .{row, col, c, new_c, neighbour_state.count, neighbour_state.occupied}); + return new_c; + } + + pub fn get_neighbour_state(self: *SeatMap, row: usize, col: usize) NeighbourState { + var r: usize = switch(row) { + 0 => row, + else => row - 1, + }; + var count: usize = 0; + var free: usize = 0; + var occupied: usize = 0; + while (r <= row+1) : (r += 1) { + var c: usize = switch(col) { + 0 => col, + else => col - 1, + }; + while (c <= col+1) : (c += 1) { + if (row == r and col == c) { + continue; + } + if (self.index_of(r, c)) |i| { + if (self.data.items[i] == '.') { + // Floor spots don't contribute to neighbour, + // free, or occupied counts. + continue; + } + count += 1; + if (self.data.items[i] == '#') { + occupied += 1; + } + else { + free += 1; + } + } + } + } + return NeighbourState { + .count = count, + .free = free, + .occupied = occupied, + }; + } + + // returns the number of seats changed + pub fn process_round_part2(self: *SeatMap) !u64 { + // First, since operations happen concurrently, + // we mark all of our changes to a temporary buffer + var buffer = try self.allocator.alloc(u8, self.data.items.len); + defer self.allocator.free(buffer); + + // Iterate above (row, col) pairs + var row : usize = 0; + var n_changed : u64 = 0; + while (row < self.height) : (row += 1) { + var col : usize = 0; + while (col < self.width) : (col += 1) { + if (self.index_of(row, col)) |i| { + buffer[i] = self.get_new_seat_state_round2(row, col, i); + if (buffer[i] != self.data.items[i]) { + n_changed += 1; + } + } + } + } + + // Copy buffer to self.data.items + std.mem.copy(u8, self.data.items, buffer); + return n_changed; + } + + pub fn get_new_seat_state_round2(self: *SeatMap, row: usize, col: usize, index: usize) u8 { + // Floor remains unchanged + var c = self.data.items[index]; + var new_c : u8 = undefined; + if (c == '.') { + new_c = '.'; + } + + // this gives us a struct w/ .count, .occupied, .free + var neighbour_state = self.get_neighbour_state_round2(row, col); + if (c == 'L') { + if (neighbour_state.occupied == 0) { + new_c = '#'; + } + else { + new_c = c; + } + } + if (c == '#') { + if (neighbour_state.occupied >= 5) { + new_c = 'L'; + } + else { + new_c = c; + } + } + //std.log.debug("({},{}) was '{c}' and will be '{c}'. {} neighbors, {} occupied", + // .{row, col, c, new_c, neighbour_state.count, neighbour_state.occupied}); + return new_c; + } + + pub fn get_neighbour_state_round2(self: *SeatMap, row: usize, col: usize) NeighbourState { + var count: usize = 0; + var free: usize = 0; + var occupied: usize = 0; + var direction_vectors = [_][2]i64 { + [_]i64{-1, -1}, // up and left, + [_]i64{-1, 0}, // left + [_]i64{-1, 1}, // down and left, + [_]i64{0, 1}, // down + [_]i64{1, 1}, // right and down + [_]i64{1, 0}, // right + [_]i64{1, -1}, // right and up, + [_]i64{0, -1}, // up + }; + var row_signed = @intCast(i64, row); + var col_signed = @intCast(i64, col); + for (direction_vectors) |dv| { + var space_count : i64 = 0; + var has_neighbour: bool = false; + var last_neighbour_was_occupied = false; + while (true) { + space_count += 1; + var r : i64 = row_signed + (dv[0]*space_count); + var c : i64 = col_signed + (dv[1]*space_count); + if (r < 0 or c < 0) { + // invalid spot with negative indices + break; + } + if(self.index_of(@intCast(usize, r), @intCast(usize, c))) |index| { + if (self.data.items[index] == '.') { + // We see through floor spaces + continue; + } + else { + has_neighbour = true; + if (self.data.items[index] == '#') { + last_neighbour_was_occupied = true; + } + break; + } + } + else { + // The index was not valid, so we're out of bounds in some way + break; + } + } + if (has_neighbour) { + count += 1; + if (last_neighbour_was_occupied) { + occupied += 1; + } + else { + free += 1; + } + } + } + return NeighbourState { + .count = count, + .free = free, + .occupied = occupied, + }; + } + + pub fn index_of(self: *SeatMap, row: usize, col: usize) ?usize { + if (col >= self.width) { + return null; + } + if (row >= self.height) { + return null; + } + var i = (row*self.width) + col; + if (i < 0 or i >= self.data.items.len) { + return null; + } + return i; + } +}; + +test "part_one" { + var d = [_][]const u8 { + "L.LL.LL.LL", + "LLLLLLL.LL", + "L.L.L..L..", + "LLLL.LL.LL", + "L.LL.LL.LL", + "L.LLLLL.LL", + "..L.L.....", + "LLLLLLLLLL", + "L.LLLLLL.L", + "L.LLLLL.LL", + }; + + var print = true; + var stdout = std.io.getStdOut(); + + var sm = try SeatMap.init(std.testing.allocator); + defer sm.deinit(); + for (d) |l| { + try sm.add_line(l[0..]); + } + + var states = [_][]const u8 { + // 0 + "L.LL.LL.LLLLLLLLL.LLL.L.L..L..LLLL.LL.LLL.LL.LL.LLL.LLLLL.LL..L.L.....LLLLLLLLLLL.LLLLLL.LL.LLLLL.LL", + // 1 + "#.##.##.#########.###.#.#..#..####.##.###.##.##.###.#####.##..#.#.....###########.######.##.#####.##", + // 2 + "#.LL.L#.###LLLLLL.L#L.L.L..L..#LLL.LL.L##.LL.LL.LL#.LLLL#.##..L.L.....#LLLLLLLL##.LLLLLL.L#.#LLLL.##", + // 3 + "#.##.L#.###L###LL.L#L.#.#..#..#L##.##.L##.##.LL.LL#.###L#.##..#.#.....#L######L##.LL###L.L#.#L###.##", + // 4 + "#.#L.L#.###LLL#LL.L#L.L.L..#..#LLL.##.L##.LL.LL.LL#.LL#L#.##..L.L.....#L#LLLL#L##.LLLLLL.L#.#L#L#.##", + // 5 + "#.#L.L#.###LLL#LL.L#L.#.L..#..#L##.##.L##.#L.LL.LL#.#L#L#.##..L.L.....#L#L##L#L##.LLLLLL.L#.#L#L#.##" + }; + // Confirm that initial map is correct + std.testing.expect(std.mem.eql(u8, sm.data.items, states[0])); + + if (print) { + _ = try stdout.write("\nInitial map:\n"); + try sm.print(); + _ = try stdout.write("\n"); + } + + var round: u64 = 0; + var changed = try sm.process_round(); + while (changed != 0) { + round += 1; + var matches = std.mem.eql(u8, sm.data.items, states[round]); + //std.log.warn("Round {} matches expected state: {}", .{round, matches}); + //std.log.warn("len {}: {}", .{sm.data.items.len, sm.data.items}); + //std.log.warn("len {}: {}", .{states[round].len, states[round]}); + //std.log.warn("index of first diff {}", + // .{std.mem.indexOfDiff(u8, sm.data.items, states[round])}); + std.testing.expect(matches); + if (print) { + var title = try std.fmt.allocPrint(std.testing.allocator, "\nRound {}:\n", + .{round}); + _ = try stdout.write(title); + std.testing.allocator.free(title); + try sm.print(); + _ = try stdout.write("\n"); + } + changed = try sm.process_round(); + } + if (print) { + _ = try stdout.write("Final state: \n"); + try sm.print(); + _ = try stdout.write("\n"); + } + std.testing.expect(std.mem.eql(u8, sm.data.items, states[round])); + + var n_occupied = sm.count_occupied(); + std.testing.expectEqual(n_occupied, 37); +} + +test "part two" { + var d = [_][]const u8 { + "L.LL.LL.LL", + "LLLLLLL.LL", + "L.L.L..L..", + "LLLL.LL.LL", + "L.LL.LL.LL", + "L.LLLLL.LL", + "..L.L.....", + "LLLLLLLLLL", + "L.LLLLLL.L", + "L.LLLLL.LL", + }; + + var print = true; + var stdout = std.io.getStdOut(); + + var sm = try SeatMap.init(std.testing.allocator); + defer sm.deinit(); + for (d) |l| { + try sm.add_line(l[0..]); + } + + var states = [_][]const u8 { + // 0 + "L.LL.LL.LLLLLLLLL.LLL.L.L..L..LLLL.LL.LLL.LL.LL.LLL.LLLLL.LL..L.L.....LLLLLLLLLLL.LLLLLL.LL.LLLLL.LL", + // 1 + "#.##.##.#########.###.#.#..#..####.##.###.##.##.###.#####.##..#.#.....###########.######.##.#####.##", + // 2 + "#.LL.LL.L##LLLLLL.LLL.L.L..L..LLLL.LL.LLL.LL.LL.LLL.LLLLL.LL..L.L.....LLLLLLLLL##.LLLLLL.L#.LLLLL.L#", + // 3 + "#.L#.##.L##L#####.LLL.#.#..#..##L#.##.###.##.#L.###.#####.#L..#.#.....LLL####LL##.L#####.L#.L####.L#", + // 4 + "#.L#.L#.L##LLLLLL.LLL.L.L..#..##LL.LL.L#L.LL.LL.L##.LLLLL.LL..L.L.....LLLLLLLLL##.LLLLL#.L#.L#LL#.L#", + // 5 + "#.L#.L#.L##LLLLLL.LLL.L.L..#..##L#.#L.L#L.L#.#L.L##.L####.LL..#.#.....LLL###LLL##.LLLLL#.L#.L#LL#.L#", + // 6 + "#.L#.L#.L##LLLLLL.LLL.L.L..#..##L#.#L.L#L.L#.LL.L##.LLLL#.LL..#.L.....LLL###LLL##.LLLLL#.L#.L#LL#.L#", + }; + // Confirm that initial map is correct + std.testing.expect(std.mem.eql(u8, sm.data.items, states[0])); + + if (print) { + _ = try stdout.write("\nInitial map:\n"); + try sm.print(); + _ = try stdout.write("\n"); + } + + var round: u64 = 0; + var changed = try sm.process_round(); + while (changed != 0) { + round += 1; + var matches = std.mem.eql(u8, sm.data.items, states[round]); + //std.log.warn("Round {} matches expected state: {}", .{round, matches}); + //std.log.warn("len {}: {}", .{sm.data.items.len, sm.data.items}); + //std.log.warn("len {}: {}", .{states[round].len, states[round]}); + //std.log.warn("index of first diff {}", + // .{std.mem.indexOfDiff(u8, sm.data.items, states[round])}); + std.testing.expect(matches); + if (print) { + var title = try std.fmt.allocPrint(std.testing.allocator, "\nRound {}:\n", + .{round}); + _ = try stdout.write(title); + std.testing.allocator.free(title); + try sm.print(); + _ = try stdout.write("\n"); + } + changed = try sm.process_round_part2(); + } + if (print) { + _ = try stdout.write("Final state: \n"); + try sm.print(); + _ = try stdout.write("\n"); + } + std.testing.expect(std.mem.eql(u8, sm.data.items, states[round])); + + var n_occupied = sm.count_occupied(); + std.testing.expectEqual(n_occupied, 26); +} diff --git a/day12/build.zig b/day12/build.zig new file mode 100644 index 0000000..49704c7 --- /dev/null +++ b/day12/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day12", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day12/input b/day12/input new file mode 100644 index 0000000..dc64185 --- /dev/null +++ b/day12/input @@ -0,0 +1,750 @@ +W1 +F91 +W3 +F82 +N1 +E2 +N4 +R90 +F25 +N2 +F75 +E4 +R90 +F91 +R90 +F64 +L90 +E1 +L90 +S2 +L180 +S2 +E3 +N2 +E5 +L90 +N2 +R90 +F30 +L90 +N1 +F37 +S1 +E5 +F3 +E2 +F59 +W3 +L270 +S5 +W5 +S4 +F84 +N5 +R180 +E4 +F31 +L90 +E2 +F77 +L90 +N5 +F17 +N4 +N4 +W2 +F45 +S1 +F92 +E1 +F33 +L270 +F21 +L90 +E1 +F81 +N5 +F20 +E2 +R90 +N4 +W3 +L180 +S2 +F33 +E5 +F87 +R90 +N2 +F29 +E3 +S4 +L90 +E4 +R90 +S2 +F65 +L90 +F69 +W2 +N4 +F73 +R180 +S3 +R90 +N3 +R90 +W1 +L180 +F96 +N3 +W2 +L180 +S5 +F29 +E3 +S4 +W1 +F53 +E1 +L90 +E5 +F26 +E3 +R270 +E2 +S2 +W2 +F43 +W2 +F53 +F74 +R180 +N5 +W3 +S4 +F70 +R90 +W4 +F56 +L90 +S5 +R180 +E4 +S4 +F80 +S1 +F91 +R90 +S4 +F88 +L90 +S5 +R90 +E2 +S1 +F37 +N1 +R90 +F92 +W5 +F14 +N2 +E5 +S2 +F89 +L180 +N4 +E4 +L90 +F32 +E4 +R90 +F99 +N3 +L180 +F78 +S1 +R270 +W1 +F11 +S4 +F47 +N4 +L90 +F17 +R90 +E4 +S3 +F14 +S1 +R90 +N3 +F52 +W3 +S5 +L180 +F41 +R90 +F62 +W1 +R90 +E4 +F1 +W5 +F86 +W1 +N5 +F5 +S1 +E5 +F67 +W3 +F97 +E1 +L90 +S2 +E1 +R90 +F82 +E3 +N2 +F16 +L90 +W2 +F35 +R180 +N2 +E3 +N4 +W4 +F13 +S5 +E1 +S5 +L90 +E5 +F65 +E5 +L90 +S4 +E3 +W4 +N1 +R90 +N5 +F93 +R90 +S5 +R90 +L90 +F86 +E3 +F90 +E4 +N2 +E4 +R180 +W5 +R90 +E3 +F98 +F56 +L90 +F68 +L90 +N3 +F35 +S1 +W5 +F25 +L180 +F7 +R270 +F84 +R90 +S4 +E5 +S3 +L270 +F33 +W3 +R90 +W5 +N3 +E4 +R90 +W2 +F100 +E5 +S2 +L90 +F6 +E1 +L90 +S1 +F17 +N3 +E1 +S3 +F78 +R90 +W5 +N4 +L90 +F13 +W5 +R90 +F7 +F74 +R90 +E4 +F28 +L90 +S5 +R90 +F77 +S2 +E2 +N3 +F30 +E1 +R90 +W2 +S2 +F62 +E2 +L90 +E2 +F56 +L90 +F61 +S1 +F14 +W3 +F23 +L90 +E3 +S3 +L270 +S5 +F97 +E5 +S1 +F96 +W2 +F61 +L180 +F25 +L90 +W4 +F100 +W4 +F14 +W4 +S5 +R90 +F67 +E1 +R90 +F89 +W5 +S3 +W2 +N2 +F64 +L180 +S4 +R270 +F47 +E1 +S1 +E4 +N1 +R90 +N2 +E5 +F97 +N3 +E5 +S5 +R180 +E5 +F34 +L90 +W1 +W1 +N3 +R90 +F17 +N1 +F75 +S4 +W5 +N2 +W1 +N2 +L90 +W3 +N2 +F1 +N1 +W3 +R90 +F18 +E4 +N4 +F18 +N4 +F73 +W4 +F61 +W3 +R90 +N5 +L90 +N4 +F70 +E4 +F10 +L90 +F33 +N5 +L90 +W4 +L180 +E2 +F41 +E1 +S4 +E4 +L90 +F28 +N2 +W4 +S2 +F86 +R180 +S3 +W3 +S3 +W2 +F55 +W1 +F18 +W2 +F18 +L90 +S4 +W1 +L90 +F47 +L90 +S4 +F39 +N5 +L180 +S3 +W5 +F95 +W1 +R90 +E2 +N3 +L90 +S4 +F77 +S1 +W4 +S5 +E4 +R90 +W1 +R90 +W3 +W2 +N4 +F1 +W1 +N5 +F55 +E4 +N4 +W5 +L90 +F90 +E4 +R90 +E2 +R90 +S5 +F44 +N2 +E3 +R90 +F64 +W1 +L180 +L180 +F55 +L90 +F15 +S2 +E1 +R270 +F10 +R90 +W4 +F43 +E1 +F7 +N2 +W3 +F10 +N1 +L270 +N2 +L90 +E2 +R90 +F28 +W2 +N5 +F70 +R90 +E3 +E3 +F75 +W4 +L90 +S2 +R90 +F83 +L270 +E1 +F87 +R180 +N3 +L90 +F30 +L90 +E1 +N5 +F87 +N4 +R90 +F51 +W5 +N3 +R90 +S5 +F98 +W4 +N2 +E2 +L90 +E4 +S1 +E5 +F60 +N1 +L180 +E1 +F10 +R90 +W5 +F90 +W5 +F9 +S1 +W3 +F9 +E2 +S4 +L180 +F61 +W2 +N3 +F35 +R90 +E4 +N3 +W4 +L90 +E1 +L90 +S1 +F62 +S5 +W1 +N5 +L180 +F76 +W3 +L90 +W4 +L90 +N2 +E3 +N5 +E1 +N2 +F13 +S1 +F20 +W5 +L90 +S1 +F89 +S3 +L90 +W2 +L90 +F48 +W5 +N1 +R90 +F93 +L90 +E4 +L90 +N2 +F100 +W5 +S5 +W1 +S1 +E2 +S1 +W4 +R90 +S2 +F99 +W2 +F80 +L90 +F78 +N4 +L90 +F67 +S1 +L90 +F23 +W3 +N1 +W5 +F76 +R270 +F51 +L90 +W2 +N1 +E3 +S3 +L90 +F83 +L90 +F46 +S5 +L180 +N3 +E3 +F49 +E5 +N4 +W5 +L90 +E3 +R90 +S4 +F54 +E1 +F49 +N4 +L180 +E3 +L90 +R90 +F95 +W2 +N2 +F12 +R180 +E4 +R90 +N5 +L180 +S3 +W3 +S1 +F22 +W1 +F18 +L90 +F35 +R90 +F3 +S4 +L90 +F53 +W5 +F58 +L90 +S2 +F48 +S5 +R180 +F67 +L180 +W1 +S3 +L90 +F33 +F34 +R90 +F54 +W2 +L180 +S5 +W4 +R90 +F80 +W4 +S1 +W4 +F35 +E1 +F48 +N3 +L270 +F78 +N4 +S4 +F11 +S1 +W3 +L90 +W1 +F26 +R180 +E3 +F43 +S4 +R180 +W3 +N2 +F80 +W4 +F29 +W5 +W1 +R270 +N3 +L90 +F17 +W4 +F49 +S4 +S1 +F47 diff --git a/day12/src/main.zig b/day12/src/main.zig new file mode 100644 index 0000000..0d4d24f --- /dev/null +++ b/day12/src/main.zig @@ -0,0 +1,197 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + defer gpa.free(contents); + + var ship = ShipPosition{}; + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + ship.update(line[0], try std.fmt.parseInt(i64, line[1..], 10)); + std.log.debug("After '{}', ship at ({}, {}) facing {}", + .{line, ship.position[0], ship.position[1], ship.facing}); + } + std.log.info("Ship is at ({},{}) facing {}. It has travalled {} manhattan distance from start", + .{ship.position[0], ship.position[1], ship.facing, + ship.manhattan_distance_from([_]i64{0, 0})}); + + // Part 2 + ship = ShipPosition{}; + it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + ship.update_part2(line[0], try std.fmt.parseInt(i64, line[1..], 10)); + std.log.debug("After '{}', ship at ({}, {}), with waypoint ({}, {})", + .{line, ship.position[0], ship.position[1], + ship.waypoint[0], ship.waypoint[1]}); + } + std.log.info("Ship is at ({},{}) facing {} and waypoint ({}, {}). It has travalled {} manhattan distance from start", + .{ship.position[0], ship.position[1], ship.facing, + ship.waypoint[0], ship.waypoint[1], + ship.manhattan_distance_from([_]i64{0, 0})}); +} + +const ShipPosition = struct { + facing : i64 = 90, + position : [2]i64 = [_]i64{0, 0}, + waypoint: [2]i64 = [_]i64{10, 1}, + + pub fn update(self: *ShipPosition, command: u8, value: i64) void { + switch(command) { + 'N' => { + self.position[1] += value; + }, + 'S' => { + self.position[1] -= value; + }, + 'E' => { + self.position[0] += value; + }, + 'W' => { + self.position[0] -= value; + }, + 'R' => { + self.facing += value; + }, + 'L' => { + self.facing -= value; + }, + 'F' => { + std.log.debug("Facing before moving forward: {}", .{self.facing}); + while (self.facing < 0) { + self.facing += 360; + } + if (self.facing >= 360) { + self.facing = @intCast(i64, @mod(self.facing, 360)); + } + std.log.debug("Facing after normalizing, before moving forward: {}", + .{self.facing}); + var c : u8 = switch(self.facing) { + 0 => 'N', + 90 => 'E', + 180 => 'S', + 270 => 'W', + else => { + std.log.warn("Unexpected facing {}", .{self.facing}); + unreachable; + }, + }; + self.update(c, value); + }, + else => { + std.log.warn("Unknown command: '{}'", .{command}); + }, + } + } + + pub fn manhattan_distance_from(self: *ShipPosition, from: [2]i64) u64 { + return (std.math.absCast(self.position[0] - from[0])) + + (std.math.absCast(self.position[1] - from [1])); + } + + pub fn update_part2(self: *ShipPosition, command: u8, value: i64) void { + switch(command) { + 'N' => { + self.waypoint[1] += value; + }, + 'S' => { + self.waypoint[1] -= value; + }, + 'E' => { + self.waypoint[0] += value; + }, + 'W' => { + self.waypoint[0] -= value; + }, + 'R' => { + // Rotate around the ship + self.waypoint = rotate_point(self.waypoint, -value); + }, + 'L' => { + // Rotate around the ship + self.waypoint = rotate_point(self.waypoint, value); + }, + 'F' => { + // For forward value times towards the waypoint. + self.position[0] += self.waypoint[0] * value; + self.position[1] += self.waypoint[1] * value; + // Waypoint stays relative to ship + //self.waypoint[0] = self.position[0] + self.waypoint[0]; + //self.waypoint[1] = self.position[1] + self.waypoint[1]; + }, + else => { + std.log.warn("Unknown command: '{}'", .{command}); + }, + } + } + +}; + +pub fn rotate_point(point: [2]i64, degrees: i64) [2]i64 { + var radians : f64 = (@intToFloat(f64, degrees) * std.math.pi) / 180.0; + var old_x = @intToFloat(f64, point[0]); + var old_y = @intToFloat(f64, point[1]); + var x : f64 = old_x * std.math.cos(radians) - old_y * std.math.sin(radians); + var y : f64 = old_y * std.math.cos(radians) + old_x * std.math.sin(radians); + return [2]i64 { + @floatToInt(i64, std.math.round(x)), + @floatToInt(i64, std.math.round(y)), + }; +} + +test "part_one" { + var data = [_][]const u8 { + "F10", + "N3", + "F7", + "R90", + "F11", + }; + var ship = ShipPosition{}; + for (data) |d| { + ship.update(d[0], try std.fmt.parseInt(i64, d[1..], 10)); + } + std.testing.expectEqual(ship.position[0], 17); + std.testing.expectEqual(ship.position[1], -8); + std.testing.expectEqual(ship.manhattan_distance_from([_]i64{0, 0}), 25); +} + +test "part_two" { + var data = [_][]const u8 { + "F10", + "N3", + "F7", + "R90", + "F11", + }; + var ship = ShipPosition{}; + for (data) |d| { + ship.update_part2(d[0], try std.fmt.parseInt(i64, d[1..], 10)); + std.log.warn("After '{}', ship at ({}, {}), with waypoint ({}, {})", + .{d, ship.position[0], ship.position[1], + ship.waypoint[0], ship.waypoint[1]}); + } + std.testing.expectEqual(ship.position[0], 214); + std.testing.expectEqual(ship.position[1], -72); + std.testing.expectEqual(ship.manhattan_distance_from([_]i64{0, 0}), 286); +} + +// test "rotate" { +// var point = [_]i64 {4,-3}; +// var p = rotate_point(point, 90); +// std.testing.expectEqual(p[0], 3); +// std.testing.expectEqual(p[1], 4); + +// p = rotate_point(point, 180); +// std.testing.expectEqual(p[0], -4); +// std.testing.expectEqual(p[1], 3); + +// p = rotate_point(point, 270); +// std.testing.expectEqual(p[0], -4); +// std.testing.expectEqual(p[1], 3); + +// } diff --git a/day13/build.zig b/day13/build.zig new file mode 100644 index 0000000..eda46ed --- /dev/null +++ b/day13/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day13", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day13/input b/day13/input new file mode 100644 index 0000000..73a2112 --- /dev/null +++ b/day13/input @@ -0,0 +1,2 @@ +1005595 +41,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,37,x,x,x,x,x,557,x,29,x,x,x,x,x,x,x,x,x,x,13,x,x,x,17,x,x,x,x,x,23,x,x,x,x,x,x,x,419,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,19 diff --git a/day13/src/main.zig b/day13/src/main.zig new file mode 100644 index 0000000..b1bdc49 --- /dev/null +++ b/day13/src/main.zig @@ -0,0 +1,467 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + defer gpa.free(contents); + + var buses = std.ArrayList(Bus).init(gpa); + defer buses.deinit(); + + var it = std.mem.tokenize(contents, "\n"); + var estimated_arrival_at_bus_station: u64 = 0; + if (it.next()) |l| { + estimated_arrival_at_bus_station = try std.fmt.parseUnsigned(u64, l, 10); + } + if (it.next()) |l| { + var bus_it = std.mem.tokenize(l, ","); + var offset: u64 = 0; + while (bus_it.next()) |b| : (offset += 1) { + if (b[0] == 'x') { + continue; + } + var a = std.fmt.parseUnsigned(u64, b, 10) catch continue; + var bus = Bus{.id = a, .offset = offset}; + std.log.debug("Bus: {}", .{bus}); + try buses.append(bus); + } + } + + var earliest_bus = find_earliest_bus_after(buses.items, estimated_arrival_at_bus_station); + var wait_time = earliest_bus.earliest_departure_after(estimated_arrival_at_bus_station) - estimated_arrival_at_bus_station; + std.log.info("Earliest bus '{}' will depart at {}, a wait of {}.", + .{earliest_bus.id, earliest_bus.earliest_departure_after(estimated_arrival_at_bus_station), wait_time}); + std.log.info("Part one: {}", .{earliest_bus.id * wait_time}); + + // Part 2 + // the challenge warns us it will "surely be" above 100000000000000 + // 18446744073709551615 <-- u64 max + //var est_start : u64 = buses.items[0].earliest_departure_after(estimated_arrival_at_bus_station); + //est_start = 100000733946084; + est_start = 101775718927832; + // From Est start 101775718927832 + // To 140354342739376 took 180.75m of CPU time, + // 598411311431841 <-- sol'n after using sieve + lcm + // It would have probably taken another (180.75)*3.26 = 9.82 hours to get there... + // lcm + sieve: ~ 0.003s, and starts working from 0. + var prize_start : u64 = 0; + var act = std.os.Sigaction { + .sigaction = handle_sigusr, + //.sigaction = std.os.linux.SIG_IGN, + .mask = std.os.empty_sigset, + .flags = 0, + }; + std.os.sigaction(10, &act, null); + // Brute force approach + // while (prize_start == 0) : (est_start += buses.items[0].id) { + // var matches = true; + // for (buses.items[1..]) |b, k| { + // if (@mod(est_start + b.offset, b.id) % b.id != 0) { + // matches = false; + // //std.log.debug("Bus {} failed iteration starting at {}", .{b.id, est_start}); + // break; + // } + // } + // if (matches) { + // prize_start = est_start; + // } + // } + prize_start = try find_bus_offset_departure(buses.items[0..], gpa); + std.log.info("Earliest depature match prize condition: {}", .{prize_start}); +} + +var t_last_sigusr : i128 = 0; +var est_start : u64 = 0; +var last_start_value : u64 = 0; +fn handle_sigusr(sig: i32, info: *std.os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void { + var values_per_second_avg : f64 = 0.0; + if (last_start_value == 0) { + std.log.warn("Last {}", .{est_start}); + } + else { + var calcs_done : f64 = @intToFloat(f64, (est_start - last_start_value)/41); + values_per_second_avg = calcs_done + / @intToFloat(f64, std.time.nanoTimestamp() - t_last_sigusr); + std.log.warn("Last {}, {}/s avg - {} calcs done", + .{est_start, values_per_second_avg * std.time.ns_per_s, calcs_done}); + } + last_start_value = est_start; + t_last_sigusr = std.time.nanoTimestamp(); +} + +fn find_earliest_bus_after(buses: []Bus, time: u64) Bus { + var earliest_bus_index : u64 = 0; + var earliest_departure_time : u64 = std.math.maxInt(u64); + for (buses) |bus, k| { + var departs_at : u64 = Bus.earliest_departure(bus.id, time); + if (departs_at < earliest_departure_time) { + earliest_bus_index = k; + earliest_departure_time = departs_at; + } + } + return buses[earliest_bus_index]; +} + +const Bus = struct { + id: u64, + offset: u64 = 0, + + pub fn earliest_departure_after(self: *Bus, time: u64) u64 { + return Bus.earliest_departure(self.id, time); + } + + pub fn earliest_departure(id: u64, time: u64) u64 { + var d : u64 = ((time / id)+1) * id; + std.debug.assert(d >= time); + return d; + } +}; + + +fn find_bus_offset_departure(buses: []Bus, a: *std.mem.Allocator) !u64 { + var list_pos : usize = 0; + var t : u64 = 0; + var increment : u64 = buses[0].id; + var bus_ids = try a.alloc(u64, buses.len); + defer a.free(bus_ids); + for (buses) |b, k| { + bus_ids[k] = b.id; + } + while (list_pos < (buses.len-1)) : (t += increment) { + // Check if (t+buses[list_pos+1].offset)%buses[list_pos+1].id == 0 + if (@mod(t+buses[list_pos+1].offset, buses[list_pos+1].id) == 0) { + // Our bus arrives here, great. + increment = try lcm_by_factorization(std.testing.allocator, bus_ids[0..list_pos+2]); + std.log.debug("Bus {} (offset: {}) in pos {} at {}. New increment {}", + .{buses[list_pos+1].id, buses[list_pos+1].offset, list_pos+1, t, increment}); + list_pos += 1; + } + } + // If we left the loop, we incremented, so decrement + t -= increment; + return t; +} + +test "departure" { + var a : u64 = 939; + std.testing.expectEqual(Bus.earliest_departure(59, 939), 944); +} + +test "prize_start" { + // 7,13,x,x,59,x,31,19 + var buses = [_]Bus { + Bus{.id = 7}, + Bus{.id = 13, .offset = 1}, + Bus{.id = 59, .offset = 4}, + Bus{.id = 31, .offset = 6}, + Bus{.id = 19, .offset = 7}, + }; + est_start = 0; + var prize_start : u64 = 0; + while (prize_start == 0) : (est_start += buses[0].id) { + var matches = true; + for (buses[1..]) |b, k| { + if ((est_start + b.offset) % b.id != 0) { + matches = false; + break; + } + } + if (matches) { + prize_start = est_start; + } + } + std.log.warn("Earliest depature match prize condition: {}", .{prize_start}); + std.testing.expectEqual(prize_start, 1068781); + + // No LCM version, because the example's prize_start if based on the + // arbitrary offset. +} + +test "prize_ex1" { + //17,x,13,19 + var buses = [_]Bus { + Bus{.id = 17}, + Bus{.id = 13, .offset = 2}, + Bus{.id = 19, .offset = 3}, + }; + est_start = 0; + var prize_start : u64 = 0; + while (prize_start == 0) : (est_start += buses[0].id) { + var matches = true; + for (buses[1..]) |b, k| { + if ((est_start + b.offset) % b.id != 0) { + matches = false; + break; + } + } + if (matches) { + prize_start = est_start; + } + } + std.log.warn("Earliest depature match prize condition: {}", .{prize_start}); + std.testing.expectEqual(prize_start, 3417); + // LCM version + prize_start = try find_bus_offset_departure(buses[0..], std.testing.allocator); + std.testing.expectEqual(prize_start, 3417); +} + +test "prize_ex2" { + // 67,7,59,61 + var buses = [_]Bus { + Bus{.id = 67}, + Bus{.id = 7, .offset = 1}, + Bus{.id = 59, .offset = 2}, + Bus{.id = 61, .offset = 3}, + }; + est_start = 0; + var prize_start : u64 = 0; + while (prize_start == 0) : (est_start += buses[0].id) { + var matches = true; + for (buses[1..]) |b, k| { + if ((est_start + b.offset) % b.id != 0) { + matches = false; + break; + } + } + if (matches) { + prize_start = est_start; + } + } + std.log.warn("Earliest depature match prize condition: {}", .{prize_start}); + std.testing.expectEqual(prize_start, 754018); + + // LCM version + prize_start = try find_bus_offset_departure(buses[0..], std.testing.allocator); + std.testing.expectEqual(prize_start, 754018); +} + +test "prize_ex3" { + // 67,x,7,59,61 + var buses = [_]Bus { + Bus{.id = 67}, + Bus{.id = 7, .offset = 2}, + Bus{.id = 59, .offset = 3}, + Bus{.id = 61, .offset = 4}, + }; + est_start = 0; + var prize_start : u64 = 0; + while (prize_start == 0) : (est_start += buses[0].id) { + var matches = true; + for (buses[1..]) |b, k| { + if ((est_start + b.offset) % b.id != 0) { + matches = false; + break; + } + } + if (matches) { + prize_start = est_start; + } + } + std.log.warn("Earliest depature match prize condition: {}", .{prize_start}); + std.testing.expectEqual(prize_start, 779210); + // LCM version + prize_start = try find_bus_offset_departure(buses[0..], std.testing.allocator); + std.testing.expectEqual(prize_start, 779210); +} + +test "prize_ex4" { + // 67,7,x, 59,61 + var buses = [_]Bus { + Bus{.id = 67}, + Bus{.id = 7, .offset = 1}, + Bus{.id = 59, .offset = 3}, + Bus{.id = 61, .offset = 4}, + }; + est_start = 0; + var prize_start : u64 = 0; + while (prize_start == 0) : (est_start += buses[0].id) { + var matches = true; + for (buses[1..]) |b, k| { + if ((est_start + b.offset) % b.id != 0) { + matches = false; + break; + } + } + if (matches) { + prize_start = est_start; + } + } + std.log.warn("Earliest depature match prize condition: {}", .{prize_start}); + std.testing.expectEqual(prize_start, 1261476); + // LCM version + prize_start = try find_bus_offset_departure(buses[0..], std.testing.allocator); + std.testing.expectEqual(prize_start, 1261476); +} + +test "prize_ex5" { + // 1789,37,47,1889 + var buses = [_]Bus { + Bus{.id = 1789}, + Bus{.id = 37, .offset = 1}, + Bus{.id = 47, .offset = 2}, + Bus{.id = 1889, .offset = 3}, + }; + est_start = 0; + var prize_start : u64 = 0; + while (prize_start == 0) : (est_start += buses[0].id) { + var matches = true; + for (buses[1..]) |b, k| { + if ((est_start + b.offset) % b.id != 0) { + matches = false; + break; + } + } + if (matches) { + prize_start = est_start; + } + } + std.log.warn("Earliest depature match prize condition: {}", .{prize_start}); + std.testing.expectEqual(prize_start, 1202161486); + // LCM version + prize_start = try find_bus_offset_departure(buses[0..], std.testing.allocator); + std.testing.expectEqual(prize_start, 1202161486); +} + +fn lcm_by_factorization(allocator: *std.mem.Allocator, values: []u64) !u64 { + var highest_powers = std.hash_map.AutoHashMap(u64, u64).init(allocator); + defer highest_powers.deinit(); + + // For each item in the set, get the prime factorization of the item's value + for (values) |v| { + var list = try prime_factors(v, allocator); + defer list.deinit(); + for (list.items) |factor| { + std.log.warn("{}^{} is a prime factor of {}", .{factor.base, factor.power, v}); + if (highest_powers.get(factor.base)) |other_power| { + if (factor.power > other_power) { + highest_powers.putAssumeCapacity(factor.base, factor.power); + } + } + else { + try highest_powers.put(factor.base, factor.power); + } + } + } + + var lcm : u64 = 1; + var it = highest_powers.iterator(); + while (it.next()) |entry| { + std.log.warn("{}^{} is part of the LCM", .{entry.key, entry.value}); + lcm *= std.math.pow(u64, entry.key, entry.value); + } + + return lcm; +} + +const Factor = struct { + base: u64, + power: u64 = 1, +}; + +fn prime_factors(value: u64, allocator: *std.mem.Allocator) !std.ArrayList(Factor) { + var factors = std.ArrayList(Factor).init(allocator); + // Using the "test and fail method" + var current : u64 = value; + var divisor : u64 = 2; + if (is_prime(value)) { + try factors.append(Factor{.base = value}); + return factors; + } + while(current != 1) { + //std.log.warn("{} rem {} = {}", .{current, divisor, @rem(current, divisor)}); + if (@rem(current, divisor) == 0) { + current = current / divisor; + // Add divisor to the list of factors if it's not there, otherwise + // increment the power + var index: ?usize = null; + for (factors.items) |v, k| { + if (v.base == divisor) { + index = k; + break; + } + } + if (index) |i| { + factors.items[i].power += 1; + } + else { + try factors.append(Factor{.base = divisor}); + } + } + else { + // Out of this factor, increment the divisor until the next prime number + // divisor is reached. + divisor += 1; + while(!is_prime(divisor)) : (divisor+=1) {} + } + } + + return factors; +} + +fn is_prime(value: u64) bool { + if (value == 1) { + return false; + } + var i: u64 = 2; + while (i < (value-1)) : (i += 1) { + if (@rem(value, i) == 0) { + return false; + } + } + return true; +} + +test "is_prime_49" { + std.testing.expect(is_prime(49) == false); +} + +test "is_prime_1009" { + std.testing.expect(is_prime(1009)); +} + +test "prime_factors_100" { + var a = std.testing.allocator; + var factors = try prime_factors(100, a); + defer factors.deinit(); + // for (factors.items) |v| { + // std.log.warn("{}^{} ", .{v.base, v.power}); + // } + std.testing.expectEqual(factors.items.len, 2); + std.testing.expectEqual(factors.items[0].base, 2); + std.testing.expectEqual(factors.items[0].power, 2); + std.testing.expectEqual(factors.items[1].base, 5); + std.testing.expectEqual(factors.items[0].power, 2); +} + +test "prime_factors_1009" { + var a = std.testing.allocator; + var factors = try prime_factors(1009, a); + defer factors.deinit(); + // for (factors.items) |v| { + // std.log.warn("{}^{} ", .{v.base, v.power}); + // } + std.testing.expectEqual(factors.items.len, 1); + std.testing.expectEqual(factors.items[0].base, 1009); + std.testing.expectEqual(factors.items[0].power, 1); +} + +// This is a pretty long test... +test "prime_factors_1289732" { + var a = std.testing.allocator; + var factors = try prime_factors(128973, a); + defer factors.deinit(); + // for (factors.items) |v| { + // std.log.warn("{}^{} ", .{v.base, v.power}); + // } + std.testing.expectEqual(factors.items.len, 3); + std.testing.expectEqual(factors.items[0].base, 3); + std.testing.expectEqual(factors.items[0].power, 1); + std.testing.expectEqual(factors.items[1].base, 13); + std.testing.expectEqual(factors.items[1].power, 1); + std.testing.expectEqual(factors.items[2].base, 3307); + std.testing.expectEqual(factors.items[2].power, 1); +} diff --git a/day14/build.zig b/day14/build.zig new file mode 100644 index 0000000..6195db4 --- /dev/null +++ b/day14/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day14", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day14/input b/day14/input new file mode 100644 index 0000000..98121d1 --- /dev/null +++ b/day14/input @@ -0,0 +1,584 @@ +mask = 1X11X010X000X0X101X00100011X10100111 +mem[40278] = 36774405 +mem[51306] = 55175378 +mem[31036] = 805355 +mem[8433] = 48148 +mem[58481] = 45466 +mask = 1000101X11001XXX00X01110X1X000XX0100 +mem[42362] = 2765432 +mem[20493] = 213778 +mem[52954] = 756325 +mask = 10010000X00X1010000101X0010X001X1X10 +mem[34108] = 155448 +mem[19047] = 166539692 +mask = 1X0000111X0X10100X10X1110010X0100000 +mem[44380] = 108787272 +mem[50688] = 178803 +mem[13224] = 18328 +mem[47270] = 41220136 +mem[1679] = 5379693 +mem[25086] = 5316 +mask = 100010X011001X1000X1000XXX0000X010X0 +mem[8433] = 12191 +mem[45074] = 466358 +mem[57607] = 88673989 +mem[1764] = 3258736 +mask = X0011010110010010000X00100100X1001X0 +mem[42636] = 8106931 +mem[26732] = 819582135 +mem[61324] = 115576 +mem[46608] = 259438 +mem[62850] = 325 +mask = 11XX001111001X1001110X1XXX1110001X0X +mem[52922] = 2111 +mem[39872] = 2919426 +mem[49237] = 13351029 +mem[25369] = 403711 +mem[25714] = 525 +mem[11361] = 930295699 +mask = 100010001100X110X0111000X000X00X0000 +mem[55023] = 398985 +mem[1543] = 794 +mem[47160] = 65745 +mask = 1000001011X010XX00001001010X11101X01 +mem[3993] = 6186451 +mem[15936] = 678 +mem[12520] = 889 +mask = 110010XX10X0101X01X011X1010X00001100 +mem[21281] = 1112 +mem[1813] = 834 +mem[23778] = 88 +mem[877] = 4305190 +mem[41759] = 688804 +mem[31991] = 4165476 +mask = 1000X0101X001010000X10X00X00X01X00X1 +mem[62604] = 118285948 +mem[25086] = 804036 +mem[52954] = 414491 +mem[61838] = 14920 +mem[12372] = 14382 +mask = XXX1X00010001000X00X101X001000X01111 +mem[38767] = 23779 +mem[15107] = 3739 +mem[19591] = 35246 +mem[64406] = 27640 +mem[47997] = 1470326 +mask = 1011101011X0X1X100X0X11110010100X011 +mem[57638] = 42095143 +mem[18633] = 7407282 +mem[23584] = 1861 +mem[9800] = 35320 +mem[25647] = 17074 +mask = X0XX10X0100X1010X000X00011X100001101 +mem[19475] = 11720838 +mem[22303] = 3396 +mem[31371] = 963 +mem[27119] = 913 +mem[48910] = 28628571 +mem[48457] = 3430746 +mask = 1000101X1XX011010000010001000011XX00 +mem[42746] = 439123 +mem[26673] = 186688 +mem[9335] = 104841 +mem[47814] = 814 +mem[31051] = 23 +mem[26161] = 192849624 +mask = 110000X1X100101X011X001X0011XX011001 +mem[10584] = 8361 +mem[21594] = 83379 +mem[47043] = 458757662 +mem[1767] = 3878 +mem[37986] = 5338251 +mem[59740] = 779934 +mem[22725] = 495512 +mask = 10110X10100010X1011010X00010X11101X1 +mem[32885] = 15961 +mem[49329] = 11659 +mem[49589] = 883656 +mem[58578] = 3299 +mem[13410] = 16573 +mem[57567] = 56589 +mem[17446] = 2435 +mask = 100100001XX01110X00010000X100101X0X0 +mem[46571] = 57904 +mem[64234] = 1904852 +mem[17836] = 917 +mem[3697] = 79951109 +mem[17934] = 311 +mem[62943] = 105198 +mem[43632] = 127650 +mask = 110X001X00001X100X001X011100X01X0X01 +mem[32984] = 5679479 +mem[2985] = 52007072 +mask = 1000X01011001100XX0000X1110X00010101 +mem[52709] = 46005248 +mem[64106] = 148 +mem[10607] = 177262862 +mem[1672] = 768 +mem[55771] = 114128471 +mem[102] = 407505 +mask = X0X01010X1X011000X0000000X1001101X10 +mem[24357] = 37895788 +mem[4818] = 12679 +mem[1895] = 677 +mem[19538] = 1012377512 +mem[51317] = 290 +mem[26273] = 3433 +mask = 100X0X10X101100X1X10X111111001001X00 +mem[30547] = 1084 +mem[55023] = 38977 +mem[62922] = 235723 +mem[26793] = 2101257 +mem[3343] = 846 +mem[23767] = 749476 +mask = 10001XXX11X01101X0101X11101X1110X010 +mem[61302] = 2841122 +mem[54867] = 8646 +mem[50226] = 130817 +mem[48234] = 29376 +mem[39560] = 605311 +mask = 110010101X001X1X000000000X0001110X10 +mem[44651] = 1982752 +mem[46095] = 7221 +mem[22548] = 1154372 +mask = 11X100X0XX101010X00011101110X1010X01 +mem[28851] = 10138786 +mem[40188] = 9003080 +mem[46594] = 260547019 +mem[13047] = 644 +mem[61575] = 318501037 +mem[17933] = 130721 +mask = 10X000111X01X010XX1X0XX11001010001X0 +mem[17836] = 11610 +mem[60798] = 17334088 +mem[18040] = 8111502 +mem[5507] = 3549486 +mask = 100010101X001XXX00X0X10001X10111X01X +mem[1101] = 1830700 +mem[12750] = 44919 +mem[61081] = 1145728 +mem[221] = 98190 +mem[5230] = 1674762 +mask = 10110101X0X0100001X01101X1111X011011 +mem[63476] = 774 +mem[38765] = 6583 +mem[53101] = 425799 +mem[2689] = 76519 +mask = 1X0X0X001XX010100000X1X0X1000X010100 +mem[63306] = 25107559 +mem[29367] = 7911 +mem[33854] = 333886 +mem[34129] = 1601023 +mem[19106] = 105039 +mem[20340] = 33500 +mask = 1XX11X10100XX00X0X001010011010010111 +mem[17552] = 318 +mem[52954] = 755503843 +mem[45796] = 251387 +mask = 110010X01000101001000101X100001X010X +mem[19611] = 4546530 +mem[94] = 16405 +mem[37449] = 16299407 +mem[63044] = 1717 +mem[60882] = 53035 +mask = 1X111010100010X10X00X110XX0010010XX1 +mem[46825] = 38742 +mem[1559] = 2601 +mem[17127] = 10125964 +mem[45796] = 17645381 +mem[57067] = 650 +mem[12750] = 7052753 +mem[51876] = 223481 +mask = X00X1010110010010X000X000110X0X0X00X +mem[20021] = 98402475 +mem[62492] = 59443811 +mask = 100X101X100X1010000100010X000010X011 +mem[11361] = 790603 +mem[32392] = 1461971 +mem[16860] = 55486 +mem[48278] = 118088 +mem[6887] = 436990 +mem[44042] = 244740 +mask = 1000X01XX100X10000XX1X0011001XX01110 +mem[20112] = 2750699 +mem[12269] = 52907343 +mem[42636] = 6065 +mem[17001] = 169286 +mask = 10X1101X1X001X010X00011X0X0111001X11 +mem[37947] = 96 +mem[63306] = 7396 +mem[5465] = 1081 +mem[14662] = 1011 +mem[65279] = 131 +mask = 110100111100XX1X0111011110101000000X +mem[37780] = 7990 +mem[31512] = 40679485 +mem[14491] = 737737 +mem[30998] = 124949091 +mask = X1011X001000101XX0001X0X00111101001X +mem[33157] = 12243 +mem[56747] = 419147 +mem[11586] = 6256 +mem[64708] = 76550 +mem[37957] = 243778 +mem[5091] = 2456 +mask = 11X110X0X0001011X0000X0000100101X0X1 +mem[25324] = 2093940 +mem[36379] = 2777325 +mem[54213] = 228702576 +mem[32976] = 5846431 +mem[29430] = 119936 +mask = 1101010000101000X0001111100XXX111X11 +mem[31402] = 7431602 +mem[2073] = 7956 +mem[36885] = 3966 +mem[32392] = 37896 +mem[6832] = 173996362 +mem[53853] = 16478619 +mem[65160] = 667963 +mask = 100XX10X100X101X0X00000011X00X110X00 +mem[62304] = 3584301 +mem[57317] = 963348 +mem[16414] = 7872061 +mem[34763] = 1271472 +mask = 10XX001011000100000010X0100X01100111 +mem[48910] = 527784663 +mem[6555] = 360 +mem[52875] = 2675 +mem[18803] = 524 +mem[42703] = 3789970 +mask = 1X0100101X00X00X011100X1X11100X0101X +mem[45317] = 6806741 +mem[48723] = 23187771 +mem[34283] = 291852 +mem[29981] = 115905 +mem[63917] = 245041 +mask = 10010X0011001X10000000001X1001X10XX0 +mem[24836] = 124320580 +mem[13017] = 387784 +mem[49496] = 6149582 +mem[40990] = 3612867 +mem[42530] = 414515530 +mask = 11010XX01100X001XX1100X00001XX001011 +mem[49876] = 340001 +mem[12520] = 447064754 +mem[31346] = 2199326 +mem[38744] = 3174513 +mask = 100X101XX100100100101X000X00011111X0 +mem[58504] = 161861 +mem[51785] = 352 +mem[5035] = 14642386 +mask = 10XX0011100X101010110001110X11001X0X +mem[55328] = 912776 +mem[54729] = 404668417 +mem[1081] = 1230593 +mem[43126] = 275450 +mem[9568] = 6977 +mem[38414] = 258888 +mem[17523] = 628 +mask = 11011X10110010001110110X0XX1XX001101 +mem[14522] = 3706 +mem[23442] = 84315 +mem[60757] = 7650 +mem[64106] = 4820 +mem[12365] = 24537836 +mem[46911] = 2142190 +mem[60482] = 14617749 +mask = 11X1001111001X10X11100X000X010100110 +mem[30003] = 4640103 +mem[46235] = 8912631 +mem[28941] = 239 +mem[3232] = 2552211 +mem[14072] = 24479 +mem[45848] = 97107 +mem[27490] = 7267061 +mask = X00XXX1111X01101X0101110001XXX101110 +mem[50700] = 61091 +mem[2006] = 46171 +mem[54190] = 13801104 +mem[437] = 700 +mem[25806] = 370455 +mask = 1X00X0X0X00010100X00X00X010XX1100101 +mem[23418] = 3953103 +mem[4151] = 16351752 +mem[33858] = 2781804 +mem[40347] = 48747047 +mem[24323] = 185098 +mem[13410] = 3244984 +mem[22024] = 2046007 +mask = 101110XXX1001X01X100X1XX000111111111 +mem[42442] = 6862901 +mem[37947] = 133 +mem[52715] = 90558 +mask = 1X0XX0X0100010X0000X010X010X0001010X +mem[41622] = 3864588 +mem[37947] = 2574041 +mem[36379] = 282 +mem[7539] = 1884 +mem[43885] = 252462770 +mask = 1X0000XX110XX0X0X01101X0100X11101010 +mem[31739] = 122014445 +mem[12525] = 35483 +mem[49565] = 120526 +mask = 10000X00111X1010X0X00X0001X001X111X0 +mem[50] = 184186855 +mem[26970] = 28009237 +mem[43747] = 57180 +mask = XX01X010110X1XX101X11011X00101000011 +mem[34649] = 23812 +mem[19379] = 739289 +mem[9427] = 290837028 +mask = 1000001101X0X1000011111XX000101X11XX +mem[53212] = 976414185 +mem[54319] = 309721 +mem[61044] = 26059565 +mem[58543] = 112 +mem[47508] = 485916879 +mem[58912] = 603 +mask = 11X100000000100X000011101X001X0X0011 +mem[12536] = 1079539 +mem[60933] = 890 +mem[38277] = 24422421 +mem[31503] = 275497096 +mask = 10111010111011110X001111X0X01XX0X011 +mem[36315] = 732755 +mem[12521] = 5283380 +mem[14593] = 11354059 +mask = 110X10001000100X00001100X10000001XX0 +mem[178] = 10049489 +mem[58352] = 1284 +mem[55836] = 13364 +mem[8955] = 148648 +mask = 1001001X110010X01111001X0001010X1101 +mem[51286] = 424 +mem[24896] = 685 +mem[35764] = 984973816 +mem[1767] = 21227 +mem[58224] = 509700911 +mem[54139] = 681 +mask = 10X0101001001100X010X11001110X1X1101 +mem[4197] = 3959433 +mem[28314] = 4080074 +mem[64406] = 2275763 +mask = 10111011110011010XX0X111X00X1111111X +mem[53633] = 24715 +mem[12901] = 288197152 +mem[61838] = 365048 +mem[9985] = 113625770 +mask = 1000101011X0110X00000XX001XX0X1XX011 +mem[18728] = 2722863 +mem[62115] = 373062209 +mem[24406] = 14575043 +mem[1135] = 1658799 +mem[36109] = 27585 +mem[43154] = 932674865 +mask = 1X00001X1100101000XX01110001X01010X0 +mem[38443] = 2595746 +mem[45834] = 8200415 +mem[32618] = 2473 +mem[45317] = 204863 +mem[36385] = 1258950 +mem[1559] = 178687 +mem[7129] = 274257 +mask = 1X01X010110X1000111X11X00X1101011X01 +mem[64351] = 89231 +mem[23767] = 2060338 +mem[8182] = 3870 +mem[55067] = 3498 +mem[27490] = 113212315 +mask = 10000010110010100001XX01000X1XX00000 +mem[22484] = 465878 +mem[199] = 492230203 +mem[40351] = 41069 +mem[40347] = 28883121 +mem[54190] = 132583179 +mem[45157] = 1230 +mem[3262] = 763080 +mask = 1001010110011011X0X0100011X00X00X011 +mem[9068] = 1859901 +mem[65291] = 1860 +mem[4025] = 21940594 +mask = 11010X00X0X01X000000111010X0X1111X01 +mem[33551] = 154606 +mem[11586] = 6143673 +mem[55294] = 602657 +mem[25418] = 1846 +mem[31307] = 32063880 +mem[20048] = 1695818 +mask = 1X111X10110010110100110X110110X00000 +mem[24896] = 9413794 +mem[37579] = 13947393 +mem[62604] = 5335 +mem[9937] = 13537 +mem[14199] = 601827 +mask = 111110101X00X0110X000110X000101000X0 +mem[48234] = 1067197062 +mem[43126] = 1849938 +mem[26161] = 32826701 +mem[42432] = 2056 +mask = 10001X10110011000X100001X1100X000000 +mem[35283] = 15811124 +mem[6943] = 592604 +mem[25032] = 189694567 +mem[36455] = 163580 +mem[23535] = 61178 +mem[28952] = 363311 +mask = 1XX0000000001X10000X100001001X10X1X1 +mem[14987] = 1027 +mem[59069] = 14400510 +mem[27100] = 13017 +mem[70] = 22529 +mem[9653] = 120954062 +mask = 1X001X1010001010X001X0101000X1100001 +mem[36385] = 7634 +mem[51785] = 373478 +mem[62871] = 1219093 +mem[48687] = 720 +mem[46211] = 184017955 +mem[44651] = 4180012 +mask = 1X111X1X1100110100X0X11X011100010101 +mem[30714] = 86493051 +mem[9781] = 6458038 +mem[44042] = 196093756 +mem[54852] = 49986 +mask = 1X0X001XX10010X0XX11001100X1000100X1 +mem[59055] = 8554849 +mem[30511] = 238 +mem[59740] = 291 +mem[46825] = 4021 +mem[57257] = 47883555 +mask = 1001XX0X100X10000000X101XX0101X1X011 +mem[57317] = 3753201 +mem[36109] = 89435982 +mem[2071] = 92612 +mem[51306] = 3807708 +mem[60626] = 16185176 +mem[6288] = 52787155 +mem[51876] = 5014 +mask = 10X10X0X10X0100X0X00010X100111010000 +mem[47779] = 2632 +mem[44258] = 3287861 +mem[55067] = 554823 +mem[5507] = 16374932 +mask = X00000X01X0X101001XX00011010X010X110 +mem[15082] = 734057 +mem[20325] = 9406 +mem[43154] = 681 +mem[14046] = 2718549 +mem[36608] = 18836 +mask = 10001XX1110XX10X00X01100001011001010 +mem[64106] = 948524 +mem[63156] = 717606237 +mem[21756] = 8193201 +mem[61081] = 12060571 +mem[26182] = 1980 +mask = 100XX0X011001X0X00100101010100X100X0 +mem[40347] = 7113 +mem[20846] = 1812874 +mem[52954] = 31235865 +mem[15176] = 73255675 +mem[33551] = 45182604 +mask = 1000101X1000100000001001X10001010X1X +mem[53536] = 78486 +mem[14207] = 25081 +mem[6943] = 406911928 +mem[20627] = 33813239 +mem[52083] = 5810 +mem[51593] = 2963 +mask = 100XX01010X0100100XX1X0X011001111110 +mem[50540] = 521342322 +mem[25666] = 517512832 +mem[19475] = 60787116 +mask = 100X1010XX0011X000100010X0X1X0111X11 +mem[44296] = 11404 +mem[19921] = 12860 +mask = 10011000XX0X100000X1X10X001X00X10X10 +mem[15030] = 28046260 +mem[36124] = 53286373 +mem[18115] = 57486 +mem[14821] = 6413 +mem[46807] = 4097123 +mem[5230] = 758650 +mem[47154] = 2777 +mask = 1001X0101X0010000X11011X01001XX11101 +mem[61830] = 63370 +mem[31503] = 16024 +mem[12525] = 246729437 +mem[33593] = 115066 +mem[46594] = 59939695 +mem[178] = 6489337 +mask = 110XX000100010000000100110110XX0XX01 +mem[61044] = 1681 +mem[48145] = 78509 +mem[14662] = 317884442 +mask = 10010011110XX01000111011011X1011X111 +mem[63129] = 26 +mem[3729] = 72549 +mem[60816] = 33039 +mem[5097] = 620696594 +mem[24325] = 1480 +mem[52500] = 507 +mem[9653] = 77992342 +mask = 10X11010XX00X00100X0011X100X110X0011 +mem[50406] = 75245910 +mem[65160] = 121691 +mem[10605] = 5972898 +mem[31113] = 122549 +mask = 10X0111111101101001X1XXX1X0011101010 +mem[32648] = 13078 +mem[16040] = 42554293 +mem[49180] = 14823 +mem[12178] = 18873 +mem[45060] = 58303 +mem[49248] = 59412 +mask = 1000X010110X101001100X0010100100011X +mem[14950] = 106014 +mem[41759] = 6142194 +mem[53704] = 2925 +mask = 1000001011001010000X10010000X110X10X +mem[38572] = 30247028 +mem[23767] = 23066 +mem[32618] = 542388 +mem[10770] = 411 +mem[16831] = 40856 +mem[13505] = 2142 +mem[28786] = 140994490 +mask = 1100X0X000001XX00100X0010110X0X01X01 +mem[17768] = 45460151 +mem[4197] = 705 +mem[2953] = 12201 +mask = 1000000011XX10X00X0010X1011X111X0111 +mem[18985] = 29719899 +mem[45172] = 258207909 +mem[49882] = 85394924 +mem[21653] = 603 +mem[31300] = 37290319 +mem[5035] = 5768 +mem[6427] = 15769266 +mask = 10010011110010X0111101X000000101X0X1 +mem[47082] = 157766 +mem[13410] = 3842391 +mem[58172] = 2576 +mask = 10X000001000101000011101X0X000XX1001 +mem[3121] = 198929928 +mem[59740] = 16383 +mem[12269] = 37852 +mem[18190] = 1240 +mask = 10000XX001000100XX0X100X1010110110X0 +mem[9713] = 1435 +mem[50404] = 1789 +mem[28429] = 3239 +mem[178] = 2804 +mask = 1000010010X11011X0X01X0111010011X0X0 +mem[44077] = 202823 +mem[30483] = 3929 +mem[25920] = 10040 +mem[221] = 135771 +mask = 10X0X01111001100000000000100X0001X1X +mem[9427] = 152879 +mem[38057] = 11090 +mem[58564] = 32957206 +mask = 110X0010110X1X100010101X00100X001010 +mem[30968] = 2095418 +mem[3121] = 139148 +mem[53666] = 26824 diff --git a/day14/src/main.zig b/day14/src/main.zig new file mode 100644 index 0000000..5a24b72 --- /dev/null +++ b/day14/src/main.zig @@ -0,0 +1,296 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var map = std.hash_map.AutoHashMap(u64, u64).init(gpa); + defer map.deinit(); + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + + // Part one + var and_mask : u64 = std.math.maxInt(u64); + var or_mask : u64 = 0; + + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + std.log.debug("{}", .{line}); + if (std.mem.eql(u8, line[0..4], "mask")) { + // Set mask + var mask_iter = std.mem.tokenize(line, "="); + _ = mask_iter.next(); // skip the first one + if (mask_iter.next()) |v| { + set_masks(std.mem.trim(u8, v, " "), &and_mask, &or_mask); + } + } + else { + var memory_location: u64 = 0; + var memory_value: u64 = 0; + var mem_iter = std.mem.tokenize(line, "=["); + std.log.warn("{}", .{mem_iter.next()}); // skip 'mem[' + if (mem_iter.next()) |location_line| { + std.log.debug("parsing '{}'", .{location_line}); + memory_location = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, location_line, " ]"), 10); + } + if (mem_iter.next()) |value_line| { + memory_value = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, value_line, " "), 10); + } + try write_memory(&map, memory_location, memory_value, and_mask, or_mask); + } + } + + var map_it = map.iterator(); + var sum : u64 = 0; + while (map_it.next()) |entry| { + sum += entry.value; + } + std.log.info("Part 1: Sum of non-zero memory locations: {}", .{sum}); + + // Part 2 + map.deinit(); + map = std.hash_map.AutoHashMap(u64, u64).init(gpa); + gpa.free(contents); + try f.seekTo(0); + contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + it = std.mem.tokenize(contents, "\n"); + var address_mask : [36]u8 = undefined; + while (it.next()) |line| { + std.log.debug("{}", .{line}); + if (std.mem.eql(u8, line[0..4], "mask")) { + // Set mask + var mask_iter = std.mem.tokenize(line, "="); + _ = mask_iter.next(); // skip the first one + if (mask_iter.next()) |v| { + std.mem.copy(u8, &address_mask, std.mem.trim(u8, v, " ")); + } + } + else { + var memory_location: u64 = 0; + var memory_value: u64 = 0; + var mem_iter = std.mem.tokenize(line, "=["); + _ = mem_iter.next(); // skip 'mem[' + if (mem_iter.next()) |location_line| { + std.log.debug("parsing '{}'", .{location_line}); + memory_location = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, location_line, " ]"), 10); + } + if (mem_iter.next()) |value_line| { + memory_value = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, value_line, " "), 10); + } + try write_memory_address_masked(&map, memory_location, memory_value, address_mask[0..]); + } + } + map_it = map.iterator(); + sum = 0; + while (map_it.next()) |entry| { + sum += entry.value; + } + std.log.info("Part 2: Sum of non-zero memory locations: {}", .{sum}); +} + +fn write_memory_address_masked(map: *std.hash_map.AutoHashMap(u64, u64), location: u64, value: u64, + mask: []const u8) !void { + // Fuse the value into the character mask + var i : u6 = 0; + var new_mask : [36]u8 = undefined; + std.mem.copy(u8, &new_mask, mask); + while (i < 36) : (i += 1) { + if (new_mask[i] == 'X') { + continue; + } + else if (new_mask[i] == '1') { + continue; + } + else if (new_mask[i] == '0') { + // mask to isolate bit at position 35 - i + // kth() counts from LSB to MSB, we are going in string order from + // MSB to LSB + new_mask[i] = switch(kth_bit(location, 35-i)) { + 0 => '0', + 1 => '1', + else => { + unreachable; + }, + }; + //std.log.warn("Index {}: {c} -> {c}", .{i, new_mask[i], mask[i]}); + } + } + std.log.warn("\nValue: {b:36} ({})\nPre-fuse: {}\nPst-fuse: {}", .{location, location, mask, new_mask}); + var addresses = try generate_address_list(map.allocator, new_mask[0..]); + defer addresses.deinit(); + + for (addresses.items) |address| { + std.log.warn("Wrote {} to address {}", .{value, address}); + try map.put(address, value); + } +} + +// Caller is responsible for freeing this +// This function takes the "fused mask", where the only thing left to resolve +// if the 'X' bits. +fn generate_address_list(allocator: *std.mem.Allocator, mask: []const u8) !std.ArrayList(u64) { + var masks = std.ArrayList(u64).init(allocator); + var i : u64 = 0; + // Store the offsets of the locations of the X character + var x_locations = std.ArrayList(usize).init(allocator); + defer x_locations.deinit(); + for (mask) |c, k| { + if (c == 'X') { + try x_locations.append(k); + } + } + var n_variants = std.math.pow(u64, 2, x_locations.items.len); + //std.log.warn("{} Xs in mask '{}', {} variants", .{x_locations.items.len, mask, n_variants}); + while (i < n_variants) : (i += 1) { + var m = try allocator.alloc(u8, mask.len); + std.mem.copy(u8, m, mask); + var bit_index : u6 = 0; + while (bit_index < x_locations.items.len) : (bit_index += 1) { + // At 0, all Xs become zero, + // At 1, last X becomes one, otherwise Xs are zero + // ... + m[x_locations.items[bit_index]] = switch(kth_bit(i, bit_index)) { + 0 => '0', + 1 => '1', + else => { + unreachable; + }, + }; + } + var value = try std.fmt.parseUnsigned(u64, m, 2); + //std.log.warn("\nFrom: {:64}\nGot: {b:64}", .{m, value}); + try masks.append(value); + allocator.free(m); + } + return masks; +} + +// @see https://www.geeksforgeeks.org/find-value-k-th-bit-binary-representation/ +fn kth_bit(value: u64, k: u6) u64 { + //std.debug.warn("\nKey: {}, V: {}\nOrig: {b:64}\n", .{k, value, value}); + var one: u64 = 1; + var shifted: u64 = 0; + var overflowed = @shlWithOverflow(u64, one, k, &shifted); + if (overflowed) { + std.log.warn("OVERFLOWED", .{}); + } + //std.debug.warn("Shft: {b:64}\n", .{shifted}); + //std.debug.warn("Andd: {b:64}\n", .{value & shifted}); + //std.debug.warn("Rslt: {b:64}\n", .{(value & shifted) >> k}); + return (value & shifted) >> k; +} + +fn write_memory(map: *std.hash_map.AutoHashMap(u64, u64), location: u64, value: u64, and_mask: u64, or_mask: u64) !void { + // Mask + var new_value = value; + new_value &= and_mask; + new_value |= or_mask; + try map.put(location, new_value); + std.log.debug("Wrote '{}' to '{}' (pre-masked: '{}')", + .{new_value, location, value}); + //std.log.warn("\npre_mask: {b:64}\nand_mask: {b:64}\nor_mask :{b:64}\npst_mask: {b:64}", + // .{value, and_mask, or_mask, new_value}); +} + +//const maskWidth : u64 = 36; +fn set_masks(line: []const u8, and_mask: *u64, or_mask: *u64) void { + and_mask.* = std.math.maxInt(u64); + or_mask.* = 0; + + var one: u64 = 1; + for (line) |c, k| { + var offset = @intCast(u6, line.len - k - 1); + switch(c) { + '1' => { + // Only need to tweak the or_mask + or_mask.* |= (one << offset); + }, + '0' => { + and_mask.* &= ~(one << offset); + }, + 'X' => { + continue; + }, + else => unreachable, + } + } + std.log.debug("and mask:{b:64}", .{and_mask}); + std.log.debug("or mask:{b:64}", .{or_mask}); +} + +test "mask_setting" { + var and_mask : u64 = 0; + var or_mask : u64 = 0; + var l = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"; + set_masks(l, &and_mask, &or_mask); +} + +test "memory_writing" { + var and_mask : u64 = 0; + var or_mask : u64 = 0; + var l = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"; + set_masks(l, &and_mask, &or_mask); + + var map = std.hash_map.AutoHashMap(u64, u64).init(std.testing.allocator); + defer map.deinit(); + + try write_memory(&map, 8, 11, and_mask, or_mask); + try write_memory(&map, 7, 101, and_mask, or_mask); + try write_memory(&map, 8, 0, and_mask, or_mask); + + if (map.get(8)) |v| { + std.testing.expectEqual(v, 64); + } + else { + unreachable; + } + + if (map.get(7)) |v| { + std.testing.expectEqual(v, 101); + } + else { + unreachable; + } +} + +test "kth_bit" { + var value : u64 = 13; + // 0000 1101 + var expected = [_]u64 { + // goes from LSB to MSB + 1, 0, 1, 1, + 0, 0, 0, 0, + }; + for (expected) |v, k| { + var key : u6 = @intCast(u6, k); + std.testing.expectEqual(kth_bit(value, key), expected[k]); + } +} + +test "generate_address_list" { + var mask = "000000000000000000000000000000X1101X"; + var addresses = try generate_address_list(std.testing.allocator, mask[0..]); + defer addresses.deinit(); + + //std.log.warn("\n26: {b:64}\n27: {b:64}\n58: {b:64}\n59: {b:64}\n", .{26, 27, 58, 59}); + std.testing.expectEqual(addresses.items.len, 4); + std.testing.expectEqual(addresses.items[0], 26); + std.testing.expectEqual(addresses.items[1], 58); + std.testing.expectEqual(addresses.items[2], 27); + std.testing.expectEqual(addresses.items[3], 59); +} + +test "part2" { + var map = std.hash_map.AutoHashMap(u64, u64).init(std.testing.allocator); + defer map.deinit(); + try write_memory_address_masked(&map, 42, 100, "000000000000000000000000000000X1001X"); + try write_memory_address_masked(&map, 26, 1, "00000000000000000000000000000000X0XX"); + var map_it = map.iterator(); + var sum : u64 = 0; + while (map_it.next()) |entry| { + sum += entry.value; + } + std.testing.expectEqual(sum, 208); +} diff --git a/day15/build.zig b/day15/build.zig new file mode 100644 index 0000000..6af6b1e --- /dev/null +++ b/day15/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day15", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day15/src/main.zig b/day15/src/main.zig new file mode 100644 index 0000000..5d3ad9a --- /dev/null +++ b/day15/src/main.zig @@ -0,0 +1,203 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + //var f = try std.fs.cwd().openFile("input", .{}); + //var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + + // Starting numbers 0,8,15,2,12,1,4 + var seed = [_]u64 {0, 8, 15, 2, 12, 1, 4}; + var game = try MemoryGame.create(gpa); + defer game.deinit(); + + try game.seed_game(seed[0..]); + try game.run_until(2020); + std.log.info("Round {} spoke {}", .{game.round-1, game.last_number}); + + // Part 2 + try game.run_until(30000000); + std.log.info("Round {} spoke {}", .{game.round-1, game.last_number}); +} + +const NumberEntry = struct { + last: u64, + second_last: ?u64 = null, +}; + +const MemoryGame = struct { + map: std.hash_map.AutoHashMap(u64, NumberEntry), + allocator: *std.mem.Allocator, + round: u64 = 1, // Starting at one to match the puzzle + last_number: u64 = 0, + + pub fn create(a: *std.mem.Allocator) !*MemoryGame { + var self = try a.create(MemoryGame); + errdefer a.destroy(self); + self.* = .{ + .map = std.hash_map.AutoHashMap(u64, NumberEntry).init(a), + .allocator = a, + }; + return self; + } + + pub fn deinit(self: *MemoryGame) void { + self.map.deinit(); + self.allocator.destroy(self); + } + + // Assumes there's not repeated number in the seed + pub fn seed_game(self: *MemoryGame, seed: []u64) !void { + for (seed) |s, k| { + try self.map.put(s, NumberEntry{.last = self.round}); + self.last_number = s; + self.round += 1; + } + } + + // Returns the number spoken, but also updates everything + pub fn do_round(self: *MemoryGame) !u64 { + // Consider last number "spoken" + // Has it been said before? + var retval : u64 = 0; + if (self.map.get(self.last_number)) |v| { + //std.log.debug("Found previously spoken number {} for round {}. Previous spoken on round {}, has a previous occurence: {}\n", + // .{self.last_number, self.round, v.last, v.second_last != null}); + if ((v.last == (self.round-1)) and (v.second_last == null)) { + // The previously spoken number was new + retval = 0; + if (self.map.get(0)) |v2| { + self.map.putAssumeCapacity(0, NumberEntry {.last = self.round, .second_last = v2.last}); + } + else { + // 0 is our new number + try self.map.put(0, NumberEntry {.last = self.round}); + } + } + else { + // The previous number was already spoken, so we speak the diff + retval = v.last - v.second_last.?; + if (self.map.get(retval)) |v2| { + self.map.putAssumeCapacity(retval, NumberEntry {.last = self.round, .second_last = v2.last}); + } + else { + try self.map.put(retval, NumberEntry {.last = self.round}); + } + } + } + else { + unreachable; + } + self.last_number = retval; + self.round += 1; + return retval; + } + + pub fn run_until(self: *MemoryGame, target_round: u64) !void { + var last : u64 = 0; + while (self.round <= target_round) { + //std.log.warn("Round {} before running do_round()", .{self.round}); + last = try self.do_round(); + //std.log.warn("Round {} spoke {}", .{self.round-1, self.last_number}); + } + } +}; + +test "036_ten_turns" { + var seed = [_]u64 {0, 3, 6}; + var game = try MemoryGame.create(std.testing.allocator); + defer game.deinit(); + try game.seed_game(seed[0..]); + if (game.map.get(0)) |value| { + std.testing.expectEqual(value.last, 1); + } + if (game.map.get(3)) |value| { + std.testing.expectEqual(value.last, 2); + } + if (game.map.get(6)) |value| { + std.testing.expectEqual(value.last, 3); + } + + var response = try game.do_round(); + std.testing.expectEqual(response, 0); // Round 4 + + response = try game.do_round(); + std.testing.expectEqual(response, 3); // Round 5 + + response = try game.do_round(); + std.testing.expectEqual(response, 3); // ROund 6 + + response = try game.do_round(); + std.testing.expectEqual(response, 1); // Round 7 + + response = try game.do_round(); + std.testing.expectEqual(response, 0); // Round 8 + + response = try game.do_round(); + std.testing.expectEqual(response, 4); // Roiund 9 + + response = try game.do_round(); + std.testing.expectEqual(response, 0); // Round 10 +} + +test "132_to_2020" { + var seed = [_]u64 {1, 3, 2}; + var game = try MemoryGame.create(std.testing.allocator); + defer game.deinit(); + try game.seed_game(seed[0..]); + try game.run_until(2020); + //std.log.warn("Last number spoken was {}", .{game.last_number}); + std.testing.expectEqual(game.last_number, 1); +} + +test "213_to_2020" { + var seed = [_]u64 {2, 1, 3}; + var game = try MemoryGame.create(std.testing.allocator); + defer game.deinit(); + try game.seed_game(seed[0..]); + try game.run_until(2020); + //std.log.warn("Last number spoken was {}", .{game.last_number}); + std.testing.expectEqual(game.last_number, 10); +} + +test "123_to_2020" { + var seed = [_]u64 {1, 2, 3}; + var game = try MemoryGame.create(std.testing.allocator); + defer game.deinit(); + try game.seed_game(seed[0..]); + try game.run_until(2020); + //std.log.warn("Last number spoken was {}", .{game.last_number}); + std.testing.expectEqual(game.last_number, 27); +} + +test "231_to_2020" { + var seed = [_]u64 {2, 3, 1}; + var game = try MemoryGame.create(std.testing.allocator); + defer game.deinit(); + try game.seed_game(seed[0..]); + try game.run_until(2020); + //std.log.warn("Last number spoken was {}", .{game.last_number}); + std.testing.expectEqual(game.last_number, 78); +} + +test "321_to_2020" { + var seed = [_]u64 {3, 2, 1}; + var game = try MemoryGame.create(std.testing.allocator); + defer game.deinit(); + try game.seed_game(seed[0..]); + try game.run_until(2020); + //std.log.warn("Last number spoken was {}", .{game.last_number}); + std.testing.expectEqual(game.last_number, 438); +} + +test "312_to_2020" { + var seed = [_]u64 {3, 1, 2}; + var game = try MemoryGame.create(std.testing.allocator); + defer game.deinit(); + try game.seed_game(seed[0..]); + try game.run_until(2020); + //std.log.warn("Last number spoken was {}", .{game.last_number}); + std.testing.expectEqual(game.last_number, 1836); +} diff --git a/day16/build.zig b/day16/build.zig new file mode 100644 index 0000000..b44ade0 --- /dev/null +++ b/day16/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day16", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day16/input b/day16/input new file mode 100644 index 0000000..19b2595 --- /dev/null +++ b/day16/input @@ -0,0 +1,235 @@ +136,368,517,218,187,318,185,172,146,646,804,747,816,625,695,701,420,588,167,302 +144,452,191,495,196,652,878,605,607,61,932,897,539,82,456,806,587,595,153,168 +517,981,569,738,886,608,935,882,943,627,884,644,228,698,640,53,748,570,880,322 +65,428,312,692,61,465,626,312,644,645,539,189,485,182,310,555,442,493,550,275 +701,547,434,796,278,451,179,397,233,645,741,512,442,800,693,213,188,429,654,707 +898,573,456,132,190,898,705,447,875,160,688,592,627,520,434,81,517,634,240,185 +155,433,198,917,513,425,143,149,421,131,815,13,69,887,928,451,497,923,623,347 +908,896,430,539,532,406,439,75,857,134,589,631,552,541,633,933,522,557,807,917 +367,397,712,343,276,195,334,131,137,881,884,912,197,548,817,744,54,226,457,899 +340,453,916,915,430,487,816,543,485,712,703,899,638,756,431,649,364,925,238,815 +525,70,427,894,279,430,792,365,278,946,624,568,371,61,453,595,324,947,598,104 +986,444,243,741,822,745,484,878,457,486,937,368,746,652,126,589,907,317,828,741 +171,830,687,65,815,368,508,799,71,230,560,595,364,303,312,757,112,274,597,881 +917,135,661,130,898,699,618,58,206,73,149,488,458,818,69,803,572,328,888,75 +270,133,228,458,519,56,425,450,277,750,365,538,591,522,925,201,533,982,857,190 +810,599,315,529,515,898,857,605,92,438,629,533,899,491,360,603,537,458,542,597 +307,128,930,489,156,323,924,900,309,216,101,127,312,647,605,491,237,523,746,875 +632,660,660,701,700,106,169,144,341,625,432,196,799,880,808,944,443,200,341,750 +349,881,943,793,541,772,643,171,540,572,647,55,882,569,934,365,944,199,278,568 +703,755,639,929,140,196,897,235,342,79,360,370,302,314,818,786,565,535,186,444 +936,458,393,624,509,563,540,830,788,902,200,628,896,917,795,95,496,332,941,308 +154,234,305,793,927,947,632,661,367,271,273,205,527,638,151,547,285,806,186,328 +641,530,616,660,626,274,368,171,280,149,269,456,658,336,306,194,659,102,318,149 +322,72,125,138,550,365,688,280,442,303,491,509,136,696,996,235,202,704,334,913 +640,571,170,700,803,650,592,545,421,703,600,638,590,242,316,203,3,531,906,233 +424,899,571,333,226,66,159,698,326,330,62,662,140,191,933,742,755,478,349,99 +645,790,316,205,637,935,187,700,565,485,746,947,130,188,436,726,311,827,309,58 +153,200,307,361,169,634,608,312,228,163,313,654,520,511,527,705,300,173,306,433 +125,56,770,177,237,447,425,55,557,192,275,652,160,568,495,508,525,100,487,588 +877,457,275,799,205,889,890,304,568,893,237,825,597,202,911,175,917,164,337,822 +312,306,427,893,562,326,904,931,703,693,946,71,181,631,328,566,552,190,750,709 +91,137,910,193,277,702,142,457,562,335,228,568,672,195,349,139,759,754,946,57 +548,892,303,808,883,514,69,705,942,615,128,822,514,366,54,934,554,420,433,926 +306,518,931,549,652,792,282,808,157,752,60,857,341,104,632,202,806,98,336,940 +144,991,568,185,756,367,893,695,784,631,901,797,607,69,545,696,369,944,948,641 +60,542,350,690,178,793,273,322,688,321,719,433,592,67,518,808,449,758,180,447 +901,740,339,828,898,913,895,284,93,794,789,894,529,238,75,439,519,797,54,890 +301,314,556,624,202,207,161,277,140,138,330,740,908,553,190,432,99,532,789,54 +534,67,160,994,129,272,550,599,657,630,786,556,626,319,245,692,64,948,397,532 +518,545,351,652,920,142,105,706,185,167,268,549,540,184,140,347,597,830,653,753 +275,75,743,916,512,918,162,805,150,798,797,178,67,935,603,300,94,494,491,452 +555,322,542,648,363,787,747,747,909,245,305,203,455,758,920,110,349,150,451,315 +640,309,891,542,541,519,69,720,699,435,799,131,699,686,948,541,520,703,529,696 +918,924,201,345,458,359,821,535,528,431,164,93,563,497,657,187,606,102,325,897 +154,877,828,160,346,675,144,300,304,174,605,708,437,831,934,234,234,911,550,793 +428,128,570,341,530,891,303,184,366,752,485,573,156,277,335,104,217,202,174,149 +500,558,336,927,881,135,640,440,931,242,648,304,338,235,895,232,126,61,308,551 +201,899,52,447,175,624,677,518,519,915,343,788,429,664,647,233,420,276,655,490 +396,884,892,744,877,186,988,203,639,103,143,181,900,510,346,556,631,788,742,177 +630,534,685,517,134,590,908,627,370,525,541,907,320,807,302,186,706,340,815,247 +791,490,78,232,73,273,890,589,543,271,655,169,180,530,441,137,629,918,278,920 +814,0,436,661,362,458,497,787,72,318,900,341,190,130,897,896,487,602,95,904 +918,179,141,508,886,99,307,894,686,634,641,318,546,232,563,165,543,885,705,929 +652,807,144,143,642,265,420,887,55,51,157,513,748,169,420,427,651,692,880,937 +318,565,305,929,754,587,318,308,306,825,568,457,72,218,146,805,160,342,269,70 +555,688,323,557,816,651,229,491,237,795,694,517,931,827,629,586,150,229,108,663 +907,230,149,455,109,536,910,601,801,548,346,942,159,125,158,59,74,174,446,496 +396,756,177,597,157,940,802,337,122,623,795,938,883,746,397,227,741,70,900,55 +536,159,803,195,336,426,228,888,434,911,887,753,888,735,309,185,876,920,799,623 +280,920,396,155,202,367,656,454,454,875,324,24,240,562,885,821,493,519,702,142 +491,199,150,134,433,186,949,200,101,97,546,152,706,788,337,56,760,366,145,857 +644,528,644,422,752,165,351,593,549,347,941,243,244,512,757,537,99,626,905,804 +631,901,747,424,904,510,206,99,594,820,180,910,357,171,231,488,59,328,805,656 +229,923,194,517,656,364,74,485,99,804,943,190,946,343,573,751,392,819,420,236 +616,823,922,633,149,746,565,558,322,593,319,897,695,496,914,568,552,511,94,587 +119,568,129,320,302,305,804,554,232,647,303,194,923,891,915,744,485,551,540,68 +74,336,432,197,715,923,914,527,278,660,910,53,692,452,422,513,568,531,650,944 +787,604,243,646,429,56,73,546,553,883,170,883,432,200,634,701,920,22,54,896 +318,271,875,590,360,445,177,63,999,154,746,637,535,329,92,892,949,204,442,435 +51,558,155,421,441,325,920,568,820,300,804,537,544,423,74,231,91,616,245,312 +659,652,941,431,349,351,50,662,520,646,305,642,96,490,350,697,671,637,495,797 +776,131,949,887,272,457,910,642,940,425,702,176,746,510,271,245,885,928,886,562 +313,420,594,938,946,571,193,999,938,534,161,100,607,136,101,894,934,595,561,590 +269,745,143,347,305,593,722,69,487,662,60,137,569,240,653,71,590,891,648,632 +542,623,629,806,515,178,898,230,496,143,748,509,485,604,518,445,918,981,818,626 +706,303,536,635,196,190,642,884,300,55,179,920,813,634,520,328,796,189,560,101 +239,542,116,685,104,801,759,52,567,436,322,745,628,487,687,520,203,856,191,641 +332,748,664,896,929,593,740,881,318,654,427,148,7,235,939,205,422,348,128,800 +919,553,103,430,426,727,437,663,368,368,795,103,912,751,933,922,361,492,231,516 +231,586,567,204,101,574,762,167,567,567,161,568,317,934,603,510,68,655,892,907 +491,273,431,135,161,192,930,484,167,361,396,197,247,830,938,454,939,363,605,931 +339,888,500,830,328,630,629,750,273,300,279,603,562,103,57,277,127,342,309,306 +733,68,884,341,650,602,804,656,307,891,551,789,201,485,185,488,69,188,183,600 +525,601,168,649,235,519,922,453,130,193,87,105,529,943,799,880,898,788,320,56 +822,164,814,195,519,700,546,896,595,94,916,492,457,745,491,919,597,278,67,894 +703,310,529,551,898,564,857,924,915,538,530,61,529,788,920,819,730,314,493,699 +497,337,168,443,698,502,911,496,700,800,814,905,422,62,493,202,881,820,430,891 +185,794,689,155,191,797,131,103,163,91,897,602,902,154,520,927,686,447,364,277 +927,607,746,440,322,752,202,596,427,101,194,22,346,630,127,128,752,947,561,508 +159,513,441,763,644,856,146,698,527,595,239,439,178,918,142,600,149,494,820,552 +343,557,340,70,452,655,381,883,785,137,130,908,496,653,877,894,940,791,151,433 +169,586,177,757,332,717,367,540,826,536,815,750,542,800,520,792,831,364,324,902 +935,516,687,946,99,337,447,625,936,422,351,518,79,661,149,826,184,457,73,434 +744,289,881,568,484,703,640,334,520,917,828,133,199,328,304,137,345,370,560,439 +804,487,367,273,67,239,739,587,892,697,158,508,929,143,523,909,418,637,184,135 +297,627,931,235,828,324,941,586,703,520,934,634,423,439,941,158,67,180,883,902 +432,155,443,557,254,311,340,450,807,239,277,243,628,817,789,689,591,554,696,517 +307,73,278,429,881,197,328,792,900,918,882,332,105,740,58,758,933,195,92,81 +697,759,167,816,537,430,875,444,790,943,498,649,144,525,655,359,463,909,324,573 +370,883,875,67,428,97,206,143,518,124,920,513,439,201,918,179,791,176,650,641 +792,63,139,564,738,520,175,520,365,591,694,932,631,249,887,438,103,946,174,98 +945,909,559,597,605,270,928,692,881,149,366,571,703,754,784,744,572,898,495,162 +754,316,191,157,704,153,111,551,883,535,362,800,925,130,929,949,425,686,91,923 +551,440,753,714,104,749,691,445,143,340,427,555,277,167,758,606,300,305,314,302 +433,604,649,372,751,889,568,305,654,160,194,536,921,930,573,337,230,552,303,817 +568,926,140,332,144,183,724,924,313,935,132,935,795,535,798,823,146,201,591,233 +351,605,724,662,56,704,443,562,896,787,347,234,793,816,494,561,659,898,552,454 +857,893,188,127,184,93,562,795,125,490,54,243,361,943,276,348,988,818,103,540 +308,787,793,232,426,273,704,397,740,907,830,311,126,100,985,542,628,636,157,485 +650,551,594,909,534,514,277,554,745,432,569,494,582,230,590,922,750,562,126,311 +814,904,444,204,821,160,492,205,324,489,792,912,699,454,828,341,983,275,830,187 +637,924,804,175,948,515,211,604,624,827,746,820,798,742,485,451,785,488,184,100 +153,208,199,827,200,56,530,185,655,821,177,700,148,170,535,337,707,900,343,521 +192,878,310,319,922,133,898,368,794,804,898,96,311,622,787,894,564,690,589,942 +242,899,820,143,58,623,811,52,661,342,702,562,878,146,538,510,307,206,795,900 +928,893,947,827,895,161,275,266,99,338,882,930,227,445,129,50,192,626,337,906 +756,554,564,101,96,287,198,800,192,92,798,639,687,878,932,321,785,694,153,631 +789,743,557,565,915,188,481,740,538,422,159,625,70,270,660,143,139,695,523,701 +437,657,397,336,698,592,329,175,452,913,492,816,492,478,313,923,915,181,819,645 +926,248,489,490,180,526,273,91,819,515,742,875,65,875,62,307,439,930,701,442 +787,892,816,592,332,299,331,786,151,547,161,755,798,95,572,235,499,567,644,311 +754,125,490,559,71,553,514,279,397,437,929,5,204,327,228,132,234,340,560,633 +913,87,426,522,242,240,184,193,708,750,510,558,697,103,151,651,625,332,948,571 +300,427,555,241,423,949,59,230,339,590,685,806,647,914,100,630,544,213,71,100 +755,343,926,350,822,445,943,693,932,200,905,97,129,664,159,916,251,450,557,589 +698,54,529,201,71,55,693,187,488,24,607,915,456,448,179,489,454,160,876,545 +437,756,54,565,445,901,194,206,945,821,349,59,696,496,902,532,166,160,633,150 +101,177,158,698,165,928,572,364,60,545,547,554,706,350,319,200,95,97,327,697 +51,68,223,67,883,827,533,432,949,643,497,906,519,66,312,593,188,97,635,66 +306,98,918,128,664,184,428,140,181,492,758,325,291,922,590,441,231,878,562,789 +468,541,235,433,334,946,192,97,449,940,168,61,495,155,560,639,657,825,587,948 +451,541,754,99,586,534,692,19,132,758,441,366,929,531,420,690,633,876,178,532 +553,331,320,193,887,433,104,817,241,374,91,700,708,498,269,708,151,269,635,739 +630,824,178,166,829,645,68,339,397,747,103,132,857,243,596,204,690,97,898,335 +550,741,634,426,58,381,934,363,456,895,345,487,898,703,99,906,528,498,635,360 +907,934,498,698,793,810,691,275,423,238,313,438,575,425,141,563,322,884,135,201 +14,330,588,105,146,173,309,897,59,176,334,891,785,656,492,315,571,426,104,795 +153,876,887,321,657,931,855,510,362,333,556,92,64,591,180,641,54,179,931,910 +361,328,275,565,359,532,894,133,61,567,701,632,470,67,509,806,626,747,911,271 +2,198,322,698,608,447,817,454,532,68,888,540,690,447,434,921,949,705,946,97 +182,361,485,348,368,922,52,799,433,187,298,369,238,168,693,797,156,631,200,936 +754,553,559,545,685,191,490,634,589,539,392,879,128,105,701,509,549,815,511,687 +882,564,261,156,564,655,455,908,739,359,137,516,485,426,904,933,597,307,349,660 +419,896,64,802,443,543,804,300,746,914,793,593,426,314,489,803,929,743,275,59 +171,636,681,93,927,315,520,587,168,694,50,130,333,441,795,628,702,202,68,920 +139,738,164,895,128,344,806,653,438,887,136,939,351,458,361,239,746,102,510,594 +921,911,367,799,548,897,51,122,366,934,929,229,625,157,685,945,130,513,916,367 +947,195,626,827,707,535,439,700,707,326,657,455,109,179,147,450,599,96,690,159 +438,95,521,520,937,226,794,364,522,127,883,645,424,423,524,704,312,917,1,344 +947,635,455,738,814,740,422,450,793,138,519,988,232,947,792,64,426,65,663,428 +840,367,447,188,909,333,130,245,927,241,73,315,574,173,229,325,273,508,878,689 +882,143,361,90,309,447,909,929,330,234,509,363,743,50,931,756,336,603,516,332 +129,829,154,143,646,350,105,155,524,443,171,65,338,345,336,742,302,644,982,688 +575,739,805,347,944,747,308,509,686,569,928,203,757,92,436,912,822,281,205,808 +744,710,565,141,237,67,694,569,147,434,664,949,700,528,820,623,337,597,68,340 +719,185,486,550,369,316,831,175,420,632,490,629,899,364,912,485,923,657,61,646 +885,276,511,745,789,313,400,545,573,708,687,650,72,692,876,625,202,823,750,608 +74,930,695,875,635,608,335,658,642,689,227,657,743,16,896,142,944,795,167,525 +423,831,603,795,452,351,794,238,857,97,606,360,735,426,426,895,931,336,514,315 +902,227,487,754,520,177,98,191,316,332,745,738,502,645,828,240,148,826,703,541 +136,173,317,265,640,348,653,894,75,686,563,125,949,443,641,183,634,104,650,334 +191,628,943,661,808,657,645,160,316,148,316,637,166,606,652,344,277,943,565,448 +370,949,693,569,147,938,204,926,796,700,880,437,328,891,172,308,5,100,635,145 +498,304,533,453,446,52,184,310,634,527,933,59,405,913,650,624,545,521,59,446 +451,14,454,313,143,799,643,784,485,690,651,58,565,938,330,742,300,756,193,556 +799,103,882,650,785,603,820,317,636,453,111,593,626,902,630,795,638,928,534,527 +303,134,527,820,145,127,548,825,200,232,801,573,594,598,920,456,925,723,593,341 +829,540,461,605,702,534,785,237,587,155,635,143,176,489,930,205,126,705,228,320 +915,144,484,559,142,804,158,76,237,335,921,660,531,370,194,457,891,660,627,508 +426,239,910,745,557,805,435,154,431,795,528,856,989,539,206,346,659,231,182,326 +54,893,815,195,567,142,940,452,628,638,533,319,936,760,547,425,569,695,749,818 +663,157,244,699,323,129,489,510,93,100,143,821,72,543,549,172,335,648,165,228 +597,426,936,829,799,315,787,148,98,259,913,497,200,326,344,641,276,278,201,822 +250,941,689,157,312,639,631,588,572,902,632,334,311,226,921,522,647,240,566,820 +746,928,535,791,342,51,931,167,637,935,155,655,848,831,926,342,881,882,126,136 +437,792,745,628,556,69,91,893,161,436,64,877,186,436,533,679,423,184,552,170 +147,192,755,556,570,199,181,642,103,128,125,549,593,741,934,202,984,435,101,308 +275,948,568,340,538,947,338,156,541,487,334,336,219,561,738,365,530,188,624,422 +531,397,664,617,908,57,93,171,149,364,598,148,875,818,199,823,455,128,328,820 +193,489,794,169,159,365,76,803,75,484,915,634,276,330,229,421,156,98,587,456 +324,159,6,66,237,458,489,167,887,155,530,934,321,53,226,97,748,605,359,179 +744,596,339,431,759,453,889,456,441,130,12,485,927,877,498,561,746,545,457,300 +944,194,517,587,426,489,129,96,136,885,801,788,554,157,457,538,615,154,527,428 +628,485,820,803,883,203,888,599,204,794,784,564,245,692,606,288,327,906,434,146 +510,314,660,644,698,568,262,351,359,513,946,361,657,607,56,310,351,884,624,498 +798,928,439,531,555,159,4,331,742,75,931,790,532,822,425,792,144,196,305,902 +786,751,749,893,808,91,190,445,944,877,921,887,686,165,97,820,135,234,337,662 +829,925,635,819,559,748,205,594,803,71,791,319,449,937,203,132,71,386,62,520 +892,226,631,900,803,172,203,305,495,397,143,175,328,194,72,171,588,130,722,320 +301,518,630,913,143,548,226,132,184,448,304,229,662,231,608,763,245,906,828,437 +453,273,189,550,269,600,441,703,125,299,631,759,436,321,882,125,644,263,815,426 +787,879,590,455,154,203,74,95,334,359,559,314,552,319,513,454,24,299,364,656 +429,437,322,739,827,230,168,197,708,701,186,441,749,312,635,856,445,777,902,635 +946,4,831,146,508,326,450,206,492,662,69,98,897,650,658,547,333,889,197,129 +300,917,642,791,661,825,306,450,278,237,940,943,188,158,138,713,630,946,550,817 +511,340,588,630,545,554,359,443,269,824,325,639,752,829,128,423,493,936,787,123 +928,92,807,754,161,280,317,337,877,493,299,546,940,802,820,877,716,143,707,902 +207,424,789,178,179,552,707,785,275,233,455,598,887,68,921,641,522,754,432,738 +514,116,60,191,534,633,598,427,327,369,341,54,130,599,347,572,707,337,102,232 +807,530,347,364,543,330,695,93,901,190,333,603,615,57,648,697,449,320,592,822 +878,696,303,298,892,366,697,234,754,186,443,572,488,188,172,700,443,935,927,183 +495,147,901,788,647,197,171,925,745,919,701,941,73,568,542,390,429,912,529,131 +800,696,330,793,655,914,59,180,447,816,50,321,806,917,58,51,78,900,430,881 +166,808,924,185,139,428,64,888,659,151,519,336,277,194,91,484,875,488,526,363 +875,172,904,364,919,794,926,236,915,816,816,135,909,118,595,750,530,925,656,193 +807,379,919,57,440,741,931,426,307,757,487,940,487,362,485,195,226,623,323,493 +206,789,424,130,573,831,355,945,60,658,790,368,931,944,548,534,757,942,341,486 +948,280,664,190,126,560,436,885,571,893,550,785,68,281,159,889,881,312,942,705 +557,542,818,697,913,351,635,130,801,930,66,946,351,230,170,260,508,93,438,903 +890,570,314,658,785,245,882,510,325,636,929,322,337,710,923,451,303,550,187,458 +891,790,943,449,689,549,519,588,2,443,304,160,556,240,553,75,320,275,436,572 +56,946,556,623,142,930,875,318,686,285,454,562,637,935,152,902,496,704,97,917 +637,102,294,643,179,522,493,442,546,453,884,185,351,652,178,206,129,341,931,168 +522,626,821,308,198,547,637,792,984,827,693,456,596,330,73,204,646,234,698,149 +198,327,324,564,815,904,947,702,798,70,203,758,233,129,647,96,880,269,2,904 +682,420,455,944,928,168,368,943,947,273,940,556,552,424,924,135,346,324,56,561 +508,101,190,526,934,622,945,925,341,159,586,549,180,703,437,820,65,368,635,396 +748,787,876,487,158,589,169,653,905,334,631,637,329,270,338,615,625,324,238,228 +183,803,751,563,206,204,320,876,13,949,594,647,568,317,750,628,877,155,546,880 +90,818,606,509,636,172,59,599,818,498,435,229,234,801,904,168,802,315,567,458 +522,327,105,857,186,641,131,234,821,154,817,887,718,608,232,140,566,598,804,485 +645,744,827,913,103,602,229,525,569,187,544,163,370,793,450,925,245,510,68,738 +932,365,93,115,147,237,654,137,50,913,485,92,458,787,342,174,898,58,817,910 +315,488,205,645,638,699,235,364,663,74,687,597,771,749,896,631,139,532,897,550 +145,130,336,914,322,76,492,338,359,798,536,64,361,509,917,370,95,586,934,935 +525,544,796,226,96,572,367,916,652,71,634,745,161,998,591,942,547,344,227,626 +794,806,486,897,231,361,808,739,183,370,227,192,69,136,560,439,887,109,269,331 +496,928,270,550,800,179,788,646,197,789,906,511,640,550,904,227,592,81,895,92 +396,334,738,230,104,929,502,137,302,440,927,175,449,169,304,451,421,559,901,513 +899,187,303,161,608,545,638,160,496,537,338,426,516,374,66,303,650,430,453,758 +95,991,554,932,943,95,740,276,323,190,856,697,888,270,498,595,600,786,149,454 +384,155,54,630,181,230,645,58,540,745,548,520,430,935,155,755,171,571,592,892 +892,695,529,937,330,605,60,901,520,539,553,330,205,588,538,472,689,753,934,423 +53,195,67,817,21,625,543,912,368,945,509,183,425,486,367,922,156,829,755,793 +271,337,271,229,827,947,313,163,548,278,823,186,687,747,59,328,149,897,926,892 diff --git a/day16/input_fields b/day16/input_fields new file mode 100644 index 0000000..ce96069 --- /dev/null +++ b/day16/input_fields @@ -0,0 +1,20 @@ +departure location: 29-458 or 484-956 +departure station: 40-723 or 738-960 +departure platform: 30-759 or 784-956 +departure track: 37-608 or 623-964 +departure date: 31-664 or 685-950 +departure time: 27-498 or 508-959 +arrival location: 36-245 or 269-961 +arrival station: 35-808 or 814-973 +arrival platform: 40-831 or 856-951 +arrival track: 36-857 or 875-971 +class: 43-161 or 167-963 +duration: 25-75 or 91-966 +price: 37-708 or 724-972 +route: 39-370 or 396-971 +row: 47-280 or 299-949 +seat: 41-105 or 125-952 +train: 43-351 or 359-966 +type: 34-575 or 586-965 +wagon: 27-397 or 420-953 +zone: 48-206 or 226-965 \ No newline at end of file diff --git a/day16/input_myticket b/day16/input_myticket new file mode 100644 index 0000000..afcddf5 --- /dev/null +++ b/day16/input_myticket @@ -0,0 +1 @@ +61,151,59,101,173,71,103,167,127,157,137,73,181,97,179,149,131,139,67,53 \ No newline at end of file diff --git a/day16/src/main.zig b/day16/src/main.zig new file mode 100644 index 0000000..cbcd80c --- /dev/null +++ b/day16/src/main.zig @@ -0,0 +1,432 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var fields = try read_fields("input_fields", gpa); + defer fields.deinit(); + // for (fields.items) |f| { + // std.log.debug("Field '{}' has {} limits", .{f.name, f.limits.items.len}); + // for (f.limits.items) |i| { + // std.log.debug(" {} - {}", .{i.min, i.max}); + // } + // } + + var tickets = try read_tickets("input", gpa); + defer tickets.deinit(); + + var error_tickets = std.ArrayList(usize).init(gpa); + defer error_tickets.deinit(); + + var error_rate : u64 = 0; + for (tickets.items) |t, kt| { + for (t.values) |v, kv| { + if (!valid_for_any_field(v, fields.items[0..])) { + std.log.debug("Field {} ({}) from ticket #{} is not valid for any field", + .{kv, v, kt}); + error_rate += v; + try error_tickets.append(kt); + break; + } + } + } + std.log.info("Error rate from nearby tickets: {}, from {} tickets", .{error_rate, tickets.items.len}); + + // Part 2, discard invalid tickets. + while (error_tickets.popOrNull()) |v| { + var t = tickets.orderedRemove(v); + std.log.debug("Removed ticket #{}: '{}'\n{}, {}, {}, {}, {}, {}, {}, {}, {}, {}\n{}, {}, {}, {}, {}, {}, {}, {}, {}, {}", + .{v, t, t.values[0], t.values[1], t.values[2], t.values[3], t.values[4], t.values[5], t.values[6], t.values[7], t.values[8], t.values[9], t.values[10], t.values[11], t.values[12], t.values[13], t.values[14], t.values[15], t.values[16], t.values[17], t.values[18], t.values[19]}); + } + std.log.debug("{} valid tickets to use for field position search", .{tickets.items.len}); + try determine_field_positions(tickets.items[0..], fields.items[0..], gpa); + for (fields.items) |f, idx| { + std.log.info("Field '{}' has position {}", + .{f.name, f.position.?}); + } + + var my_ticket = Ticket { + .values = [_]u64 { + 61,151,59,101,173,71,103,167,127,157,137,73,181,97,179,149,131,139,67,53, + }, + }; + + var part2_result : u64 = 1; + for (fields.items) |f, idx| { + if (std.mem.startsWith(u8, f.name, "departure")) { + part2_result *= my_ticket.values[f.position.?]; + } + } + std.log.info("Product of all values for the departure codes on my ticket: {}", .{part2_result}); +} + +pub fn determine_field_positions(tickets: []Ticket, fields: []Field, allocator: *std.mem.Allocator) !void { + // While there are fields with unknown positions, loop through the fields from 0..len, + // To improve performance, we could cache which fields are not valid for a given position + // in the ticket values to avoid re-calculating across the list. + // If the input tickets contain invalid examples, then this resolution with loop forever. + // while(fields_with_unknown_positions_exist(fields)) { + // for (fields) |f, f_idx| { + // if (f.position != null) { + // continue; + // } + // std.log.warn("Testing field '{}' ({}) to determine position", + // .{f.name, f_idx}); + // var pos : usize = 0; + // while (pos < fields.len) : (pos += 1) { + // if (already_known_position(fields, f_idx)) { + // continue; + // } + // std.log.warn("Checking to see if all tickets match field {} in value index {}", + // .{f.name, pos}); + // if (all_tickets_fit_field_limits(tickets, &fields[f_idx], pos)) { + // fields[f_idx].position = pos; + // std.log.warn("Found position {} for field {}", + // .{pos, f.name}); + // break; + // } + // } + // } + // } + + // We have field.len positions to resolve. For each field, we build a list of possible + // columns that could match. If after the first pass, fields with only a single possible + // column are assigned that column, then those column numbers of removed from the + // possibilities of the remaining fields. + var completely_resolved_positions = std.ArrayList(usize).init(allocator); + defer completely_resolved_positions.deinit(); + + var possible_positions_per_field = try allocator.alloc(std.ArrayList(usize), fields.len); + defer allocator.free(possible_positions_per_field); + for (fields) |f, idx| { + possible_positions_per_field[idx] = std.ArrayList(usize).init(allocator); + var ticket_value_index : usize = 0; + while (ticket_value_index < fields.len) : (ticket_value_index += 1) { + if (all_tickets_fit_field_limits(tickets, &fields[idx], ticket_value_index)) { + std.log.warn("Adding {} as option for field {}", .{ticket_value_index, f.name}); + try possible_positions_per_field[idx].append(ticket_value_index); + } + } + std.log.warn("Field '{}' has possible ticket value indices:", .{f.name}); + for (possible_positions_per_field[idx].items) |i| { + std.log.warn(" {}", .{i}); + } + } + + var most_constrained_field_index : usize = 0; + var min_possibilities : usize = std.math.maxInt(usize); + // Check to make sure we can start to solve without making a decision of some sort + for (fields) |f, idx| { + if (possible_positions_per_field[idx].items.len < min_possibilities) { + min_possibilities = possible_positions_per_field[idx].items.len; + most_constrained_field_index = idx; + } + } + std.debug.assert(min_possibilities == @as(usize, 1)); + while (completely_resolved_positions.items.len < fields.len) { + var ok = try process_solution_round(fields, possible_positions_per_field, &completely_resolved_positions); + if (!ok) { + std.log.warn("Unable to solve", .{}); + break; + } + for (fields) |f, idx| { + std.log.warn("After round, field {} has {} possibilities remaining.", + .{f.name, possible_positions_per_field[idx].items.len}); + for (possible_positions_per_field[idx].items) |i| { + std.log.warn(" {}", .{i}); + } + } + } + + // Set the position for each field + for (fields) |f, idx| { + std.log.warn("Field {} has {} remaining possibilities after solution rounds: {}", + .{f.name, possible_positions_per_field[idx].items.len, + possible_positions_per_field[idx].items[0]}); + std.debug.assert(possible_positions_per_field[idx].items.len <= 1); + fields[idx].position = possible_positions_per_field[idx].items[0]; + } + + // Cleanup + for (possible_positions_per_field) |p| { + p.deinit(); + } +} + +fn process_solution_round(fields: []Field, possibilities: []std.ArrayList(usize), resolved: *std.ArrayList(usize)) !bool { + // Check to make sure we can start to solve without making a decision of some sort + for (fields) |f, idx| { + if (possibilities[idx].items.len == 1) { + std.log.warn("{} only solution for {}", .{possibilities[idx].items[0], f.name}); + var already_in_resolved = in_array(idx, resolved); + if (!already_in_resolved) { + try resolved.append(idx); + } + // Remove the from possibilities of other fields + var value_to_remove = possibilities[idx].items[0]; + for (fields) |f2, idx2| { + std.log.warn("Checking {} for removal of possibility {}", + .{f2.name, value_to_remove}); + if (idx2 == idx) { + continue; + } + var need_to_remove = false; + var remove_index : ?usize = null; + if (possibilities[idx2].items.len == 1) { + continue; + } + for (possibilities[idx2].items) |i, k| { + std.log.warn("pos {}: {}", .{k, i}); + if (i == value_to_remove) { + std.log.warn("want to remove index {} (value: {}) from possibilities", .{k, i}); + need_to_remove = true; + remove_index = k; + break; + } + } + if (need_to_remove) { + if (remove_index) |ri| { + std.log.warn("Removed index {} from possibilities for {}", + .{ri, f2.name}); + _ = possibilities[idx2].orderedRemove(ri); + } + else { + std.log.warn("Wanted to remove {} from possibilities for {}, but remove_index not set", + .{idx2, f2.name}); + } + } + } + if (!already_in_resolved) { + // Only process one removal per round + break; + } + } + } + // @TODO Verifiy we still have at least another round left + //std.debug.assert(min_possibilities == @as(usize, 1)); + // if (min_possibilities > 1) { + // std.log.warn("Unable to provide solution, minimum of two possibilities for all remaining fields.", .{}); + // return false; + // } + var min_possibilities_remaining : usize = std.math.maxInt(usize); + for (fields) |f, idx| { + if (in_array(idx, resolved)) { + continue; + } + min_possibilities_remaining = std.math.min(min_possibilities_remaining, + possibilities[idx].items.len); + } + if (min_possibilities_remaining > 1) { + std.log.warn("Unable to process more rounds, at least all non-resolved items have multiple solutions remaining", .{}); + return false; + } + if (fields.len == resolved.items.len) { + std.log.debug("Resolve items length matches field items length, should be done doing solution rounds", .{}); + return false; + } + return true; +} + +fn in_array(value: usize, a: *std.ArrayList(usize)) bool { + for (a.items) |v, k| { + if (value == v) { + return true; + } + } + return false; +} + +fn all_tickets_fit_field_limits(tickets: []Ticket, field: *Field, index: usize) bool { + for (tickets) |t, k| { + //std.log.warn("Checking ticket for field '{}', index {}: {}", + // .{field.name, index, t}); + if (!field.in_limits(t.values[index])) { + //std.log.warn("Ticket #{} has a value {} at index {} which does not match limits of field '{}'", + //.{k, t.values[index], index, field.name}); + return false; + } + } + return true; +} + +fn already_known_position(fields: []Field, position: usize) bool { + for (fields) |f| { + if (f.position) |p| { + if (p == position) { + return true; + } + } + } + return false; +} + +fn fields_with_unknown_positions_exist(fields: []Field) bool { + for (fields) |f| { + if (f.position == null) { + return true; + } + } + return false; +} + +pub fn read_tickets(filename: []const u8, a: *std.mem.Allocator) !std.ArrayList(Ticket) { + var f = try std.fs.cwd().openFile(filename, .{}); + var contents = try f.readToEndAlloc(a, std.math.maxInt(u32)); + defer a.free(contents); + + var tickets = std.ArrayList(Ticket).init(a); + errdefer tickets.deinit(); + + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + var ticket = std.mem.zeroes(Ticket); + var count : u64 = 0; + var ticket_it = std.mem.tokenize(line, ","); + while (ticket_it.next()) |v| { + ticket.values[count] = try std.fmt.parseUnsigned(u64, v, 10); + count += 1; + } + try tickets.append(ticket); + } + return tickets; +} + +const Ticket = struct { + values: [20]u64, +}; + +pub fn valid_for_any_field(value: u64, fields: []Field) bool { + var r = false; + for (fields) |f| { + r = f.in_limits(value); + // for (f.limits.items) |l| { + // if (value >= l.min and value <= l.max) { + // r = true; + // //std.log.debug("{} is at least valid for field '{}', between {} and {}", + // // .{value, f.name, l.min, l.max}); + // break; + // } + // } + if (r == true) { + break; + } + } + return r; +} + +fn read_fields(filename: []const u8, a: *std.mem.Allocator) !std.ArrayList(Field) { + var f = try std.fs.cwd().openFile(filename, .{}); + var contents = try f.readToEndAlloc(a, std.math.maxInt(u32)); + defer a.free(contents); + var it = std.mem.tokenize(contents, "\n"); + + var fields = std.ArrayList(Field).init(a); + errdefer fields.deinit(); + var limits : std.ArrayList(Limit) = undefined; + var name : []u8 = undefined; + while (it.next()) |line| { + var lit = std.mem.tokenize(line, ":"); + limits = std.ArrayList(Limit).init(a); + errdefer limits.deinit(); + if (lit.next()) |n| { + name = try a.dupe(u8, n); + } + if (lit.next()) |limit_line| { + // split on the 'o', just cause. I don't think we have a handy split + // for a complete string + var limit_line_it = std.mem.tokenize(limit_line, "o"); + while(limit_line_it.next()) | range_line | { + var min: u64 = 0; + var max: u64 = 0; + var range_line_it = std.mem.tokenize(range_line, "-"); + if (range_line_it.next()) |v| { + min = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, v, "r "), 10); + } + if (range_line_it.next()) |v| { + max = try std.fmt.parseUnsigned(u64, std.mem.trim(u8, v, "r "), 10); + } + try limits.append(Limit {.min = min, .max = max}); + } + } + try fields.append(Field {.name = name, .limits = limits, .allocator = a}); + } + return fields; +} + +const Limit = struct { + min: u64, + max: u64, +}; + +const Field = struct { + name: []u8, + limits: std.ArrayList(Limit), + allocator: * std.mem.Allocator, + position: ?u64 = null, + + pub fn deinit(self: *const Field) void { + self.allocator.free(self.name); + self.limits.deinit(); + } + + pub fn in_limits(self: *const Field, value: u64) bool { + //std.log.warn("Testing if {} fits in limits for field '{}'", + // .{value, self.name}); + for (self.limits.items) |l| { + //std.log.warn("{}", .{l}); + if (value >= l.min and value <= l.max) { + return true; + } + } + //std.log.warn("{} does not fit in limits for field '{}'", .{value, self.name}); + return false; + } +}; + +test "valid_for_any_field" { + var fields = try read_fields("test_input_fields", std.testing.allocator); + + std.testing.expect(valid_for_any_field(40, fields.items[0..])); + std.testing.expect(valid_for_any_field(4, fields.items[0..]) == false); + std.testing.expect(valid_for_any_field(55, fields.items[0..]) == false); + std.testing.expect(valid_for_any_field(12, fields.items[0..]) == false); + + for(fields.items) |f| { + f.deinit(); + } + fields.deinit(); +} + +test "field_resolution" { + var fields = try read_fields("test_input_fields2", std.testing.allocator); + + var tickets = [_]Ticket { + Ticket { .values = [_]u64 {3, 9, 18, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,} + }, + Ticket { .values = [_]u64 {15, 1, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,} + }, + Ticket { .values = [_]u64 {5, 14, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,} + }, + }; + + var fit = all_tickets_fit_field_limits(tickets[0..], &fields.items[1], 0); + std.testing.expect(fit); + + fit = all_tickets_fit_field_limits(tickets[0..], &fields.items[0], 0); + std.testing.expect(fit == false); + + try determine_field_positions(tickets[0..], fields.items[0..], std.testing.allocator); + std.testing.expectEqual(@as(u64, 1), fields.items[0].position.?); + std.testing.expectEqual(@as(u64, 0), fields.items[1].position.?); + std.testing.expectEqual(@as(u64, 2), fields.items[2].position.?); + for(fields.items) |f| { + f.deinit(); + } + fields.deinit(); + +} diff --git a/day16/test_input_fields b/day16/test_input_fields new file mode 100644 index 0000000..bf992cd --- /dev/null +++ b/day16/test_input_fields @@ -0,0 +1,3 @@ +class: 1-3 or 5-7 +row: 6-11 or 33-44 +seat: 13-40 or 45-50 \ No newline at end of file diff --git a/day16/test_input_fields2 b/day16/test_input_fields2 new file mode 100644 index 0000000..c44aae6 --- /dev/null +++ b/day16/test_input_fields2 @@ -0,0 +1,3 @@ +class: 0-1 or 4-19 +row: 0-5 or 8-19 +seat: 0-13 or 16-19 \ No newline at end of file diff --git a/day17/build.zig b/day17/build.zig new file mode 100644 index 0000000..54a298a --- /dev/null +++ b/day17/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day17", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day17/input b/day17/input new file mode 100644 index 0000000..d0697d6 --- /dev/null +++ b/day17/input @@ -0,0 +1,8 @@ +####...# +......#. +#..#.##. +.#...#.# +..###.#. +##.###.. +.#...### +.##....# diff --git a/day17/src/main.zig b/day17/src/main.zig new file mode 100644 index 0000000..9fa1622 --- /dev/null +++ b/day17/src/main.zig @@ -0,0 +1,633 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u64)); + defer gpa.free(contents); + + var sim = try Simulation.init(gpa); + defer sim.deinit(); + + var sim4d = try Simulation4D.init(gpa); + defer sim4d.deinit(); + + var it = std.mem.tokenize(contents, "\n"); + var y : i64 = 0; + while (it.next()) |line| { + for (line) |c, k| { + var state : CubeState = .inactive; + if (c == '#') { + state = .active; + } + try sim.add_cube([_]i64 {@intCast(i64, k), y, 0}, state); + try sim4d.add_cube([_]i64 {@intCast(i64, k), y, 0, 0}, state); + } + y += 1; + } + + // Run 6 rounds + try sim.do_round(); // 1 + try sim.do_round(); // 2 + try sim.do_round(); // 3 + try sim.do_round(); // 4 + try sim.do_round(); // 5 + try sim.do_round(); // 6 + + std.log.info("After 6 rounds, there are {} active cubes", + .{sim.count_active_cubes()}); + + // Part 2 + try sim4d.do_round(); // 1 + try sim4d.do_round(); // 2 + try sim4d.do_round(); // 3 + try sim4d.do_round(); // 4 + try sim4d.do_round(); // 5 + try sim4d.do_round(); // 6 + + std.log.info("After 6 rounds, there are {} active cubes", + .{sim4d.count_active_cubes()}); +} + +const CubeState = enum { + inactive, + active +}; + +const Cube = struct { + pos: [3]i64, + state: CubeState = .inactive, + next_state: ?CubeState = null, + neighbours: u64 = 0, + + pub fn get_neighbour_positions(self: *Cube) [26][3]i64 { + return [_][3]i64 { + // z-1 + [_]i64 {self.pos[0], self.pos[1], self.pos[2]-1}, + [_]i64 {self.pos[0], self.pos[1]+1, self.pos[2]-1}, + [_]i64 {self.pos[0], self.pos[1]-1, self.pos[2]-1}, + [_]i64 {self.pos[0]-1, self.pos[1], self.pos[2]-1}, + [_]i64 {self.pos[0]-1, self.pos[1]+1, self.pos[2]-1}, + [_]i64 {self.pos[0]-1, self.pos[1]-1, self.pos[2]-1}, + [_]i64 {self.pos[0]+1, self.pos[1], self.pos[2]-1}, + [_]i64 {self.pos[0]+1, self.pos[1]+1, self.pos[2]-1}, + [_]i64 {self.pos[0]+1, self.pos[1]-1, self.pos[2]-1}, + // z+0 + [_]i64 {self.pos[0], self.pos[1]+1, self.pos[2]}, + [_]i64 {self.pos[0], self.pos[1]-1, self.pos[2]}, + [_]i64 {self.pos[0]-1, self.pos[1], self.pos[2]}, + [_]i64 {self.pos[0]-1, self.pos[1]+1, self.pos[2]}, + [_]i64 {self.pos[0]-1, self.pos[1]-1, self.pos[2]}, + [_]i64 {self.pos[0]+1, self.pos[1], self.pos[2]}, + [_]i64 {self.pos[0]+1, self.pos[1]+1, self.pos[2]}, + [_]i64 {self.pos[0]+1, self.pos[1]-1, self.pos[2]}, + // z+1 + [_]i64 {self.pos[0], self.pos[1], self.pos[2]+1}, + [_]i64 {self.pos[0], self.pos[1]+1, self.pos[2]+1}, + [_]i64 {self.pos[0], self.pos[1]-1, self.pos[2]+1}, + [_]i64 {self.pos[0]-1, self.pos[1], self.pos[2]+1}, + [_]i64 {self.pos[0]-1, self.pos[1]+1, self.pos[2]+1}, + [_]i64 {self.pos[0]-1, self.pos[1]-1, self.pos[2]+1}, + [_]i64 {self.pos[0]+1, self.pos[1], self.pos[2]+1}, + [_]i64 {self.pos[0]+1, self.pos[1]+1, self.pos[2]+1}, + [_]i64 {self.pos[0]+1, self.pos[1]-1, self.pos[2]+1}, + }; + } + + pub fn print_state(self: *Cube) !void { + var stdout = std.io.getStdOut().writer(); + var c : u8 = '.'; + if (self.state == .active) { + c = '#'; + } + try stdout.print("({}x, {}y, {}z) {c}\n", .{self.pos[0], self.pos[1], self.pos[2], c}); + } +}; + +const Simulation = struct { + map: std.hash_map.AutoHashMap([3]i64, Cube), + allocator: *std.mem.Allocator, + + pub fn init(allocator: *std.mem.Allocator) !*Simulation { + var self = try allocator.create(Simulation); + errdefer allocator.destroy(self); + + self.* = Simulation { + .map = std.hash_map.AutoHashMap([3]i64, Cube).init(allocator), + .allocator = allocator, + }; + return self; + } + + pub fn deinit(self: *Simulation) void { + self.map.deinit(); + self.allocator.destroy(self); + } + + pub fn add_cube(self: *Simulation, pos: [3]i64, state: CubeState) !void { + try self.map.put(pos, Cube {.pos = pos, .state = state}); + } + + pub fn print_state(self: *Simulation) !void { + // @TODO Organize the output somehow + var stdout = std.io.getStdOut().writer(); + var z_min : i64 = std.math.maxInt(i64); + var z_max : i64 = std.math.minInt(i64); + var y_min : i64 = std.math.maxInt(i64); + var y_max : i64 = std.math.minInt(i64); + var x_min : i64 = std.math.maxInt(i64); + var x_max : i64 = std.math.minInt(i64); + + var it = self.map.iterator(); + while (it.next()) |entry| { + //try entry.value.print_state(); + x_max = std.math.max(x_max, entry.value.pos[0]); + x_min = std.math.min(x_min, entry.value.pos[0]); + y_max = std.math.max(y_max, entry.value.pos[1]); + y_min = std.math.min(y_min, entry.value.pos[1]); + z_max = std.math.max(z_max, entry.value.pos[2]); + z_min = std.math.min(z_min, entry.value.pos[2]); + } + + // For from lowest to highest then + var z_pos = z_min; + while (z_pos <= z_max) : (z_pos += 1) { + try stdout.print("z={} x=[{}..{}],y=[{}..{}]\n", .{z_pos, x_min, x_max, y_min, y_max}); + var y_pos = y_min; + while (y_pos <= y_max) : (y_pos += 1) { + var x_pos = x_min; + while (x_pos <= x_max) : (x_pos += 1) { + //try stdout.print("({}, {}, {})\n", .{x_pos, y_pos, z_pos}); + var c : u8 = '.'; + if (self.map.get([_]i64{x_pos, y_pos, z_pos})) |cube| { + if (cube.state == .active) { + c = '#'; + } + } + try stdout.print("{c}", .{c}); + } + _ = try stdout.write("\n"); + } + _ = try stdout.write("\n"); + } + _ = try stdout.write("\n"); + + } + + pub fn print_state_neighbour_count (self: *Simulation) !void { + // @TODO Organize the output somehow + var stdout = std.io.getStdOut().writer(); + var z_min : i64 = std.math.maxInt(i64); + var z_max : i64 = std.math.minInt(i64); + var y_min : i64 = std.math.maxInt(i64); + var y_max : i64 = std.math.minInt(i64); + var x_min : i64 = std.math.maxInt(i64); + var x_max : i64 = std.math.minInt(i64); + + var it = self.map.iterator(); + while (it.next()) |entry| { + //try entry.value.print_state(); + x_max = std.math.max(x_max, entry.value.pos[0]); + x_min = std.math.min(x_min, entry.value.pos[0]); + y_max = std.math.max(y_max, entry.value.pos[1]); + y_min = std.math.min(y_min, entry.value.pos[1]); + z_max = std.math.max(z_max, entry.value.pos[2]); + z_min = std.math.min(z_min, entry.value.pos[2]); + } + + // For from lowest to highest then + var z_pos = z_min; + while (z_pos <= z_max) : (z_pos += 1) { + try stdout.print("z={} x=[{}..{}],y=[{}..{}]\n", .{z_pos, x_min, x_max, y_min, y_max}); + var y_pos = y_min; + while (y_pos <= y_max) : (y_pos += 1) { + var x_pos = x_min; + while (x_pos <= x_max) : (x_pos += 1) { + //try stdout.print("({}, {}, {})\n", .{x_pos, y_pos, z_pos}); + var c : u64 = 0; + if (self.map.get([_]i64{x_pos, y_pos, z_pos})) |cube| { + c = cube.neighbours; + } + try stdout.print("{:02}", .{c}); + } + _ = try stdout.write("\n"); + } + _ = try stdout.write("\n"); + } + _ = try stdout.write("\n"); + + } + + pub fn do_round(self: *Simulation) !void { + // For each cube, check all of it's neighbours + var it = self.map.iterator(); + var neighbours_to_add = std.ArrayList([3]i64).init(self.allocator); + defer neighbours_to_add.deinit(); + + // Get the neighbours we need possibly create for this round + while (it.next()) |entry| { + var neighbours = entry.value.get_neighbour_positions(); + var n_active : u64 = 0; + for (neighbours) |n_pos| { + if (self.map.get(n_pos)) |n| { + // Noop, we already have a cube + } + else { + // The neighbour doesn't yet exist, we should create it + // but we don't want to do that while iterating over + // the current entries. + // We also want to make sure that we're not adding a + // value that's already in the list to be added. + // For the moment, we'll check that when iterating + // over neighbours_to_add. + try neighbours_to_add.append(n_pos); + } + } + } + // Add any new neighbours + for (neighbours_to_add.items) |new_pos| { + // Double-check we don't already have this neighbour + if (self.map.get(new_pos)) |v| { + continue; + } + else { + try self.map.putNoClobber(new_pos, Cube {.pos = new_pos, .state = .inactive}); + } + } + + self.calculate_neighbour_states(); + try self.print_state_neighbour_count(); + + // Now next state should be set, we go through again to swap + // @TODO Update state + it = self.map.iterator(); + while (it.next()) |entry| { + if (entry.value.state == .active) { + if (entry.value.neighbours >= 2 and entry.value.neighbours <= 3) { + entry.value.state = .active; + } + else { + entry.value.state = .inactive; + } + } + else { + if (entry.value.neighbours == 3) { + entry.value.state = .active; + } + } + entry.value.next_state = null; + } + } + +pub fn calculate_neighbour_states(self: *Simulation) void { + var it = self.map.iterator(); + while (it.next()) |entry| { + var neighbours = entry.value.get_neighbour_positions(); + var n_active : u64 = 0; + std.log.warn("Checking neighbours for ({}, {}, {})", + .{entry.value.pos[0], entry.value.pos[1], entry.value.pos[2]}); + for (neighbours) |n_pos| { + if (self.map.get(n_pos)) |n| { + if (n.state == .active) { + std.log.warn("Neighbour at ({}, {}, {}) is active", + .{n.pos[0], n.pos[1], n.pos[2]}); + n_active += 1; + } + } + else { + // Noop, another function creates our neighbours, and it should + // be run before this one. + } + } + entry.value.neighbours = n_active; + } +} + + pub fn count_active_cubes(self: *Simulation) u64 { + var it = self.map.iterator(); + var count : u64 = 0; + while (it.next()) |entry| { + if (entry.value.state == .active) { + count += 1; + } + } + return count; + } +}; + +// Part 2, is just more tedious +const Cube4D = struct { + pos: [4]i64, + state: CubeState = .inactive, + neighbours: u64 = 0, + + pub fn get_neighbour_positions(self: *Cube4D, a: *std.mem.Allocator) [80][4]i64 { + var neighbours : [80][4]i64 = undefined; + var x = self.pos[0]-1; + var idx : usize = 0; + while (x <= self.pos[0]+1) : (x += 1) { + var y = self.pos[1]-1; + while (y <= self.pos[1]+1) : (y +=1) { + var z = self.pos[2]-1; + while (z <= self.pos[2]+1) : (z +=1) { + var w = self.pos[3]-1; + while (w <= self.pos[3]+1) : (w+=1) { + if (x == self.pos[0] and y == self.pos[1] and z == self.pos[2] + and w == self.pos[3]) { + continue; + } + neighbours[idx] = [_]i64{x, y, z, w}; + idx += 1; + } + } + } + } + return neighbours; + } +}; + + +const Simulation4D = struct { + map: std.hash_map.AutoHashMap([4]i64, Cube4D), + allocator: *std.mem.Allocator, + + pub fn init(allocator: *std.mem.Allocator) !*Simulation4D { + var self = try allocator.create(Simulation4D); + errdefer allocator.destroy(self); + + self.* = Simulation4D { + .map = std.hash_map.AutoHashMap([4]i64, Cube4D).init(allocator), + .allocator = allocator, + }; + return self; + } + + pub fn deinit(self: *Simulation4D) void { + self.map.deinit(); + self.allocator.destroy(self); + } + + pub fn add_cube(self: *Simulation4D, pos: [4]i64, state: CubeState) !void { + try self.map.put(pos, Cube4D {.pos = pos, .state = state}); + } + + // pub fn print_state(self: *Simulation) !void { + // // @TODO Organize the output somehow + // var stdout = std.io.getStdOut().writer(); + // var z_min : i64 = std.math.maxInt(i64); + // var z_max : i64 = std.math.minInt(i64); + // var y_min : i64 = std.math.maxInt(i64); + // var y_max : i64 = std.math.minInt(i64); + // var x_min : i64 = std.math.maxInt(i64); + // var x_max : i64 = std.math.minInt(i64); + + // var it = self.map.iterator(); + // while (it.next()) |entry| { + // //try entry.value.print_state(); + // x_max = std.math.max(x_max, entry.value.pos[0]); + // x_min = std.math.min(x_min, entry.value.pos[0]); + // y_max = std.math.max(y_max, entry.value.pos[1]); + // y_min = std.math.min(y_min, entry.value.pos[1]); + // z_max = std.math.max(z_max, entry.value.pos[2]); + // z_min = std.math.min(z_min, entry.value.pos[2]); + // } + + // // For from lowest to highest then + // var z_pos = z_min; + // while (z_pos <= z_max) : (z_pos += 1) { + // try stdout.print("z={} x=[{}..{}],y=[{}..{}]\n", .{z_pos, x_min, x_max, y_min, y_max}); + // var y_pos = y_min; + // while (y_pos <= y_max) : (y_pos += 1) { + // var x_pos = x_min; + // while (x_pos <= x_max) : (x_pos += 1) { + // //try stdout.print("({}, {}, {})\n", .{x_pos, y_pos, z_pos}); + // var c : u8 = '.'; + // if (self.map.get([_]i64{x_pos, y_pos, z_pos})) |cube| { + // if (cube.state == .active) { + // c = '#'; + // } + // } + // try stdout.print("{c}", .{c}); + // } + // _ = try stdout.write("\n"); + // } + // _ = try stdout.write("\n"); + // } + // _ = try stdout.write("\n"); + + // } + + // pub fn print_state_neighbour_count (self: *Simulation) !void { + // // @TODO Organize the output somehow + // var stdout = std.io.getStdOut().writer(); + // var z_min : i64 = std.math.maxInt(i64); + // var z_max : i64 = std.math.minInt(i64); + // var y_min : i64 = std.math.maxInt(i64); + // var y_max : i64 = std.math.minInt(i64); + // var x_min : i64 = std.math.maxInt(i64); + // var x_max : i64 = std.math.minInt(i64); + + // var it = self.map.iterator(); + // while (it.next()) |entry| { + // //try entry.value.print_state(); + // x_max = std.math.max(x_max, entry.value.pos[0]); + // x_min = std.math.min(x_min, entry.value.pos[0]); + // y_max = std.math.max(y_max, entry.value.pos[1]); + // y_min = std.math.min(y_min, entry.value.pos[1]); + // z_max = std.math.max(z_max, entry.value.pos[2]); + // z_min = std.math.min(z_min, entry.value.pos[2]); + // } + + // // For from lowest to highest then + // var z_pos = z_min; + // while (z_pos <= z_max) : (z_pos += 1) { + // try stdout.print("z={} x=[{}..{}],y=[{}..{}]\n", .{z_pos, x_min, x_max, y_min, y_max}); + // var y_pos = y_min; + // while (y_pos <= y_max) : (y_pos += 1) { + // var x_pos = x_min; + // while (x_pos <= x_max) : (x_pos += 1) { + // //try stdout.print("({}, {}, {})\n", .{x_pos, y_pos, z_pos}); + // var c : u64 = 0; + // if (self.map.get([_]i64{x_pos, y_pos, z_pos})) |cube| { + // c = cube.neighbours; + // } + // try stdout.print("{:02}", .{c}); + // } + // _ = try stdout.write("\n"); + // } + // _ = try stdout.write("\n"); + // } + // _ = try stdout.write("\n"); + + // } + + pub fn do_round(self: *Simulation4D) !void { + // For each cube, check all of it's neighbours + var it = self.map.iterator(); + var neighbours_to_add = std.ArrayList([4]i64).init(self.allocator); + defer neighbours_to_add.deinit(); + + // Get the neighbours we need possibly create for this round + while (it.next()) |entry| { + var neighbours = entry.value.get_neighbour_positions(self.allocator); + //defer self.allocator.free(neighbours); + var n_active : u64 = 0; + for (neighbours) |n_pos| { + if (self.map.get(n_pos)) |n| { + // Noop, we already have a cube + } + else { + // The neighbour doesn't yet exist, we should create it + // but we don't want to do that while iterating over + // the current entries. + // We also want to make sure that we're not adding a + // value that's already in the list to be added. + // For the moment, we'll check that when iterating + // over neighbours_to_add. + try neighbours_to_add.append(n_pos); + } + } + } + // Add any new neighbours + for (neighbours_to_add.items) |new_pos| { + // Double-check we don't already have this neighbour + if (self.map.get(new_pos)) |v| { + continue; + } + else { + try self.map.putNoClobber(new_pos, Cube4D {.pos = new_pos, .state = .inactive}); + } + } + + self.calculate_neighbour_states(); + + // Now next state should be set, we go through again to swap + // @TODO Update state + it = self.map.iterator(); + while (it.next()) |entry| { + if (entry.value.state == .active) { + if (entry.value.neighbours >= 2 and entry.value.neighbours <= 3) { + entry.value.state = .active; + } + else { + entry.value.state = .inactive; + } + } + else { + if (entry.value.neighbours == 3) { + entry.value.state = .active; + } + } + } + } + + pub fn calculate_neighbour_states(self: *Simulation4D) void { + var it = self.map.iterator(); + while (it.next()) |entry| { + var neighbours = entry.value.get_neighbour_positions(self.allocator); + //defer self.allocator.free(neighbours); + var n_active : u64 = 0; + //std.log.warn("Checking neighbours for ({}, {}, {})", + // .{entry.value.pos[0], entry.value.pos[1], entry.value.pos[2]}); + for (neighbours) |n_pos| { + if (self.map.get(n_pos)) |n| { + if (n.state == .active) { + //std.log.warn("Neighbour at ({}, {}, {}) is active", + // .{n.pos[0], n.pos[1], n.pos[2]}); + n_active += 1; + } + } + else { + // Noop, another function creates our neighbours, and it should + // be run before this one. + } + } + entry.value.neighbours = n_active; + } + } + + pub fn count_active_cubes(self: *Simulation4D) u64 { + var it = self.map.iterator(); + var count : u64 = 0; + while (it.next()) |entry| { + if (entry.value.state == .active) { + count += 1; + } + } + return count; + } +}; + +test "get_neighbour_positions" { + var cube = Cube{ + .pos = [_]i64{0, 0, 0}, + }; + var neighbours = cube.get_neighbour_positions(); + for (neighbours) |n| { + std.log.warn("({}, {}, {})", .{n[0], n[1], n[2]}); + } +} + +test "small_cubeway" { + var sim = try Simulation.init(std.testing.allocator); + defer sim.deinit(); + try sim.add_cube([_]i64 {0, 0, 0}, .inactive); + try sim.add_cube([_]i64 {1, 0, 0}, .active); + try sim.add_cube([_]i64 {2, 0, 0}, .inactive); + + try sim.add_cube([_]i64 {0, 1, 0}, .inactive); + try sim.add_cube([_]i64 {1, 1, 0}, .inactive); + try sim.add_cube([_]i64 {2, 1, 0}, .active); + + try sim.add_cube([_]i64 {0, 2, 0}, .active); + try sim.add_cube([_]i64 {1, 2, 0}, .active); + try sim.add_cube([_]i64 {2, 2, 0}, .active); + + try sim.print_state(); + sim.calculate_neighbour_states(); + try sim.print_state_neighbour_count(); + std.testing.expectEqual(@as(u64, 5), sim.count_active_cubes()); + + std.log.warn("\n\n --- First round --- \n", .{}); + try sim.do_round(); // 1 + try sim.print_state(); + std.testing.expectEqual(@as(u64, 11), sim.count_active_cubes()); + + try sim.do_round(); // 2 + try sim.do_round(); // 3 + try sim.do_round(); // 4 + try sim.do_round(); // 5 + try sim.do_round(); // 6 + + var active = sim.count_active_cubes(); + std.testing.expectEqual(@as(u64, 112), active); +} + +test "4d_cubeway" { + var sim = try Simulation4D.init(std.testing.allocator); + defer sim.deinit(); + try sim.add_cube([_]i64 {0, 0, 0, 0}, .inactive); + try sim.add_cube([_]i64 {1, 0, 0, 0}, .active); + try sim.add_cube([_]i64 {2, 0, 0, 0}, .inactive); + + try sim.add_cube([_]i64 {0, 1, 0, 0}, .inactive); + try sim.add_cube([_]i64 {1, 1, 0, 0}, .inactive); + try sim.add_cube([_]i64 {2, 1, 0, 0}, .active); + + try sim.add_cube([_]i64 {0, 2, 0, 0}, .active); + try sim.add_cube([_]i64 {1, 2, 0, 0}, .active); + try sim.add_cube([_]i64 {2, 2, 0, 0}, .active); + + try sim.do_round(); // 1 + try sim.do_round(); // 2 + try sim.do_round(); // 3 + try sim.do_round(); // 4 + try sim.do_round(); // 5 + try sim.do_round(); // 6 + + var active = sim.count_active_cubes(); + std.testing.expectEqual(@as(u64, 848), active); +} diff --git a/day18/build.zig b/day18/build.zig new file mode 100644 index 0000000..b4d3d4f --- /dev/null +++ b/day18/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day18", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day18/input b/day18/input new file mode 100644 index 0000000..da39d13 --- /dev/null +++ b/day18/input @@ -0,0 +1,381 @@ +(7 * (7 * 6 * 4 + 3)) * 3 + ((8 + 5 * 3 + 7 + 8) + 3 * (2 + 9 * 5 + 7 * 5 * 6) * 2 + 3 * 9) + (4 + 5 + 5 * 2 + 2) + ((5 + 6 + 9 + 6) + 3 + 4 * 6 * 5) +7 * 5 +(9 * (9 + 7) * 7 + (4 + 5 * 5 + 2 + 3) + 3) * 7 * 5 + 8 + (4 + (7 + 9 + 6 * 9) * 2) +((6 + 4) * 6 * (5 + 3) * 9 * (3 * 5 * 5 * 9 * 4 + 9) * 4) * 2 * 8 + 9 +7 * 7 + (9 + 2 * 9 + 9) +9 + (7 * 7 * 5 * 9 * 7) * 2 + 3 * 3 +5 * (5 * (8 * 4) * 7 + 8 + 7) * (5 * (4 * 3 * 5 + 2 * 5) + (6 * 6 * 7 * 2 + 2) + 4) + (5 + 4 * 7 + 5 * 9 + 9) * 2 +((7 + 3 + 8) + (2 + 6 * 4 * 5)) + 8 +8 * (6 * 7 + 3 * (8 * 5 * 2 * 4)) * (3 + (5 + 5 + 6) * (4 * 3 + 7 * 5 + 7) + (3 * 5 * 9 * 3)) + 8 +6 + 4 + 8 + 4 * ((3 + 5 * 8) + 7 * 7 * 8 * 7 * 2) +3 * (9 + 4) * (9 + 2 + 6 + 5) + 4 * (7 * 2) + 6 +4 * 6 + (8 + 3) + 7 +2 + (8 * (5 + 6 * 5) + 9 * 7 + (7 * 7)) + 5 + 5 +(8 + (5 * 7 * 3 + 6) + 8) * 8 + 6 +8 * 6 * 6 +8 * 6 + (9 + 4 * 5 * 3) * 9 * (4 * 2 + 6 + 7 + 4 * 8) +(5 * 9 * 8 * 9 * 6) * 8 +7 * 5 + ((2 * 7 * 5 + 2 + 6 + 3) * 9) * 5 + ((2 * 2 * 4 + 3) * 5) +(2 + 3 * 4 * (2 + 4 * 9 + 8) * 8) + 6 + 8 + 7 * 2 +3 + 7 + (3 * 4 * (8 * 6 + 8 * 8 * 2 + 9)) * 4 +9 * 9 + 9 + (3 * 7 * 9 * 4) +(7 * 7 + (2 * 5 * 8) * 4) * 9 + (9 + 4 * 8 * (9 + 3 * 5 * 4 * 7 * 4)) + 3 * 3 +7 + 6 + 3 * 8 * 4 * (9 * 4 * (5 + 7 * 2 * 8 + 7 * 8)) +(7 + 2) * 5 * 8 + 6 * 2 +9 + 4 + (5 + (7 * 7 * 9 + 5) + 6 * 5 + 2 * (4 * 7 * 7 + 8 * 5 * 5)) * 2 + 2 +8 + 2 * 2 * (2 + (2 + 7 + 7 * 7 * 3) + 7) +3 + 4 * (3 + 3 * 3 + 4) * 9 * 6 + 8 +((4 + 4 + 6) + (5 * 5 + 4 * 9 * 5) + 5) + 2 * 2 +9 * 5 * 6 * 2 + 6 + (2 * 9 + (2 * 3 + 4)) +(3 * 9) + 2 * (2 * 5 + 7 + 9 * 7 * 6) + 5 * 5 * 2 +7 + 3 + 5 * 6 +7 + 5 + (2 * 8 + (6 * 6) + 6) + (4 + 7) +2 * (9 + 5 * 3 + 5 + 5 + 4) * (3 + 4 + 3 + 5 + 2 + 7) + 2 * 2 +(4 * 5 + 6 * 3 + (5 * 3)) * 5 + 5 +9 + 8 + 7 * (7 + 9 + 2 * 2 + 7) * 7 +3 * 3 * ((4 + 3 * 4 * 2 * 2 * 6) * (9 + 6) * 3) * 5 +9 + 6 + 7 + 6 +8 * (4 * 8 * 8 * 7 + 4 + 9) +2 + (7 * 9 * 2) + 6 * 6 * 4 * 6 +((4 * 6 + 7 + 9 * 4) + 9) * 4 * ((6 * 3 + 3 + 9 * 7) * 8 * 4 * 5 * (2 * 6 * 8 * 5 + 5 * 3)) * 7 +(4 * 7) + 5 +6 + 9 * 6 + 9 + ((5 + 7 * 5 * 8) + 7 + 7 + 8 * (2 + 8 * 2 * 4 * 7 + 9) * 7) +6 + 3 + (9 + 6 * (4 + 7 + 4 * 6 * 7)) + 6 +5 * 7 * (4 * 6 * (3 + 8 + 6 * 8)) + 8 +(5 * 6) * 8 + 2 * 3 + (7 + 4 + 3) +3 + 4 * 9 * 2 + (7 + (5 * 9 * 7 + 7 * 4) * 4) + 3 +2 * 9 + ((3 + 5 + 2 + 9 * 9 + 6) + 4 + (6 * 4) + 2) + 3 +3 + 6 + (3 + 6 + 8 + 2 + 2) +8 * ((8 * 6) + (7 + 2 * 2 * 2 + 4 * 3) * (9 + 8 + 4 * 8) + 8 * 4) + 2 +9 + 4 * (7 * (2 * 4 + 9 * 3 + 7) * 8 + (4 * 3 * 9 + 9 * 5 + 7) + 9 * (6 * 4 * 2)) + ((5 + 6 + 7 * 9 * 6 + 6) + (6 * 2 + 8 + 9 + 4 + 4) + (8 * 5 * 2 + 6 + 7) * 5 + 3) * 9 * 8 +9 + 2 + (5 + 3 * 2 * (7 + 4 * 5 * 5 + 3 * 7) * 8 * (5 * 6)) +7 * (3 + 3 + 7 * 7 * 9) + (2 + 5 * 6 * 4) +9 + 8 + 9 +8 * (7 + (5 * 7) + (7 + 3) * 2 + 7) + 4 * 3 +2 * (2 * 6 + 5 * 7) * 2 + (3 + 3) * ((2 * 3 + 2) + (5 * 3 * 4 + 8 * 2)) +4 * (3 + 7 + 6 + 8 + 3 + 6) + 8 + (2 * 3 * (5 * 2 + 6 + 5 * 8)) +2 + 5 + 3 + 2 + 4 + (2 + (6 + 4) + 5) +2 * (4 * 4) + (5 + 2 * (4 + 2 * 2 + 4) * 4 + (5 * 9 * 9) + 2) +(6 + 9 + (3 + 5 * 3) + 4 * 2 * 2) + 7 + ((6 * 6 + 4 * 5 * 5 + 4) + 5) + ((8 + 4 + 9 * 8 * 9 + 2) + (7 + 2 + 9) + 4) + 5 +7 * 3 + (6 + (8 * 5) * 6 * 8) * 2 * 9 * 4 +9 + 9 + 9 + 2 +(7 * 9 * 2 + 8 * 7 * 4) + 9 + (9 * 6 * 9 + 7) * 3 * (9 * 5 * 5) +4 * 7 * ((7 + 9 * 5 * 4 + 7 * 4) + (2 + 3 + 5 * 4 + 2) + (2 + 5 * 8 * 5 * 5 + 6)) * 6 +5 + 8 * (9 + (9 + 3 + 9 + 5 + 5)) +(3 * 7 * 2 * 3 + (8 + 8 + 3 * 9)) + 8 + 8 * 6 + 8 + 6 +9 + 4 + 8 * (7 * 8 + 8 + 4 * 8) +2 * 9 + 2 * (5 + 3) * 2 * (5 * 5 * 8 + (3 + 4 + 4 + 5) + 4 * 4) +5 * 7 + 2 * ((2 * 8 * 8 + 8 * 2 * 7) * 6 * 7 + 7 + 2) * 2 + 9 +4 * (6 * (6 * 3 * 3)) * (7 * 5 * 4 * 2 * (5 + 5 + 8 * 3)) + 7 + 7 * 8 +3 * 2 + 4 +9 + 6 * 2 * 4 + 2 +((5 * 5 + 3 + 7 * 2) * 2 * 5 + (9 + 9)) + 3 + 6 * (9 + 8) * 8 * 9 +4 * (8 + 2 + 3 * 9 * 6) * 6 * 3 +2 * (9 * 6 + (8 + 6 * 4) * (5 * 5) + 9 * 2) +6 + (3 * (6 * 6 + 4 + 5) + 3 * 5 * 4 + (6 + 9 + 4 * 5 * 3)) + 6 * (3 + (6 + 5 + 5 + 6) * 8 + 8 * 4) * 4 + 6 +9 * 9 * 2 + (6 * 4 * 2 + 4 * 7 * 9) * 7 + ((5 + 6 + 7 + 7) * (7 * 3 + 9) + 9) +(2 + (6 + 8 + 6 * 5 + 5) + 8 * 5) * 9 + 3 +2 * 9 + 2 + (9 * (4 + 6 + 4 + 2) * 9 * 5 + 7 + 2) +8 + 6 + 4 + 6 +3 + ((6 * 4 + 2 + 4 + 3 + 8) * (4 * 3) * (9 + 4 * 6 + 2 * 7 * 6)) + 5 + 7 +3 * (8 * 4 + 9 + 4) * 7 * 2 + ((5 + 9 * 6 * 4 * 4) * 8 * 4 * (6 + 2)) +((8 * 7 + 6) * 3 + 2 + 5) + 8 * 5 * 8 +(3 * 2 * 6 * 3 * 2) * 6 * 2 * 9 +(4 * 8 * 3 + 5) + (8 + 9) + 7 * 7 + 3 * 3 +(2 + 7 * (7 * 8)) + 8 + (6 * (4 * 8) * 4 * 2 * 8) * 4 * ((7 + 8 + 4 + 3 + 6) * 4 + 9 + 4) + 3 +((7 + 2 + 3 * 3) * 5 * 5 + 4) + 9 * 2 + 7 + 9 + 2 +(6 + (2 + 7)) * 4 + 7 + 8 * 5 +(9 * 8) + (8 + (2 + 4 + 5 + 6 * 9) + 2 * (8 + 9)) +2 * (9 + 8) * 8 * ((7 * 6 + 7 * 3) + 2 + 5 * (7 * 2 + 7 + 8) + 3 * 3) + 8 +4 * 6 + 6 + 4 * 9 +(2 + 4 + 5 + 3 + 6) + 3 * 3 * 3 + (5 * 2 * 9 + 6 * 6 + 5) +7 * 5 + (6 + 2 * 2 * 8 + 5) * 6 + 6 +(5 + 8 + 2) + 3 +3 + 3 * 5 * ((3 + 8 + 5 + 9) * 4 + 4 * 4 + 4) + 8 * 3 +2 + (5 + 5 + (6 * 5 * 2 * 8) * 4 + 8) +8 + (5 * 7 * 2 * 2) * (7 + 9 * 5) * 2 + 9 + 4 +((9 * 9) + 6 + 4 + 9) * 5 +5 + 3 * ((4 + 8) + 9 * 2 * 6 + 7) +6 + 7 + 5 * (2 + 9 * 4 * 5 * 7 + 5) + 9 * 4 +(7 * 2 + 4 + (8 * 8 + 2 * 5 * 3 * 6)) + (4 + 4 * 3 + 7) + 4 * 6 +2 * (5 * 9 * (5 + 3 * 5) * 5 + 6) + 4 + 5 +5 * (4 + 7 + 4) +9 * 7 + 8 + 4 + (6 * (6 * 2 * 4 + 9)) + 5 +6 * 3 +(5 * 6 + 2 * (2 + 5 * 6 * 4 + 9 + 2)) + (4 + 3 * (9 * 9 + 4 * 8 * 8 * 9) * 4) * (8 + 7 + (4 + 8 * 2 + 4) * 9) +8 * 5 + 9 +7 + 4 * 9 * 6 + 6 +9 + 6 * (8 * (7 * 6 + 2 + 4 + 6 + 9) * 2 + 2 + 2 + (7 + 7 + 9)) +6 * (7 * 6 * 6) * 9 * 6 + 7 +(5 * 7 + 9) * 7 + ((4 * 5 + 3) * 5 * (3 + 8 * 7) + 2 + 3 * (7 + 6 + 2)) + (3 * 5 * 5) + 2 +4 * 2 * 2 * 2 * (6 + 4 + 9 + 4 * 5) +((9 * 7 + 7) + 8 * 7) * 4 + (7 + 9 * 9) * 6 +8 * (6 * (8 + 4) + (5 + 6) * 6) * 7 + 4 * 7 * 2 +(7 + 7 * (8 * 5 + 4)) * 5 * (3 * 6 * 2 * 3 * 9) * 3 +4 + (7 * 5 * 3 * 5 + 3 * 5) * 7 +(6 + 5 + 6 * 3 * (6 * 4 + 6)) + 2 * 5 * 9 + 3 * 5 +3 * (6 + 3 + 5 * 3) + 6 * 3 + (7 + 8) * 9 +(3 + 8 + (5 * 4 + 4 + 7) + 5 * 2) + 2 + 5 + 6 * 9 + (4 + 2 + 6) +9 * 8 + (3 + (4 + 2 * 8 + 7 * 5 + 3) + (3 * 3) * 3 + (2 * 8)) +7 * 4 + (3 + 7 + 6 + 4 * (3 * 6) * 2) + ((5 + 5 * 5) + 6 + 2 * (2 * 3 * 3 + 3)) +9 * 5 * (6 + (2 * 3)) + (3 * 4 + 3 + 9 + 6) + (9 + 5 + 2 + (3 * 4 * 9 * 9 * 5) + 2 * 7) * 5 +(6 + 9 * 4 + 5 * 4 * (8 + 2 * 4 * 2 * 3)) + 4 * 9 + 6 * (4 * 5 * 9) +9 * 7 + (2 + (6 + 3) + (4 * 3 + 9) + 9) + 8 + 9 * 3 +3 * (8 + 7 + 7 + 8) * (5 + 5 + 2 + 6 + 9 + 7) +7 + (7 * 5 + 3 * 4 * 9 + 2) * (8 * 6 + (5 + 2) + 6) * 4 + (6 * 3) + 2 +(4 * 5 + 7 + 3 * (7 * 8) + 8) + 6 * 2 + 9 + 3 +7 * 4 * 8 * (7 + 5 + 2) + (8 * 8 * 2) + 3 +7 + 7 * (6 + (4 * 7 + 3 + 2 + 7) + 3) +2 + (8 + (5 + 9 + 2 * 6 * 6 + 8) * 8 + 2 * (5 * 2 + 8) * 4) + 2 * 6 +(4 * 9 * (7 * 6 * 9 + 8 * 6) * 9) * 2 * 2 +3 + (8 + 2 + (2 + 3 * 2) * 6 + (5 * 8 * 8 * 8 + 2 + 3)) * 4 * (9 + 3) * 6 +8 + 3 * (3 + 5) + 3 + 5 +4 + ((9 * 5 * 2 + 7 + 5) + 6 + 3 + 6 * (7 * 6) + 6) * 2 * 3 * (3 * 9 + 9) +((4 * 9) * 8 * 6) + 8 * 8 + 6 + ((6 + 4 + 7) * (2 + 2 * 4 * 9) + 3 + (5 * 9 + 9 * 9 + 5) + 2) +(8 * 4) + (8 + 8) +((4 + 5 + 2 * 4 * 7 + 3) * 6 * (4 * 6 + 8) * 9 * (9 + 7 + 5 + 3)) * 5 +8 * 2 + 8 + (7 * (8 + 2 + 6 * 7 + 9) + (5 + 9 + 3) + 6 * 6) * (8 + (4 * 2 + 4 + 7 * 5) + 2 * 6) * 5 +(2 * 5 + (8 * 7 + 9 + 2 + 2)) * 2 + (8 * (2 + 4) + 4 * 5 + 7) + 4 +4 + (2 + (4 * 3 * 9) * 5 * 4) +((3 + 4) * 7 + 6 + (5 * 3 * 8 + 8 * 9) * 3 + 6) + 8 * 4 * ((7 + 4 * 3) * (6 + 9 + 9 * 4 * 7) + 9 + 5 + 2 + (5 + 8 * 4 * 6 + 4 * 8)) +4 * (9 * 5 * (5 * 7 * 7 + 4)) * 5 * (5 * 7 + (4 * 5) * 4 + 9) +5 + (8 * 6 + 8) + 8 +7 + (8 + 6) * 4 + 2 +(3 * (9 + 6 * 8)) * 8 +3 + 6 + 4 + ((5 + 4 * 2) + 7) +7 * 3 + 5 * (2 * 5 + 4) * 8 +5 * 5 + (6 * (8 + 5) * 7) * 7 + 4 +7 + 9 + (2 + (3 + 8 + 4) + 9 * 2 + 6) * (7 + (3 + 6 * 8 + 8 * 7) + 9 * 3 * 8 + (9 * 6 + 2 + 8 + 4 * 4)) +6 * (2 * 8 + 3 + 5 + 5) + (3 + (8 * 2 * 3) * (2 + 9 * 8 * 5 + 3) + 4 + 7) * 7 + (5 * 5 + 7) +(2 * 2 * 6 * 4 * 9 + (9 * 5 + 7 * 4 + 6 * 2)) * 4 + (4 + (8 * 2 + 3 + 6)) +2 + (8 + 4 * 8 + 3) * 6 + 7 + 4 +(6 + 6 * (2 * 5 * 5 * 4 * 5 * 4) + 8 * 7 * 3) + 5 + (3 * 6 + 3 * 7) + 5 + 5 * 3 +2 * (8 + 2 + 6 * (9 * 9 * 9 + 4 * 2 * 7) * 3 * (4 + 6 * 3 + 8 + 4)) + 8 +(6 * 7 + 8 * 6 * 7 + (5 + 9 * 3 + 6 + 9 * 5)) + 2 * 6 +(7 + 2 * 4 + 3) + 4 * 5 + 3 +((7 * 7 + 2 + 7) + (3 + 3 + 5 + 9 * 3 + 2) * (2 * 4 * 7 + 6 * 3)) * (2 + (7 + 4 + 3 * 9 + 4 * 5) * 4 + 3 * (5 + 8 * 3)) + 5 + (2 + 8 * 2 * 8 * (6 * 7 + 4 + 5)) * (3 * (7 * 6 * 3 * 8)) + 7 +3 * 4 * ((8 + 8 + 9) * 6 + 6 + 7 + 6) + 8 + 3 +(6 + (7 * 4) + (9 + 6 + 3 * 9)) + 2 * (4 + 6 * 5 + (2 + 8) * 5 + 9) + 3 * (6 + 8 + 8 * (7 * 8 * 3 * 2 + 2 + 8)) +(9 + 8 * 4 + (5 * 8 + 7 * 2 * 8 * 9) * 8 + 9) * 3 +9 + ((5 * 3 + 6) + (8 + 6 * 6 + 7 + 2 + 8) * 8 + 5 + (9 + 8 + 2 * 9 + 2)) * 7 +((8 + 2 + 6 + 3) * 8 + 5 + 8 + 2) * 9 +(6 + (4 * 4 * 7 * 2 + 6) * 4 + 2 * 8 * (6 + 2 * 8)) * 2 * 8 +3 * (4 + 3 + 3 + (3 * 7 * 7)) + 6 + 7 + 4 + 8 +(6 * 8 + 7) * 8 * 9 + 8 + 4 +(7 * 7) * 2 + (8 * 7) + 4 * (5 * 2 * (3 + 4 + 7 * 8 * 3) * 9) + 6 +7 + (9 * (6 + 8 * 7 + 6 * 3) + 4) * 4 + 3 +6 + 3 * ((2 + 2 + 3 + 9 + 9 + 8) * 6 + 2) + 5 +3 * 6 * 6 + 2 + 2 + (2 * 2) +6 + (4 + 9 * (5 + 9 * 4 * 6 + 6) + 4 * 6 * (2 * 7 * 7 * 4 + 8)) + 5 +((2 + 6) + 2 + 5) + 7 + 3 + 5 * 3 + 5 +(6 * (2 + 8 + 7) + 4 * (2 + 8) * 9) + 9 * 6 +(2 * (9 * 4 * 3 * 2) + (4 + 4 * 3 + 2)) + 4 +(6 + 4 * (5 + 9)) + 7 * 7 * 8 * 5 * 3 +(3 + (5 + 4 * 3 + 9)) * 2 * (9 + 6 * 6 * (7 + 8 + 2 * 5) * 8 * 6) +8 + 6 * 6 +8 + (8 * 9) + 5 +8 + (7 * (6 + 8) * 7 * (5 * 7 * 8 * 7) + (8 + 4 + 6 * 9 + 8) + 4) + (6 * 4) * 3 * 7 +9 + 4 + 3 * 7 * 5 +(8 + 9) + 6 + 4 * 7 +5 * (4 * 6 + 4 + 2 * (5 * 2 * 2 * 8)) * 3 +3 * 3 + 2 + ((8 + 5 + 4 + 8 + 8) * 7 * 6 + 9 * 8) +9 + (8 + (8 + 9) + 7 + 8) +(8 + 2) + (2 + 5 + 7) + 6 * 6 * 6 * 6 +5 + 7 + (5 + 4 * (5 * 6 + 3 + 3) + (7 * 9 * 5 * 6 * 6 + 3) * 8) * 7 +6 + ((7 * 3) * 6 * 5 + 5 + (3 + 3 + 9)) + (6 * 2 + 6 + 9 + (2 + 4 * 3 * 4) + 7) +8 * 5 + (9 * 2 * 7 * 2 * 6 + 8) * 2 + 2 + 6 +6 * 8 +(2 * 3 + 5 + (8 + 6 * 8 * 7 * 2)) * 3 + 2 + 6 + 2 * 5 +(7 + 6 * (2 + 2 * 4 * 9 + 7 * 5) * 4 + 2) + 4 * (9 + 6) + (9 + 5) + 7 +5 * (3 + 7 + 7 * 4) +2 * ((2 * 7 * 8 * 4 * 3 + 7) + 6 + 3) * 5 * 7 +8 * 4 + 7 + (6 * 4 + 3 + 2) + 7 * 8 +7 * 9 + (2 * 9 * 2) * 6 +8 + (6 * (2 + 8) + 9) + (7 + 6 + 6 * (8 * 3 * 5 * 5 * 9) + 3 + 7) + 8 +2 + 5 * 4 + (4 * (3 + 7 * 5 + 8) * 8 + 2) + 3 * 7 +(8 * (9 * 7 + 9 + 9 + 4) * 3 + 2) * 8 +4 + (6 + (2 + 4 * 6) + 4) +(8 * (4 + 6 + 2 * 6 + 7)) * 9 + 8 + 3 * 5 +((2 * 7 + 3 * 5) * (5 + 7 + 7 + 3 * 7 * 3) * 8) * 2 * ((2 * 9 * 4 * 6 + 4) + 6 + (8 * 5 * 4 * 5 * 6 * 8) + 7 * (9 * 6 + 7 * 3 + 4 + 7)) + 9 +6 + 8 + (3 * 3 + 2) + 5 + 4 +5 * 6 + 6 * 5 * ((3 + 5 * 8 + 4 * 8) * 9 * 9 + 6 * 4 + 6) + (4 * 7 * 5 + 9 + 7) +2 * 7 * (4 * 7 + (4 + 7 + 4 + 3 * 2 + 7) + 7) +((8 + 3 * 6 * 6 + 4) + (9 + 5 + 3 * 3) + 7 * (3 * 4 + 4 + 9 * 4 + 6) + (8 + 5 + 2 * 2 * 5)) * 8 * 6 * 7 + ((5 + 6 + 2 * 4 + 2) * (9 + 8 + 9) + 6 + (6 * 5 * 9 + 7) * 4 * 6) * 7 +4 * 5 * (9 * 3) + (9 + 6 + 5 * 8) +3 * 8 +9 + 2 * (7 + (2 + 9) * 9) + 4 * 4 * 8 +(8 + 4 + 7 * 2 + 8 * (8 + 7 * 4 + 4)) + 4 +4 + 8 + ((7 * 9 + 9) + 3 + 2 + 3) * 8 +(6 + (4 + 3 + 8 + 6 * 8)) * (5 + 9 * (5 + 2 * 7 + 8) + (6 * 7 * 4 + 2 * 5) + 4 * 9) * 8 * 5 +8 + 3 + 4 * 9 * ((4 * 9 + 3 + 6) + 3 * 3 + 9) * 2 +6 + ((3 * 2) * (4 + 9 + 9 * 5 * 2) * (2 * 8 + 4 * 7 + 4 + 8)) * 5 + (9 * 4 * 6 + 6 * 4 + 8) +2 + (5 + 4 * 8) + (9 * 9) +8 * 3 + 7 * 3 + ((2 * 2 + 6 * 3) * 3 * 7 * 8 + 5) + 9 +4 * 7 + ((6 + 7 * 3 * 4 + 8) * 2 + 6 + (4 * 6 + 9 + 6 * 8 * 3) + 3 * 3) + 3 +5 * (9 * 9 + (7 + 6 + 2 + 9 + 9 + 9)) * 8 +5 + 4 * 2 + 7 * (5 * 5 + 2 + 3) +2 * 2 + 6 + ((2 + 2 + 5) * 6 * (2 + 7 + 3 * 9) * 5 + 9 * 8) +((2 * 4 + 7) + 9 * 8) + 5 * 6 * 2 + 9 +6 + ((7 * 9 * 9 + 2) * 2) +6 * (7 + (4 + 7 * 2) * 5 + 2 + 7) + 6 * 7 + 5 +8 * (6 * 8 + (7 + 2 + 7) + 3) + 7 + 6 +(7 * 2 * 3 * 7) + 4 * 3 + 6 * 9 + 7 +8 * 7 * (8 * 9 * 3) +9 + (9 * 4 * (9 + 3 * 5 + 9 + 9) * 8 + 5 + 9) +6 * (9 * 2 * 9 + 6 + 9 + 8) + (6 * 9 * 5) + 2 * 4 +2 * 5 * (7 + 8 + 3 + 8 + 6 * 4) * 4 + 5 +2 * 2 * (4 + 3) + 2 + 4 * 4 +(6 * (9 * 6 + 2 * 2) * 4 * 3 * 4 * 7) + 2 +(2 * 5) * 3 + 3 * 3 * 7 * 8 +3 + 6 + ((6 * 6) * (9 + 8 * 2) * 7 + 5 + 9 * 2) +9 + 7 + (2 * 8) +(8 * 7) + (8 + 6 * 7 + (3 * 9 + 6) * 6 + 8) + (4 * 2 * 9) +2 + 2 + 2 + 9 * ((4 + 5 * 7 * 5 * 4 * 7) * (9 + 9) + 4 * 4 + 9) * 8 +4 + 2 + ((6 + 8 * 4 + 7) * 7 + 3 * 9 + (9 + 5)) +7 + 8 * (3 * (3 + 9 + 6 * 5) + 6 * 8) * 7 + 4 +8 + 7 * (2 * (5 * 7)) + (4 * 3 + 7) +(2 + 8 * 7) + ((8 * 9 * 3 + 3 + 5 * 7) * 2 * (9 + 6 * 3 * 5) * 4 * (4 + 6 * 6 + 4 * 9) * 3) * 6 + 4 * 4 + 2 +3 * (9 + 4 + (9 + 5 + 8 + 6 * 3 * 4) * 8 + (9 * 3 + 8 + 4 + 7)) * 8 +(4 + 4 * (4 * 7)) * 2 + 7 * 3 +((4 * 9) * (9 + 6 + 9 * 8 + 7)) + 6 + 7 + 7 +6 + ((9 * 5 + 9 + 6 * 6 + 4) * 7 + (9 + 5 + 5) * 9 + 3) * (5 * 9) + 8 + 9 +(3 + 8 * (7 * 3 * 4)) * (6 * (6 + 4) + (9 + 8) * (2 * 5 + 4) + (8 + 5 * 6 + 5 * 2 + 2)) * 6 + 9 + (7 + 6 * 5) + (5 + 4 + (6 + 8 * 2) * 2) +4 * ((6 * 8 + 7 * 6 + 4) + 4) +((5 * 6) + 4) + (9 + 4 + 9) + 2 +5 * 9 * 7 * 6 + (9 * 7) +5 + (2 + 7) * 5 + 9 + 7 +6 * 2 * 8 + 4 +(3 + 2 * 4 + 8) + ((7 * 5 + 7 * 2 * 8) + 7 + 2) * 6 * 2 + 5 +(2 * 5) * (3 * 9 * 4 * 8 + 5 * 3) * ((9 + 5 * 6 * 3) + 3 * 7 + 4) * 5 +((3 + 6 * 3) * (4 + 9 * 5 * 6 + 4 * 7)) + ((8 * 7 * 2 + 7) + 5 * 6) * 6 + 7 +(8 + 4 * 8 * 8) * 9 * 9 + 7 + 4 +(7 * 9 + 5) * 5 + (9 + 4 + 4 + (7 * 9 * 2 * 8 * 2 + 9)) * ((7 * 5 * 7 * 3 * 7) * 5 * 2) + 8 +5 + (6 * (8 + 9) * 7 + 9) + 3 + 3 +8 + 8 * (6 * 5 * (3 + 5 + 9 * 2 * 9 * 7)) +5 * (4 + 7) * 5 + 7 + 8 + 6 +3 * ((5 + 6 + 2 + 7) * 4 * 6) * 5 * 5 +(6 + 3 * (9 * 9 * 7 * 8 * 9 + 9) + 5) * 8 * 6 + 7 + 2 +8 * (4 + 3 * 5 + (5 + 2 * 3 + 8) * 2 + (8 + 7 * 7 + 4 * 7 + 7)) + 8 * 6 + 4 * 5 +4 + 7 * 8 * (2 + 6 + 5) * (4 + 8 + 4) +9 + 8 * ((2 * 3 * 6 + 4 * 2) + (6 * 5 * 9 + 7) * 5 * 2 * 9 * 7) + (9 + 4 * (2 * 8 * 7) * 3 + (9 + 8)) + 3 + 6 +7 * 3 * 8 + ((6 + 7) * 9) * 2 +5 + 3 +4 + 9 * 7 * ((7 * 8 + 7 * 2 + 5 * 7) + 5 * 4) + (5 * 5 + (7 * 6) * 6) +((2 + 4) * 5) * 3 + 5 +5 + (2 + 8 * 9 * 6 * 2 * (2 + 8 + 3 + 5)) * 9 * 8 + 3 * (9 + (4 + 2 + 4 + 7 * 4) * 9 * 9 + 7) +2 + 6 * 9 + 3 + (7 + 8 + 2) * 4 +5 * 4 * (2 * 4 + 3 + 3 * (9 + 6 + 6) + (3 * 8 * 4)) * 4 * 3 + (9 * 7) +7 * (5 * 5 + 4 + 8 + (3 * 4 + 6 + 9)) * 2 * 9 * (6 + 7) +2 + (5 + 3 * 5 * 8) + 3 * 8 + (9 + 9 * 8 * 2 * 2) +((7 + 9 * 9) * 7 * 2) + 6 * 6 * 9 +(6 * (9 + 9 + 4 + 5 + 6 + 2) + 6 + 8 + (7 * 3 * 8)) + 2 + 6 + 2 +(3 + (6 * 2 + 2 + 6 * 7 + 8) * 9 * 2) * ((2 + 9) + 8 * 9 + 2) + 3 * (3 + 4 * 7 * (3 + 2 * 8 * 6 + 7) * (5 + 3)) * 5 +(9 * (9 * 9 + 7 * 4) + (7 * 4 * 7 * 5) * (9 * 2 + 8 + 5 * 6)) * (6 * (7 + 9 + 6 * 7 + 9) + 4 * 4 * 2 + 6) * 9 +4 + (3 + (4 + 5)) + 7 * (6 + 4 * (5 + 3 + 9 + 5 + 2) * 4 + 4) + 8 + 8 +((5 + 8) + 5) * 9 + 6 + 8 * 7 +8 * (5 + (3 * 3 + 6 * 3)) * 5 + 2 + 8 * 8 +6 * 2 * 9 * (8 * 7 * (2 * 4 + 6 + 7 + 4 * 5)) + 9 + 7 +(5 * 3 * (8 * 2 * 8 + 2 + 8) * (8 + 8 + 9 * 7 * 6 * 3) + (4 * 2 * 7) * 4) + (4 * 3 + 9 * 5) + 5 + (5 + 9) +(6 + 3) * 5 + (6 + 7 + 5 + 7) +(9 * (6 + 6 * 8 + 4) * (3 * 6 + 6 + 7 + 7 + 5) + (5 * 7 + 4) * 9) * (7 + 3 + 7 * 2 + (5 + 7 * 6 + 8) * 4) * 7 +6 + 8 * (5 * 5 + (3 * 2 * 2 * 7 + 4 * 9) * 7 + 4) + 8 + 4 +9 + (5 * 7) * (5 * 6 * 8 * (5 * 2) + 9) * (6 + 3 + 6 + 9 + 2) * 6 +8 * (8 + 8 + 9 + 9 * 6 * 3) + 8 * (3 * 3) + 3 * 3 +7 * 7 * (5 + 5 * 9) + (6 * 6 * 3 * 4 * 8 + 8) + 3 +(3 * 2) + 5 * (6 * (9 + 2 + 3 + 2 * 9 + 5) + 6) + 2 + 7 * 9 +9 * 2 + 3 + (3 * 7) + 4 +7 * 5 * 7 * (4 + 3 * 7 + 3 + (4 * 5 + 5) + (5 * 8)) * (8 * 3 * (8 + 9)) +((3 * 8 * 8 + 6 + 5 * 5) + 3 + (3 * 8 * 7)) * 2 * (9 + (9 * 8) * 5) * 5 * 4 + 7 +4 * 9 * (4 + (3 * 7) + (6 * 4 * 9)) + 2 + 8 +5 * ((7 + 2 + 6 + 6) * 2 + 4 * 8) +5 + 9 * ((7 + 2) * 5 * 4 * (5 + 7) + (8 + 4 * 8 * 7 * 9)) +((4 + 3) + 6 * 3) * (4 * (4 * 6) * 3 * 2 + 8 * 4) + 8 +5 + (6 + 3 + 6 * 8 * 7 * 2) + 3 * 9 + (8 + 2 + 6 * (4 + 6 * 6 * 8 * 3 * 3)) + 7 +7 + (8 + 8 * (8 + 3 * 3 * 5 + 2)) + 4 + (2 + 3 * 7 * 7 + 6 + 2) * 9 +7 * 3 * 2 + 6 + 7 * 4 +(3 + 4 * 7 + (8 * 3 * 5 * 8 + 5 * 3) * (7 + 4 * 8 + 9)) + 8 + (4 * 3 * 4) * (6 + 4 + 8) + 5 + (9 + 6 + 2 + 4) +((3 + 9 + 5) * 7 * 2 * (3 + 7)) + 5 + 3 +(4 * 9 + 3 + 9) * 8 * 8 + ((7 * 2 + 6 * 2 * 2) + 8 * 3 * 2 + 2 + 6) * 3 + 7 +(5 * 6 * (8 + 8) + 2) + 6 + 2 * (5 + 4) + 2 +(3 * 8 + 2 + 5 + 6 + 6) + (8 + 7 + 9 * 4 * 4 + (4 * 4 + 4 * 7 + 7)) * 4 +(7 * 7 * 4) * 7 * 3 + 6 +(9 * 3 + 7) * 7 + 4 + 2 * 7 * 3 +6 * 9 + (6 * 6 + 6 * (3 * 9 + 7)) +5 + 6 * 7 + 8 + (3 * 3 + 5 + 3 + 6) + 8 +(6 + 4 + 6 * 9) + (3 * (6 * 3 * 2 + 2 + 9)) + (2 + 9 + 8 * 3 * 8 + 9) + 4 + (4 + 4 + 7) +4 + 3 * ((6 * 3 * 2) + 3 * 3 + (6 * 4 + 5 * 5 * 7) * 6 + 3) +2 + (7 * 5 * 6 + 8 + 4 * 8) * 3 * 6 * 3 +9 * (8 * (6 * 7 + 7) * 3 + 9) + 7 * 5 + 6 +((3 * 5) + 2 * 4 * 2) * 7 + (4 + (4 * 2 * 6) + 2) + (3 + 5 * 8 + 6) + (5 + 2 * 6) * 2 +8 + 9 * (4 + 6 + 9 + 2 + 4 + 6) * (9 + 4 * 5) * 2 +(6 + 9 + 4 + 7 * 7 + (6 + 5 + 4 * 6 + 4 * 5)) * 3 + 7 + (2 + 9 + 7 + 8 + 4 * 5) +(6 * 7 * (7 * 7 + 3 * 9 + 4 * 2) + 8 * 7) * 3 * 2 +(7 * (5 * 2 + 2 + 8 * 4 + 6)) + 7 + 7 * 8 * 7 + 2 +(8 * 6 * (4 + 6 * 8 * 8)) * 8 + 4 +(4 + 7) * (7 * 4 + 4 + 5 + (9 * 9 * 4 * 5) + 8) + 4 + (8 * 9 + 2 + 4 * (2 * 2 + 8) * (5 * 7 * 4 * 6 + 2)) + 6 +4 * (8 * (2 * 5) + 4 * (7 * 2 + 7 + 8) * 7) * 4 * 9 * 7 + ((5 * 4 * 5 + 7 + 9) + 7 * 7 + (6 * 3 + 8 + 7 * 4) + (6 + 4 * 3)) +((3 + 4 + 7 * 8 * 5) * 9 * 6) + 6 + 3 +((7 + 3 * 8) * (3 * 7 + 4 * 3) + 5 + 2 * 9) * 8 + 4 + 2 +((3 + 8 * 8 + 9) * 5 * (5 * 6 + 5 + 7)) + 2 * (6 * 5 + 4 * 6 * 4 * 8) * 9 * 7 +4 + 9 * 8 * ((8 * 6) + 7 * 2 + 2 * 6) +(2 * 3 * 3) + 4 * 8 * (3 * 5) +(8 * (5 + 9) + (5 * 6 * 7 * 2) + 4 + 4 + (6 * 9 + 8 + 7 + 2)) * 7 * 2 * 6 + 2 * 2 +(8 * 9 * 7 + 3 * 6) + 5 + 4 * ((9 + 8) + (3 + 7 + 6 * 2) + (7 * 5 * 9 + 5) * 8 * 3) + (6 + 9 * (6 * 8) + 2 + 4 * 4) +6 + 8 * 9 + (4 * (9 + 2 + 3 + 5 + 3 + 8) + (3 + 7 * 4) + 4 * 7 * (6 + 2)) +2 + 4 * 7 * 5 + (8 * 3) + 6 +9 + 9 + 4 + (4 * 3 + 3 * 2 + (7 + 2 + 9 + 8) + 4) +3 * 7 * 7 * 9 + 7 +(3 * 2 * 3 * 5 + 6) + 4 * 5 + 8 + 5 +7 * 6 + 7 * 8 + 8 * 3 +(6 + 2 + (6 * 8 * 5) * 6 + 3 * (8 * 5 * 9 * 2 * 7 + 4)) * 3 +(8 + (4 + 2 * 3 + 7 * 5) * 9) * 3 + 9 + 4 + 6 +(9 + 6 + (6 + 3 * 2 + 8 * 5 + 7) + (8 + 8 * 3 + 9 * 4 * 8) + 6 * 2) * (7 + 9 + 5 + 8) * 7 + 4 * ((6 * 5 * 7 + 7 * 9 * 3) + (2 * 4 + 4 * 2)) +(5 * (3 + 5 + 5 * 6) * 7) + 8 + 3 * 4 + 7 +3 * 7 * (9 * 5 + 9 + 7) + 9 * (3 * 4 * 4 * (8 * 4 + 2 + 5)) + (9 * (5 * 3 * 4 * 9) + 5 * 8 + 9 * 5) +6 + 7 + ((2 * 4 * 5 + 7) * 2 * (8 + 8 * 4 * 3) * 3) * 5 * 6 * 4 +7 * (9 * 6 * 4) + 7 + (8 * 2 * 7 * 4 + 8) +4 + 7 * (8 * 4 * 2 * (2 + 5 + 9 + 5 * 2 + 5) * (5 * 6 + 2 * 5 + 9) + 3) * 9 * (3 * 6 + 3 * (4 * 4 * 6 + 6 * 2 * 9)) + 8 +2 + 6 * (8 + 9 + 6 + 2 * (9 + 4 * 7 * 5 + 5)) * (7 * 7 * 2 * 9) +4 * 3 + (8 * (6 * 8 + 8 + 6) + 3) + 5 +(5 + 6) + (2 + 6 + 4 + 8) +(9 * 5 * 3 + 6 * 6) + (5 * 4) +3 * 2 + (7 + 7 * 2 + (6 + 6 + 2 * 8 * 4) * 3) * 8 +(4 * 6 + 6) + 4 * 9 +6 + (9 * 3 * 3 * 3) + 8 +(5 + (9 + 6 + 3 + 7 * 3 + 5)) + 5 + (4 * 3 + 4) * 9 * 3 +(6 + 8 * (8 + 3 * 2 + 4 + 5 + 9)) * 7 +6 + 3 * 3 * 5 + ((7 + 4 * 8) + 2 * 7 + 4 * (5 + 8) * 8) + ((5 * 4 * 2) * 4 * 5 + (3 + 4 + 4 * 7 + 7)) +2 * 3 * 3 * 4 * 7 + 2 +6 * (7 + 9 * 9 + (9 * 6) + 5) + 4 +8 * (2 * 7 + 5 * 5 + 8) + 5 +(4 * 5) + (3 + 3 * (5 * 9 + 8 * 2) + 6 * 4 + 4) * 5 + 6 +4 * 9 + (3 + 3 * 2 + (2 + 4 * 4 * 7 * 7 + 5) * 9) * 5 * 3 +(5 * 3 * 6 + 8 + 2 + 4) * 6 * 8 * ((6 * 2 + 2 * 4 + 6 * 2) * 6) +4 * (5 * 4 * 6 + (7 + 3 * 9 + 3)) + (3 * 4 + 4 + (5 + 7 * 6 * 2 + 7) + 3) +3 * (5 + 2 * 6 + 8 + 5) + ((8 + 3 * 6 + 8 * 3) * (7 * 7)) + 8 * 4 * 5 +4 + (8 + 6 * (4 + 3)) * 4 + 4 +4 * 3 * (3 + (8 * 9) * (9 * 7 * 4 * 9 * 4 * 8) * (5 + 2 + 2 + 2)) +8 + (2 + 2 * 5 * 3 * (4 * 3 + 7 + 6 + 3)) + 7 * 2 * 5 * 5 +4 * (7 * 9 * (2 * 2 * 5) + 2 + 8 * (6 + 2)) * 4 * 7 * 8 +(2 * 3 * 3 * 2 + (9 * 8 + 5 + 4)) + 7 * 2 * 6 +((6 * 7 + 3 + 3 * 4) * (5 + 9 + 5) + 7 * 6) + 9 +6 * 9 + 8 + 3 + 6 * (6 * 9 + 9 + 3 * 2 * 2) +(3 * 5 + 2 + 9) * (6 + 9 + (6 * 8 + 2 + 8 * 3 + 8) + (2 + 6 + 6 + 6 * 3)) * ((7 * 5 * 9) * 3 + 9 + 3 + 8 * 2) * 8 * 6 + 8 +3 * (4 + 4 + 6 * (5 + 7) * 8) * (3 * (6 * 7 + 3 + 7 + 7) + 7) +6 * 8 + 8 * (6 + 9 + 5) * 7 + 7 +3 * (8 + 5 + 8 * 7 * 7 * 8) + 7 + 9 * 4 + 9 +(4 + 5 + 7 + 6) * (9 * (6 * 3 + 9 + 3 + 3) + 6 * 8 + (2 * 8 * 4 + 7 + 5 * 4)) +7 * 2 + 3 * (5 + 9) + 7 * 3 +7 * 8 + 5 + 7 * 4 * ((7 * 4 + 8 * 8) * (6 + 5 * 8 + 7 + 5 * 3)) +(7 * 4 + 3) + (7 + 9 * 7 * 9 * (3 + 2 * 2 * 8 * 2 * 6)) + 5 * 3 + 3 + 3 +5 + 6 * (3 + 6) * (6 + (7 + 2) * 3 + (8 * 6 + 3 + 8 + 5 * 9)) * 7 +(9 + 6 + 8) + 3 + 5 + 2 + (3 * 9 + (8 + 3) + 7 * 3) +6 + (9 + 7 * 2 * (8 * 9 * 2 + 7 + 6 * 7) * 6) +2 + 4 * ((7 * 2 + 4) * 8) + 9 * 3 * 3 +3 + ((5 + 4) * 4 * 7 * (3 + 5 * 4 + 3) + 3) +(7 + 4 * 3 * 6 * 7 * 5) * 2 * 7 + 4 +(7 * (7 * 9) + 8 + 2 * (6 + 9 + 9 * 2 * 5) + 7) * 7 * 7 + 9 +(2 * 5 + 9 * 5) * 3 +3 * 9 + 5 + 7 * 9 + 6 +9 * 3 * ((3 * 6 + 4 + 8) + 9 + 2) * 3 +8 * 3 + 6 * 8 * 2 + 4 diff --git a/day18/src/main.zig b/day18/src/main.zig new file mode 100644 index 0000000..726d6e8 --- /dev/null +++ b/day18/src/main.zig @@ -0,0 +1,672 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var sum : i64 = 0; + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + defer gpa.free(contents); + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + var tree = try Tree.init(gpa); + defer tree.deinit(); + try tree.parse_line(line); + sum += tree.resolve(); + } + + std.log.info("Sum of all operations from input: {}", .{sum}); + + sum = 0; + it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + var tree = try Tree.init(gpa); + defer tree.deinit(); + try tree.parse_line_part2(line); + sum += tree.resolve(); + } + + std.log.info("Part2: Sum of all operations from input: {}", .{sum}); +} + +const Operation = enum { + addition, + multiplication, + unknown, +}; + +const TreeValueTag = enum { + value, + operation, +}; + +const TreeValue = union(TreeValueTag) { + value: i64, + operation: Operation, +}; + +/// Binary tree node +const TreeElement = struct { + parent: ?*TreeElement = null, + children: [2]?*TreeElement = [_]?*TreeElement {null, null}, + value: TreeValue, + + pub fn add_child(self: *TreeElement, c: *TreeElement) void { + //std.log.warn("Adding child {*} to {*}", .{c, self}); + for (self.children) |ch, k| { + //std.log.warn("{}: {*} ({})", .{k, ch, ch == null}); + if (ch == null) { + //std.log.warn("Set child {} of {*} to {*}", .{k, self, c}); + self.children[k] = c; + return; + } + } + // We're not meant to call add_child 3+ times on a TreeElement + unreachable; + } + + pub fn get_root_node(self: *TreeElement) *TreeElement { + var r = self; + while(r.parent) |p| { + r = p; + } + return r; + } + + pub fn print(self: *TreeElement, depth: u64) anyerror!void { + var _type = switch(@as(TreeValueTag, self.*.value)) { + .value => "value", + .operation => "operation" + }; + var i : u64 = 0; + var stdout = std.io.getStdOut().writer(); + while (i < depth) : (i += 1) { + try stdout.print(" ", .{}); + } + try stdout.print("{*} ({}) - {}\n", .{self, _type, self.value}); + for (self.children) |c, k| { + //std.log.warn("Child {} of {*} is {*}", .{k, self, c}); + if (c != null) { + try TreeElement.print(self.children[k].?, depth + 2); + //try self.children[k].?.print(depth + 2); + } + } + } + + pub fn resolve(self: *TreeElement) i64 { + if (@as(TreeValueTag, self.value) == TreeValueTag.value) { + return self.value.value; + } + else { + std.debug.assert(self.value.operation != .unknown); + var v : i64 = undefined; + var l = self.children[0].?.resolve(); + var r = self.children[1].?.resolve(); + if (self.value.operation == .addition) { + v = l + r; + std.log.warn("{} + {} = {}", .{l, r, v}); + } + else { + v = l * r; + std.log.warn("{} * {} = {}", .{l, r, v}); + } + return v; + } + } + + pub fn swap_child(self: *TreeElement, old: *TreeElement, new: *TreeElement) void { + for (self.children) |v, k| { + if (v == old) { + self.children[k] = new; + return; + } + } + // maybe we don't want to fail at swapping a child right now + unreachable; + } + pub fn nearest_operation(self: *TreeElement) ?*TreeElement { + var t : ?*TreeElement = self; + var r : ?*TreeElement = null; + while (t) |node| { + if (@as(TreeValueTag, node.value) == TreeValueTag.operation) { + r = node; + break; + } + else { + t = node.parent; + } + } + return r; + } + + pub fn nearest_unknown_parent(self: *TreeElement) ?*TreeElement { + var t : *TreeElement = self; + var r : ?*TreeElement = null; + while(t.parent) |p| { + if (@as(TreeValueTag, p.*.value) == TreeValueTag.value) { + t = p; + continue; + } + else { + r = p; + break; + } + } + return r; + } +}; + +const Tree = struct { + allocator: *std.mem.Allocator, + // we want constant pointers for the TreeElements, but + // maybe we can use this object to simplify keeping track + // of them + children: std.ArrayList(*TreeElement), + + pub fn init(a: *std.mem.Allocator) !*Tree { + var self = try a.create(Tree); + errdefer a.destroy(self); + self.* = Tree { + .allocator = a, + .children = std.ArrayList(*TreeElement).init(a), + }; + return self; + } + + pub fn deinit(self: *Tree) void { + for (self.children.items) |c| { + self.allocator.destroy(c); + } + self.children.deinit(); + self.allocator.destroy(self); + } + + pub fn resolve(self: *Tree) i64 { + std.debug.assert(self.children.items.len > 0); + var root = self.children.items[0].get_root_node(); + return root.resolve(); + } + + pub fn create_number_node(self: *Tree, buf: []const u8, previous: ?*TreeElement) !*TreeElement { + var t = try self.create_node(); + var last : *TreeElement = undefined; + t.* = .{ + .value = TreeValue { .value = try std.fmt.parseInt(i64, buf, 10) }, + }; + if (previous) |l| { + l.add_child(t); + t.parent = l; + last = l; + } + else { + last = t; + } + return last; + } + + pub fn parse_line(self: *Tree, line: []const u8) !void { + var last_node : ?*TreeElement = null; + var disjointed_nodes = std.ArrayList(*TreeElement).init(self.allocator); + defer disjointed_nodes.deinit(); + + var buf = std.mem.zeroes([16]u8); + var buf_pos : usize = 0; + for (line) |c, k| { + if (c == ' ') { + // Check buffer length, if not zero add the necessary tree node + if (buf_pos == 0) { + continue; + } + last_node = try self.create_number_node(buf[0..buf_pos], last_node); + // Reset buffer + std.mem.set(u8, buf[0..], 0); + buf_pos = 0; + continue; + } + if (std.ascii.isDigit(c)) { + buf[buf_pos] = c; + buf_pos += 1; + + // If we're at the end of the string, we need to run the stuff + // for adding a number node + if (k == line.len-1) { + last_node = try self.create_number_node(buf[0..buf_pos], last_node); + // Buffer reset unneccesary here + } + continue; + } + switch (c) { + '+' => { + std.debug.assert(last_node != null); + // If we have a last node, we should check up for + // an unknown parent. If an unknown parent exists, + // we should set the operation on that node, and + // set that node to the last_node. + // If we ourselves are unknown + if (@as(TreeValueTag, last_node.?.value) == .operation) { + if (last_node.?.value.operation == .unknown) { + last_node.?.value = TreeValue { .operation = .addition }; + continue; + } + } + else if (last_node.?.nearest_unknown_parent()) |unknown_parent| { + unknown_parent.value = TreeValue { .operation = .addition }; + last_node = unknown_parent; + continue; + } + // If there is no unknown parent, our last node could + // be an operation node or value node. + // When it's an operation node, this is probably an error? + var root = last_node.?.get_root_node(); + var t = try self.create_node(); + t.* = .{ + .value = TreeValue{ .operation = .addition}, + }; + root.parent = t; + t.add_child(root); + last_node = t; + continue; + }, + '*' => { + std.debug.assert(last_node != null); + // Same as '+' + if (@as(TreeValueTag, last_node.?.value) == .operation) { + if (last_node.?.value.operation == .unknown) { + last_node.?.value = TreeValue { .operation = .multiplication }; + continue; + } + } + else if (last_node.?.nearest_unknown_parent()) |unknown_parent| { + unknown_parent.value = TreeValue { .operation = .multiplication }; + last_node = unknown_parent; + continue; + } + var root = last_node.?.get_root_node(); + var t = try self.create_node(); + t.* = .{ + .value = TreeValue{ .operation = .multiplication}, + }; + root.parent = t; + t.add_child(root); + last_node = t; + continue; + }, + '(' => { + // We need to start a new disjointed tree. + // Create an operation node of an unknown type, + // and set that as the parent of the current last node, if + // there is one. + if (last_node) |l| { + try disjointed_nodes.append(l); + } + else { + var t = try self.create_node(); + t.* = .{ + .value = TreeValue { .operation = .unknown }, + }; + if (last_node) |l| { + l.parent = t; + t.add_child(l); + } + try disjointed_nodes.append(t); + } + last_node = null; + }, + ')' => { + std.debug.assert(last_node != null); + // Close out any number that's in progress + if (buf_pos != 0) { + last_node = try self.create_number_node(buf[0..buf_pos], last_node); + // Reset buffer + std.mem.set(u8, buf[0..], 0); + buf_pos = 0; + } + var dj = disjointed_nodes.pop(); + if (last_node) |l| { + l.parent = dj; + dj.add_child(l); + last_node = dj; + } + }, + else => unreachable, + } + } + } + + // Addition hash priority over multiplication + pub fn parse_line_part2(self: *Tree, line: []const u8) !void { + var last_node : ?*TreeElement = null; + var disjointed_nodes = std.ArrayList(*TreeElement).init(self.allocator); + defer disjointed_nodes.deinit(); + + var buf = std.mem.zeroes([16]u8); + var buf_pos : usize = 0; + for (line) |c, k| { + if (c == ' ') { + // Check buffer length, if not zero add the necessary tree node + if (buf_pos == 0) { + continue; + } + last_node = try self.create_number_node(buf[0..buf_pos], last_node); + // Reset buffer + std.mem.set(u8, buf[0..], 0); + buf_pos = 0; + continue; + } + if (std.ascii.isDigit(c)) { + buf[buf_pos] = c; + buf_pos += 1; + + // If we're at the end of the string, we need to run the stuff + // for adding a number node + if (k == line.len-1) { + last_node = try self.create_number_node(buf[0..buf_pos], last_node); + // Buffer reset unneccesary here + } + continue; + } + switch (c) { + '+' => { + std.debug.assert(last_node != null); + // If we have a last node, we should check up for + // an unknown parent. If an unknown parent exists, + // we should set the operation on that node, and + // set that node to the last_node. + // If we ourselves are unknown + if (@as(TreeValueTag, last_node.?.value) == .operation) { + if (last_node.?.value.operation == .unknown) { + last_node.?.value = TreeValue { .operation = .addition }; + continue; + } + } + else if (last_node.?.nearest_unknown_parent()) |unknown_parent| { + unknown_parent.value = TreeValue { .operation = .addition }; + last_node = unknown_parent; + continue; + } + // If there is no unknown parent, our last node could + // be an operation node or value node. + // If last_node has a parent which is an multiplication node, + // we want to insert ourselves between, otherwise we go to the top + // like in part one. + // If the last-node is itself a multiplication node, then we + // want to do the swap as well. + var t = try self.create_node(); + var nearest_op = last_node.?.nearest_operation(); + if (nearest_op) |p| { + var new_child : *TreeElement = undefined; + if (p.children[1] != null) { + new_child = p.children[1].?; + } + else if (p.children[0] != null) { + new_child = p.children[0].?; + } + else { + // maybe? + unreachable; + } + p.swap_child(new_child, t); + new_child.parent = t; + t.add_child(new_child); + t.parent = p; + last_node = t; + } + else { + if (@as(TreeValueTag, last_node.?.value) == TreeValueTag.operation and + last_node.?.value.operation == .multiplication) { + std.debug.assert(last_node.?.children[1] != null); + var mult_child = last_node.?.children[1].?; + last_node.?.swap_child(mult_child, t); + mult_child.parent = t; + t.add_child(mult_child); + t.parent = last_node.?; + last_node = t; + } + else { + var root = last_node.?.get_root_node(); + root.parent = t; + t.add_child(root); + last_node = t; + } + } + t.value = TreeValue{ .operation = .addition}; + continue; + }, + '*' => { + std.debug.assert(last_node != null); + // Same as '+' + if (@as(TreeValueTag, last_node.?.value) == .operation) { + if (last_node.?.value.operation == .unknown) { + last_node.?.value = TreeValue { .operation = .multiplication }; + continue; + } + } + else if (last_node.?.nearest_unknown_parent()) |unknown_parent| { + unknown_parent.value = TreeValue { .operation = .multiplication }; + last_node = unknown_parent; + continue; + } + var root = last_node.?.get_root_node(); + var t = try self.create_node(); + t.* = .{ + .value = TreeValue{ .operation = .multiplication}, + }; + root.parent = t; + t.add_child(root); + last_node = t; + continue; + }, + '(' => { + // We need to start a new disjointed tree. + // Create an operation node of an unknown type, + // and set that as the parent of the current last node, if + // there is one. + if (last_node) |l| { + try disjointed_nodes.append(l); + } + else { + // This assumption that the new disjointed node will + // be the new root is not always true since there is + // operator precedence now? + // We also sometimes loose nodes because of the swapping? + var t = try self.create_node(); + t.value = TreeValue { .operation = .unknown }; + if (last_node) |l| { + l.parent = t; + t.add_child(l); + } + try disjointed_nodes.append(t); + } + last_node = null; + }, + ')' => { + std.debug.assert(last_node != null); + // Close out any number that's in progress + if (buf_pos != 0) { + last_node = try self.create_number_node(buf[0..buf_pos], last_node); + // Reset buffer + std.mem.set(u8, buf[0..], 0); + buf_pos = 0; + } + var dj = disjointed_nodes.pop(); + if (last_node) |l| { + var root = l.get_root_node(); + root.parent = dj; + dj.add_child(root); + last_node = dj.get_root_node(); + } + }, + else => unreachable, + } + } + } + + fn create_node(self: *Tree) !*TreeElement { + var t = try self.allocator.create(TreeElement); + // Having some non-zero initialization problems, but + // can't use std.mem.zeroes since TreeValue doesn't + // have a "zero" value. + t.children = [_]?*TreeElement {null, null}; + t.parent = null; + try self.children.append(t); + return t; + } + + fn print_tree(self: *Tree) !void { + var stdout = std.io.getStdOut().writer(); + if (self.children.items.len == 0) { + try stdout.print("Tree {} has no children", .{self}); + return; + } + var root = self.children.items[0].get_root_node(); + try root.print(0); + } +}; + +test "no_parentheses" { + var line = "1 + 2 * 3 + 4 * 5 + 6"; + var tree = try Tree.init(std.testing.allocator); + defer tree.deinit(); + + try tree.parse_line(line); + std.debug.warn("\n", .{}); + try tree.print_tree(); + + var v = tree.resolve(); + std.testing.expectEqual(@as(i64, 71), v); +} + +test "ex2" { + var line = "1 + (2 * 3) + (4 * (5 + 6))"; + var tree = try Tree.init(std.testing.allocator); + defer tree.deinit(); + + try tree.parse_line(line); + std.debug.warn("\n", .{}); + try tree.print_tree(); + + var v = tree.resolve(); + std.testing.expectEqual(@as(i64, 51), v); +} + +test "ex3" { + var line = "2 * 3 + (4 * 5)"; + var tree = try Tree.init(std.testing.allocator); + defer tree.deinit(); + + try tree.parse_line(line); + std.debug.warn("\n", .{}); + try tree.print_tree(); + + var v = tree.resolve(); + std.testing.expectEqual(@as(i64, 26), v); +} + +test "ex4" { + var line = "5 + (8 * 3 + 9 + 3 * 4 * 3)"; + var tree = try Tree.init(std.testing.allocator); + defer tree.deinit(); + + try tree.parse_line(line); + std.debug.warn("\n", .{}); + try tree.print_tree(); + + var v = tree.resolve(); + std.testing.expectEqual(@as(i64, 437), v); +} +test "ex5" { + var line = "5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))"; + var tree = try Tree.init(std.testing.allocator); + defer tree.deinit(); + + try tree.parse_line(line); + std.debug.warn("\n", .{}); + try tree.print_tree(); + + var v = tree.resolve(); + std.testing.expectEqual(@as(i64, 12240), v); +} + +test "double_open_brackets" { + var line = "((2 * 3) + 4) * 2"; + var tree = try Tree.init(std.testing.allocator); + defer tree.deinit(); + + try tree.parse_line(line); + std.debug.warn("\n", .{}); + try tree.print_tree(); + + var v = tree.resolve(); + std.testing.expectEqual(@as(i64, 20), v); +} + +test "ex6" { + var line = "((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"; + var tree = try Tree.init(std.testing.allocator); + defer tree.deinit(); + + try tree.parse_line(line); + std.debug.warn("\n", .{}); + try tree.print_tree(); + + var v = tree.resolve(); + std.testing.expectEqual(@as(i64, 13632), v); +} + +fn test_part2(line: []const u8) !i64 { + var tree = try Tree.init(std.testing.allocator); + defer tree.deinit(); + + try tree.parse_line_part2(line); + std.debug.warn("\n", .{}); + try tree.print_tree(); + + return tree.resolve(); +} + +test "part2_no_parentheses" { + var line = "1 + 2 * 3 + 4 * 5 + 6"; + var v = try test_part2(line); + std.testing.expectEqual(@as(i64, 231), v); +} + +test "part2_ex2" { + var line = "1 + (2 * 3) + (4 * (5 + 6))"; + var v = try test_part2(line); + std.testing.expectEqual(@as(i64, 51), v); +} + +test "part2_ex3" { + var line = "2 * 3 + (4 * 5)"; + var v = try test_part2(line); + std.testing.expectEqual(@as(i64, 46), v); +} + +test "part2_ex4" { + var line = "5 + (8 * 3 + 9 + 3 * 4 * 3)"; + var v = try test_part2(line); + std.testing.expectEqual(@as(i64, 1445), v); +} + +test "part2_ex5_sub" { + var line = "5 * (2 * 3 + (4 * 5))"; + var v= try test_part2(line); + std.testing.expectEqual(@as(i64, 230), v); +} + +test "part2_ex5" { + var line = "5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))"; + var v = try test_part2(line); + std.testing.expectEqual(@as(i64, 669060), v); +} + +test "part2_ex6_sub" { + +} +test "part2_ex6" { + var line = "((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"; + var v = try test_part2(line); + std.testing.expectEqual(@as(i64, 23340), v); +} diff --git a/day2/input b/day2/input new file mode 100644 index 0000000..082b283 --- /dev/null +++ b/day2/input @@ -0,0 +1,1000 @@ +13-17 s: ssssssssssssgsssj +7-9 p: pnlzhcppvl +5-6 z: zzbwrv +7-15 w: wwwwwcqwwwwwwwww +8-9 h: hhhhhhhhsh +12-13 l: mtrkqfllrglll +3-4 t: nntt +10-14 g: svgggggfhqggghlg +3-10 x: djxxxpmcxx +1-10 z: ztzzzgzzzz +3-4 j: jjjjj +3-4 c: fbhnsccbc +2-4 q: thql +15-18 w: tcwzpwzfwwqftvczbw +5-7 l: lblwblbmllqnlbl +3-4 b: bvbfnbb +4-5 f: ffgzf +7-9 c: cctcccccc +5-6 k: szkgsk +2-5 n: nqvnmgnqnsxfn +2-10 s: dsfsbsssltss +12-14 s: ssskrssssssfsxpsqsp +13-15 j: jjjjjjjjjjjjjjjj +16-17 l: jllclhllkgcpljzwk +6-9 f: fsffwffbffbfff +5-9 s: xtzscxsstcss +6-9 h: hmnhshhhhqhrthmh +3-6 x: xxxxxx +9-11 m: mcmmmktmtmmmmm +2-6 r: grrprrsmr +15-16 v: vvvvvvvvvvvvvvwdv +2-14 j: jmjdbhjjjjjjjxnjj +5-9 r: rrwrrrrrr +3-9 b: wbbcbvbtbbbbb +2-9 r: rrtjlplkrgmrrrrxq +9-12 s: sssshsmsssss +2-14 t: qzxxvthtthtthv +2-11 p: pvlsppwmgcspl +12-15 s: dsjqsshdssbssstsssss +3-9 k: tkkkpkkklk +7-15 s: sssssssssssssgsssss +6-9 x: xxxsxzxglpwxl +2-3 x: xxmh +7-9 g: ggsggggggg +4-17 t: vtttrrrhtghfjvnqtttj +1-2 n: jgnpn +11-12 k: vlkkbkkkkklk +9-12 v: vvvvvvvvwvvvv +10-11 j: jjjjljjjjvm +1-5 x: vvxlx +3-4 l: flll +10-11 q: qqqqqqqqqlq +4-5 d: vdvhmpdtrdhdzfdsgk +14-16 b: bbqbbbxbhrbpbtmhbbb +18-19 d: dzpnbxngpgsjtnvtcdd +2-16 v: jtrhtlfhvkbbflfq +15-17 q: qqqsqqqqqqjqqqlqm +5-6 q: tqrhtqqspdqvzqbx +4-8 b: lbbzbwtv +10-13 f: hrsnsfflfffsfjff +10-14 k: kkjkkkkkkkkkkkkkkhk +4-9 c: ccwcccccc +5-7 r: grkrrrwjrrgbdtd +8-12 p: tgspnljpfhtr +5-6 v: vvvvvvm +5-7 v: vvvvvvv +6-8 q: qqqqqdqqq +2-4 v: xfvqvlp +3-4 g: gghb +3-14 z: xflgzzrkzqzxzzxgd +1-7 g: ldsgswgdgdmjlggb +5-10 h: rhhmhhnbdhhqhwp +16-18 m: mmmmmmwmmmmmmmmmmmm +5-11 j: scssgcjjjjpzjjn +13-14 s: wznksvkfvfskfs +3-9 q: qdqqkqtbcnqqqsrklqbf +7-9 c: cccchcmcvdcczwt +15-16 g: gggdgggggggggggg +1-5 k: kkkkkk +7-10 q: qqqqqqqqqqqqq +3-12 b: bbbrhbspbrbfbbqbbbb +3-5 r: gczrgr +2-6 h: whnlvhsftp +8-20 h: fhhhsdfhhfzgmhpqhhjh +15-16 z: sbzzzzzzdzjbwhgb +4-8 h: jgtbmhwb +8-9 s: hssksrnhlsdslssvcsbs +2-6 v: vvvvvvv +13-14 x: xxxxxxxxxxxxnsbx +12-13 l: pgllllltpdfpxlll +2-17 v: vqnncnxkssmhvkzstzgp +4-5 r: rrrhw +8-11 p: pppdppphppp +6-7 t: lrmqtts +8-12 h: hhlthhhhhhhhhtrzh +9-10 g: jpgpmpcrwfkz +12-13 w: wwwwwwwwwwhwwww +5-13 l: jwtlqglllllxkllls +2-4 c: ncpcgd +3-7 l: llslllll +2-5 n: jdfwnn +3-5 z: xctxd +4-6 l: lllrll +6-7 q: fqqqqqqzqqqqq +9-12 c: gccwgwqlcxccchchcrcb +7-12 p: pppgpppppppps +10-16 g: xrgfggzzghtgxgbggg +7-11 d: tdddddqdwdgxldj +11-14 p: pppppbpppppppppp +1-2 j: jhjj +8-9 v: pvvvvvvvcgvq +5-6 n: qcrhnnkktxvdxcp +7-12 x: lfnxxxdxxxxp +10-12 s: sssssssssbsgs +2-3 x: rqhzxmjnjxx +13-14 w: wwwwvwwwwwwwqhww +10-11 t: dgttttgttttt +7-9 w: wdzwwwwjj +4-10 v: vvsjvvbvvncvvvvxv +6-8 w: wwwwwpwq +7-9 j: jtjjjjrjmxg +5-11 z: zzdgztshstzczw +1-4 s: ssss +3-10 p: pqppgrphrpkdmp +9-12 x: xxxqxxxlxxsx +3-4 v: nvswzv +3-9 d: vdjvdcxdkdd +2-10 v: vvjcvvvzvkb +11-14 g: gggzggggggjgghg +4-19 p: pppqppppppppppppppvq +3-5 n: ngznkgdpn +13-14 t: tttwtbtttttxxmttt +3-7 q: qnqqqqqtqqz +3-4 r: rkgr +9-12 l: lqkfljzllqtl +5-8 m: vpmmsnfmtxbcknlmpb +15-19 s: ssptssnhsksnszsdpqss +13-14 j: jsjjjjnjjjjjjjj +6-9 p: ppppppppz +5-8 r: tqzbnvgsvfrx +7-9 h: hhhhhhhhp +8-11 s: ssssssssssss +3-10 t: ttttttttttttt +4-5 g: ngtgg +7-8 n: tnnnnnnqn +12-16 x: bxxxxxzxxxxxxxbxx +1-3 z: zzzt +11-14 x: xxgxxxxxxxwcxfx +6-11 v: rgkkhpkjvvf +16-17 n: nfgnnnnnnnnnnnngvn +3-7 w: wkwwwww +5-16 g: ggggcggwgggggggggg +1-3 l: sjvjlkzrpn +17-19 p: pppppppppppppppptpd +2-6 b: vjjwbqbdbpwsbw +4-8 g: gggggjvgd +2-6 w: pzzpwdm +3-10 g: ggggcggggggg +1-3 v: vxvjcvcpslpfn +9-10 r: qrrwrrjrrr +5-10 m: qbmdzvqmxnnmmmtk +2-14 q: vqttpdjhqvkqzqxz +12-13 r: rrxbrrrrrcrptjrr +13-15 s: cscssssssssssssss +7-10 z: zxbrzxbdbhzzzfzz +2-16 n: skqkxqmqbvbrnspnrgq +14-18 b: bbxsbbdpbnbbbnbbbpbb +5-8 b: bmcrdhbbk +11-13 f: fffffffzfffwffb +5-6 w: wwbwlww +12-14 d: gzxclqbnmnxjlzd +13-19 z: fzzzctzzdsbgzzzzwzpb +2-12 w: lcwwtwwpwffdjqwms +9-10 x: hznxnxxxxxxxgkxx +2-4 g: cwfjtlgf +11-12 k: bqfkkkklkkkkb +2-4 l: llllgxk +5-9 m: cpwmqkzhxs +8-15 b: bbwlwkblvbwdvrjbgsb +3-4 f: ffmff +4-10 c: nqxcqcfcqc +10-12 d: ddqddddddtdhd +3-4 n: dghnnqnn +6-15 s: rsbxbrfmssdknppw +2-13 m: mmkmmmmqdmkmmm +8-12 n: nnnnnnnnnnnn +2-5 d: mdkwd +14-15 l: hllllllllllllgl +6-11 g: jgccfnggggpgkt +4-6 j: jjjtjjjjjj +9-12 v: hgpjjlvhvhljb +2-4 g: jfwdgfr +4-5 f: fhffffchf +16-17 j: jjjjjjjjjjjjjjjjj +1-4 t: tcttwtttttrkt +6-13 x: qmxfxxwxrxdxxxfvgv +6-7 c: cckpccc +3-10 m: qwmmpknsgmdmfvrcvw +2-4 r: rszv +1-7 q: qqqqqqqq +1-6 l: lzlmjl +11-12 q: mqqqqxbqqrqqqdqqbkq +8-11 h: jtvbhxhhphhhh +9-11 b: bbbbfbzbzbb +5-7 l: gljssxddzscvhwrlrb +3-6 c: fxcbccddxxcn +3-5 s: ssssz +17-18 n: jctqdsjchwknkffpnn +8-10 c: crtwbwcfcqkf +3-5 r: qrzqc +7-12 z: zzzzzzzzsfzsz +13-15 p: pppppppppzrllplp +11-12 h: nhhhhjhqhhplhhh +4-5 l: lllll +4-10 g: gggzgggggg +15-16 h: qhhhshrhhfhhhhch +5-7 k: jsrvnjlkq +16-17 p: pppplppppppppppml +13-14 m: xqhmjdmrmmmffr +6-11 c: cccccgccccrccccccc +9-10 l: llllllllxllt +8-9 b: bbbpbbbwbdnkbb +5-9 m: sfmmpmmmzn +5-15 k: kkkkkkkkkkkkkkkckkkk +3-4 h: hhhh +15-19 g: gggwgggrslgxjgfgbfs +12-13 d: dddddddddddxb +6-14 k: kkrgdvhscffwwm +14-16 m: zmmmmqmmmmmmmgmm +8-9 w: wwwwgwwww +1-12 x: xxxxxxxxxxxx +1-5 b: bwrbbfwgh +1-3 t: ftttttttttttttt +10-11 m: mwmmmwkmxsf +8-9 t: tqtttttttdtttt +7-8 z: hzbkpzfg +2-3 h: htblhdhh +3-4 p: pptnlpc +4-7 l: lqlnqhljt +12-14 n: nnnnnnnnnnjnnt +1-4 d: dszd +12-13 f: fvrffffffffkfff +9-15 t: bkzstqvtgtwxtzqttd +6-7 v: vrvvvkgv +6-9 n: knbpnnjnnsn +5-8 n: nznkzzqrbn +9-12 s: ssscssssgsqwsspssp +4-16 q: slqqqqqhqqqqqqdqc +1-3 d: gdttdd +2-6 h: hhqzmh +4-9 k: lkckkpbzkl +8-17 b: bbbbkbbpbbbbbbbbn +1-2 r: bqmrw +8-9 s: ztssqssbz +1-13 s: stbqmhspsdgjs +8-10 z: trnsmlxzmzzzz +6-8 v: vlxvgzbzvvv +3-6 c: xddhwtcbpcf +13-19 g: rjvsgpnfjvzlxxzzgxgm +5-9 m: qffpmxmfmk +14-15 c: dcfwcpxcmvpxxtcbmzhc +6-10 k: jkpbkvghpxksfkkk +2-3 j: jmgjjjj +7-12 z: szrznmkjxnzj +4-9 s: ssssssssss +2-4 h: hkqvfgpsxlnhtrqr +6-11 g: gggglrlgggwv +1-6 v: vrbvlvrvv +4-10 j: jjjjjjjjjz +3-12 k: kkjkkkkkfckgkkkkk +3-15 x: xxrxxxxxxxwxpxg +5-8 v: vvhvvdzvqfrvgqvt +5-17 z: zznzzzzzzzzzzzzvf +4-12 n: fdrncrggjlbgbmwv +6-17 d: tcddhdbdvtsnrdstd +1-10 m: mqljmgchlmsx +4-6 l: fbllbl +8-9 p: kpmtpphwp +3-6 j: sjjjjj +5-6 n: nnnnbs +7-12 p: ppqppngcphpk +5-15 x: xxxxgxxxxxxxxxqx +1-3 p: ppppm +3-6 w: wwwkwww +1-4 r: rrrx +3-4 z: zzznp +12-14 n: tnzwtmnnnnndnfnnn +9-10 d: ddfdddtdddd +4-14 l: hvllsgncmhxhwl +10-15 j: kxftfsmjvjgslsjpp +2-10 g: gtgvggqggggxggdg +1-9 v: cvnxhhffnbcv +1-14 c: ccccccccccccccc +3-8 q: fnqmkbhqtbjqvczq +2-4 v: fvphvgv +10-11 k: kkkkkkkkkpt +1-10 d: dddldkddmdd +4-6 x: xxxxxxxx +4-11 k: kxkfkkkskkrkmk +1-6 n: nlmngnkqww +1-9 j: jjjjjjjjsj +5-6 b: bbbbbb +9-11 q: qqnqqmqqqpq +4-7 r: drrrrsrrz +10-15 n: nnhncnpsnxtnpnqnnghn +3-6 d: ddddddd +4-7 x: bxvxbxjwxgx +1-2 n: cmpwsbjzghgndj +2-4 r: przczfjfrbwj +3-17 k: qbvmqxxffdfpkwxdgxv +7-12 v: llmjvscvjvpvp +2-7 z: vzxzxxz +9-18 r: srdrjcrrrvhrcqrrrr +7-8 f: rffffvtrfsqff +5-8 w: pdcwwvmwwwkzwwjwxks +3-4 c: cccc +15-19 c: cccccccnccclbnplccqc +2-13 f: fffffffffffffff +3-9 t: thrkzdttb +6-11 p: pppppgppppjp +5-8 q: qqqrqfqs +7-11 r: crprgtwwrzp +2-10 f: qfhgfftfdbfnlffffff +4-5 h: dhvvlcw +3-6 s: sffsfws +2-7 b: jrvxbhbp +10-11 w: wwwgwwwwwkb +5-9 d: dddddddddddddkdv +4-14 b: bbbbbbbbbbbbbbb +4-8 x: xxxxdxbqxc +5-9 l: phlkhlllbc +1-2 s: ssgskqvrsrwdt +19-20 x: xcxqxvxxxtstnqxhxxxx +6-7 x: gxxxxgb +4-5 c: cccccc +3-10 q: pzzjqjqpfbqws +4-10 t: ttdttsccttpt +14-18 c: ccrccccccccccccccrc +2-5 x: xxzqx +5-11 c: qbckpccckccccws +5-6 g: gggggg +3-5 n: wknbnnlnnq +9-13 j: jjxjjjnjjjdqjjj +5-9 s: smsxsrfss +2-4 v: vxphvvk +6-7 x: xxxqxxbbx +1-3 g: zrgtghjwd +4-5 n: nmntwnn +6-8 g: ggznggggg +4-5 k: tkkzs +9-10 g: hqdhggggqggk +12-16 w: wwztwmwwspwhmwwz +3-5 m: mmmvmjmmm +3-4 j: jjjj +6-16 z: kzbtzqrkzzcfhvpwjszx +3-9 f: ffwffffffff +13-15 b: bbbmsbbbbbbwbbbbwb +11-14 n: nnnnnnnnnnnnnnv +8-9 v: bvvflvvbjvbtjqrvsxf +1-5 g: gjgnggg +15-16 n: nnnnnnnnnnnnnnwvqnn +12-13 l: lllhllrlllllllll +5-6 l: llmlll +8-9 z: zzqzdzvzzzz +3-4 d: ntdd +4-5 b: sbndbkjxldqpzfbzbqx +2-5 t: bwcfzdlfslsd +4-5 d: dddddd +1-3 t: jtpt +10-12 q: qqqqgqqqqqqmqq +10-19 m: mmmmmmmmmsmmmmmmmgs +2-14 x: xxxxxgxvxmxxxbx +3-13 l: tzljvxspwxdnl +6-10 p: lhnppkpswrppgppzpppn +2-6 j: djgwjjhvpwkcgsfbf +10-11 p: ppppppppprpppppp +7-12 l: lvgcbnlclvjlk +6-11 z: zzzzzzzzzzn +3-5 x: xzvhxnpwbxgxx +4-6 h: hhlrhnl +8-10 b: brngbslhqhb +6-11 s: ssqjxsssdsssss +2-5 s: dbjdjknspbdldfbjd +10-16 z: ctzzzzznzcwzztzl +14-15 j: jjjjjjjjjjjjjjjj +9-13 d: qvdpwddddddddd +10-12 c: ccccchcccccq +3-5 x: xxxxx +13-14 t: ttstttztttttltt +3-16 k: qvfjklgzlwfwnbjklqdx +12-13 g: ggggggtgggggggvg +11-15 j: vqzjvzvxjhjnjtj +7-8 t: tttttttg +6-7 x: xxxxfmn +10-13 m: mmlmmgvfmmmdmmcmmq +7-14 w: wwkwwwwwwwmptwww +17-18 b: bbbbbbbbbbbbbbbbbb +2-8 c: kbvcnrpx +16-17 n: nnnnnnnnpnnnnnngl +10-15 k: kbkjkdkwpkkhkkksklx +2-12 p: pjhdkvwdltvqrhm +2-4 x: vxhxxk +3-5 m: mmfmf +6-8 n: ngnggfnwnn +9-16 b: bnbbbtcbbbvbbrbbbbb +2-8 p: ppphpzppcgptpprhpp +9-12 x: xxxxxxxxxxxx +5-7 d: dknbddd +7-9 r: rrrrrrrrj +3-6 f: fjmfxk +3-4 n: jnnnbjckggnpjnddhx +6-12 d: dznpsfdtdsdndjddvcdd +7-12 x: xxxxxxhqxxxbxbsx +1-2 k: kkfkkkk +4-7 l: lprlqllll +10-13 x: qxxqkjxxxxxxmz +3-8 f: rxfffwcff +4-5 s: cpscszdssc +5-6 t: tttftt +2-6 p: kpvtkprdqhxzpxrbfp +6-12 s: ksnsklwqfssdsbsss +6-7 l: lzlflfl +7-9 t: ttktttttt +8-14 d: hdddzndhsddpfpdxt +8-10 d: ddnddrddvxbzskddzd +11-13 v: mvhvrtvvvvzvrvdv +4-5 g: gggjw +3-6 m: xhmrpm +7-13 k: kkkkkkkkkkkkk +10-13 n: nnnnnnmnngnnnnnn +7-15 m: kcmtmjtmwjmcsbbms +13-16 j: jjjjjjjjjjjjpjjlj +2-4 n: nnmnkn +12-14 j: jjjjjjjjjjjdjj +1-2 c: cchc +9-12 m: mmmqbmlwmmjmzmmml +3-8 r: rrkkrrrt +4-5 k: wckknxkpkktmks +9-10 d: ddddpdddnpx +1-8 q: qmpmxzfqnqctwpprm +10-12 q: sgkfxhqjkqqq +5-11 p: rwpppdlmhpptkbrlp +1-2 d: lzrbxnlcsqhssgdpvjs +5-6 c: scccck +4-5 s: ssshxsssws +3-11 l: nslwgmxmtblzttxxg +10-11 z: zzzzzzzzzzz +7-8 j: bjjjjjqdbjj +7-8 d: glpfjbpdxd +2-4 k: wkvwrk +1-5 c: vtcgcbc +16-17 x: xxxxxxxxxxxxxxxxm +2-11 f: ffffffsfffffffffffff +4-8 m: mrmmmmmmmmmmmm +2-3 x: xvzxx +2-4 h: hxpn +13-17 x: xxxxxxxxxxxrxpxxxx +4-13 q: wcqqtwwmwqqtqmqtqrqq +10-12 d: dddtdqdnjxdzdfdd +13-14 f: jffffsffmffqjff +6-7 d: sxdvddddwqxd +5-11 d: ddddfdddddcdddd +11-14 b: bbbbbbbbbhlbbj +3-4 p: pfpp +4-7 j: jjjgwkgwnfffvfzfl +6-9 l: gknrmjgxtlzcbvkgxb +4-10 n: nnnnnnnnntnnnnnnxn +1-4 r: rjrr +3-4 m: nkmr +9-10 f: fffffffffff +2-6 r: rnhtml +3-12 q: qqkqqqqqqqqkqqqqq +3-10 r: rrnrrrrrrrrrrrrr +6-8 m: bmmmdmmmmdmh +10-12 g: ppdvvxgkhfskfqc +2-10 v: txpvkgvcbqvqfk +1-5 p: tqcvbtp +6-7 z: zzzzzzz +7-16 z: fdjbbkrzjzdbdblhxb +2-4 x: xlkz +4-11 m: glhknzmvqzfmnsbn +6-8 q: qhmdgqvq +8-16 t: tttdtttdtttttttbvt +4-7 v: vptcmgvvjvvvfvvmht +7-8 t: ttttttngt +5-15 t: ztgbttrntttdvgtptjdb +10-12 b: bvndbbbbbbbbbbbbtb +2-3 t: sbqts +12-16 w: wwwwwwwwwwwwwnwww +2-3 m: kmmr +12-15 k: kkmkrkkkkzkdkrgkk +5-13 h: hhhhzhhhhhhhzhhhh +16-17 l: lllllllllllllcllq +1-3 b: bbjb +2-5 t: vtjhmf +4-5 q: vzdqfd +2-3 n: nnnn +7-14 j: jpjjjjjjljjjjjjjj +12-15 j: crsjpjjjqjjfjkv +10-11 t: ttttttttttttt +1-2 j: jjbjsjvhbfssznf +9-13 f: ffmfffffzfffgfff +15-18 g: sgblrqdftpwzggvgqt +19-20 r: rrrrrrrrrrrrrrrrrrvj +1-4 j: mjlt +3-10 x: jxxxxxxxxgxxx +6-7 p: ppptppp +7-8 b: jbmnbmsc +2-6 f: zshfcbhsh +2-5 r: rrrqwtrvclf +3-8 g: chgtwlbg +11-15 n: knnhnnhnnnpnlknnkhnn +3-8 z: zkqlzzpmjph +5-10 b: bbbbhbbbbbbbbbbbbb +6-15 c: ccccdkrncwrcclc +6-7 c: ckcccwdhcc +12-13 t: ntttktttttftttt +5-8 j: jpjzcjjjjj +7-8 k: kpkkksbkkkkkr +9-12 s: sqssssbssxcs +3-7 p: pbbplhtfpktpnppx +5-7 n: ncnnnsn +4-6 s: sssrss +3-16 v: kvvvvvvczvvvvvvvkww +3-6 k: kkkpmk +8-9 h: hhhhhhhmb +7-9 c: czwcccmtckccc +5-7 t: tstglltkt +2-6 c: cccccv +11-14 z: zzzkzqzzzzzvzzz +3-4 d: ddch +4-6 j: jjjjjvj +5-9 c: cccccccccccccc +7-9 j: hjkwpjjbjfsq +4-6 t: tttlcdb +13-15 z: zzzzzzzzzsqzzgzzzkz +8-10 t: ptckdjtsptlmzrktwcw +2-5 n: tnbhnnkvnq +11-12 m: fqmmmmmqmtmkcmmvnwmm +7-8 z: zzzzztvl +6-7 j: jbpjjjjpxmqxcbwsjrjj +2-8 t: ttkdzfwdtflfswlkntt +6-11 j: rnjjjjjjjjj +10-13 f: fwhkbfdfffvfs +5-8 l: pflplntf +3-5 r: rrrrr +16-20 g: gggggggggggggggggggg +1-12 t: xtnsxbjtttxtt +7-9 r: zrrrrrkrnrrrrrrrrr +2-11 n: nrjnnnwnnprnnn +10-12 z: zzzkxzzhznzdz +7-13 d: pdcjdddqddlddcdkdxk +10-15 r: rrrbrrrmvrcphrrqr +1-3 l: rsll +7-8 x: xxxqvrxx +5-14 p: ppcdvppbppppjpbg +5-11 x: dxdxdhkxxvxqxxxfx +6-12 r: pvbfrhqrhftqrrxcrr +4-7 t: zdbtzst +1-13 k: kkkpkghkqkskk +5-17 g: gvggqgggggqmgxggfgg +12-13 l: llllwllllllwf +2-11 b: bbbbbbbbbbbbb +7-17 h: hhhhhhhhhhhhhhhhhh +2-3 w: lwww +2-3 s: vstcs +4-6 s: vssssxss +14-16 r: fmrrrrrrrrrrwwrvrr +6-7 g: dgwgggp +12-16 g: wggxgggrggggzgbgggg +7-9 s: tjhxrscnsscssssnms +3-12 n: nnnnnnnnjnnlnnnnn +7-8 b: zncbmbglqbbbbpgm +12-18 l: lllllllllllvlllllwl +10-16 q: qqqgqfqqqqqrrqgqq +1-7 n: nnnsnrnnnp +10-11 q: qqqqqbqqqqq +5-8 k: bnsfzkkwfkknkccwqkm +4-5 c: ccdcccc +5-9 z: nlsgzzzdz +2-3 k: xkgxhqkpftx +10-13 d: ddddddddhdddddddd +4-6 x: xmjxwxx +14-16 z: zzzzzzzzzzzzzrzq +3-14 n: qnznjvlzdnnrgwfr +7-13 s: sssxsspsssssrz +4-11 k: pkkkcklbkkkk +9-11 x: xxxxxxxxxxtx +4-6 z: zzjzzfz +3-6 d: zddddddz +10-20 c: smccccvcpbccbqcxbccq +13-15 m: mmmmmvmmmjmnnmlpsm +12-13 j: jjjjjjjjjjjjj +3-5 m: pmmbm +7-17 m: mmmmmwcmmdfqrmmhlmm +3-17 g: gcggnggbgdggggggg +10-16 b: sqpsqkfbnbqzswbb +3-4 w: wwwn +5-6 d: dddddpd +12-15 m: mmmmmmdmmmqlmnvms +13-15 j: jjjjjtjjjjjjzjcj +17-18 t: ttttttttjtttttttttt +17-18 d: dcddmchdwbqrllsxjdv +16-17 h: hshghhndnhhfhhhhh +3-5 g: ggggch +6-13 c: ccvccpccccccvcccccc +2-4 h: hbfh +3-9 l: lllptphml +2-3 s: xwrqssfzr +9-13 m: mktmmwmmmmrmmrqmmmcm +8-11 l: rkvxvrglltlc +1-8 q: jfqqxngqnqchq +2-6 x: zxgjxx +5-14 g: mlbgvdglrgcqjgz +4-5 t: tqgtv +2-6 s: ssfnzs +9-11 m: mxwhmmmmmmzm +1-5 d: dbhjzd +2-16 f: fffffffffffkffffff +6-10 b: dbbbbbbbbbbb +5-6 x: xxxmxxcx +7-8 l: lllpllcb +16-17 d: dzdddddddddddddddd +3-10 t: tklkqftnwcj +9-15 g: jccxpmfjgntpptgkkcvt +1-8 r: sdrwgcvprt +4-5 v: nhbwx +17-18 z: zzzzzzzzzzzzzzzzxsz +5-13 l: cbdklqhnklkmwhpp +4-5 f: fffff +1-4 q: qpwq +9-11 x: vxxgrgxxfvvgx +3-4 r: rrfd +3-16 x: sxqxxxxxxxxxxxxwxxx +5-8 s: ssssssss +5-13 b: jbbhqqbblbbbbfcb +17-18 p: ppppppppprpppwppphp +3-9 p: kdpnpfphppvffpwf +7-8 r: jvrrrrrnrpqrn +5-6 m: ncmmdxmm +10-11 v: vvvvvvvvvdl +3-8 g: jlsscggg +1-3 m: gwms +4-5 f: fpkvnf +6-15 j: zfdrxjgxtbkbbjjctmsk +5-6 v: qnnbvvwqvbwqblqd +2-5 v: kvhvt +2-6 x: lxrgsxg +6-8 s: sssxswsjsssxss +1-6 t: dxwjttnqkt +13-14 s: sssssssssssvjg +1-2 t: rtttnf +9-17 h: hjhhhvhhbhhwhhhhphd +2-3 m: mmmwcm +10-12 v: vvvvvvvvvvvv +6-10 j: flcjtzwhwsnjjjrjrj +3-8 d: ddmrddddd +5-8 c: ccccslcrwrc +13-14 s: hpsqtxvkrsssshh +11-15 t: hrxtjgtwtlmpqfx +11-14 l: llbxlsllllqrqlllzlb +3-4 c: crlcvcxwd +3-9 s: vjbsxhwwdvshfxstc +7-8 f: jfhnffbgsfjfwf +15-16 x: ksxqvfsvnxsgvwgpjzl +16-19 g: gggggggggggggggdggg +9-11 h: hhhhhchhzmqhh +2-6 f: kfdlcfrxftzgq +2-8 p: ppnppkpwwmgp +1-2 g: ggfgrg +1-7 n: nnnnnnqwnnn +5-6 h: hzjgthqphwhnjh +10-15 l: xlllllllvlllllll +3-4 l: lzjb +4-6 l: ldzlql +7-12 b: mzlbqzbrqjjbddr +10-13 t: tttttxtttpttt +4-6 d: dddddd +4-5 k: kzvkkrkf +1-2 h: fqml +17-18 f: jhtfdfgmnchprbwbfrf +3-10 s: sjsnsksbdsss +1-17 j: jgcbjmjjjjjcxsjjjjhj +15-16 k: tkjkjbkkrkkkklmgkj +2-13 k: kkkkfkqkkkkkkkkpkk +4-13 d: ddkkdtddzdnnddjdd +1-3 v: fxvnxdvxnrbjs +8-11 s: sssssssssspssssss +1-8 k: khkkkkkkhk +8-9 k: kkktmkkzk +4-9 w: wrqdfwxwnfwwwnmzww +3-5 l: lgtcvl +13-18 n: nnnnnnnnnnqnnnvnnnn +15-17 z: zzzzzzzzzhzzzzqzv +3-5 q: lxnqsvk +8-13 g: rzzwdlzgbcmggct +10-14 d: ddvdbddddnddpd +6-10 d: dphsszqrvz +8-16 b: bnbgfbkbbbqlbcbbgqbb +13-15 d: dddjddmqndddddddvjdd +8-11 q: tnhgqkqfpjhwqgktq +1-3 n: nnnbn +11-12 f: fwfffbfcvflff +7-8 s: sssglsvssvls +2-5 z: zzzzzzzzzqjzz +2-11 m: mhzrwphzxgj +4-6 k: kkkwkd +8-15 m: mrmmmmmzmmmmzmgmm +1-7 w: wwwwwwxwwww +1-3 l: nllllllll +4-5 m: zbshj +3-9 x: xssxqxxxsxkzx +5-9 d: dnpfhsdmrxbvgxqrs +7-12 r: vhrgcnxrvksg +8-10 c: ccccccctzv +16-17 l: lllllllllllllllhl +6-15 n: nnnnnnngnnfhwwzsnnn +6-19 z: zzzzzlzzzzzzzzzzzjv +7-12 b: bxfbbwsjtbbvbqvbmbpb +5-14 g: gggcjggggggggmgg +5-8 d: wdddddkdpd +4-17 x: xtxxxxxxxxxxxxxxmkx +4-10 c: cccccccccjcscv +9-11 v: ttjzfjldvvmswpqt +5-8 r: tjrwhzgfrkgfq +5-8 m: cvhsmnzmncsfmbqmm +7-8 z: krctfpzz +2-6 w: mlnlswvh +12-15 t: zrntxzttqlthfdttt +1-8 r: pkcsjkrrrzxxsfnjw +5-15 p: xbhpkpnngpqvpcwdppg +3-4 t: tttt +8-11 j: wjjjmjjjjjqp +8-14 h: gjslnklhhkhthxh +2-6 q: qqlqqq +3-6 p: pppgppppppppppp +7-11 l: llhllllrllllxldllll +11-12 d: lddkdddddddddd +4-12 z: zwlzzqsvvclw +15-18 c: tflkxflqccwkmlckck +8-12 h: hhhhrhhhhfwhhh +6-9 r: rrrmrjrrvkrrjrdr +8-19 k: tmdlkcktbkkskvkbkbz +1-13 s: ssssssssssssss +4-5 v: xtcfvx +1-15 s: shtssssswghsfsss +2-4 k: krkl +7-12 q: dxqqqhqqqtqj +1-5 r: rrrvvrrrr +5-9 t: ttrttftxztnhtvkcmtth +7-9 g: gngkcggrg +12-13 z: zzzzzzzzzzzbk +3-4 l: lslllc +4-5 t: pqchpk +5-6 h: hhhhml +15-16 h: qhhhhhhhhhhhhhhhhhmh +5-6 d: ddddfs +1-6 d: dthfdzddfnsdddm +14-15 d: ddddddddndhtddsdnddh +5-7 j: qjjjpjplljjc +2-6 q: qqqqqqq +3-4 b: bbbb +5-6 s: ssssjjs +1-6 b: bbbbfb +7-13 m: cpvmbbnnrmzwf +2-4 f: fnhn +6-7 d: gdktlddrdlvmqdtddpzv +4-5 w: cwlww +6-9 z: zmdrgzlmzx +5-10 m: mjbjmmmlmmwxm +2-4 s: ssnhht +8-16 t: tttttttdtttdtttjtt +3-5 z: wxgzhtswb +13-14 l: lllllblpllllchll +4-8 g: vggqzvggnggggggggg +8-9 h: hhthkshhpnhqhgh +4-7 l: hglxklpl +2-3 w: mkmgkwzwmw +6-7 h: hhhhhrz +4-6 f: tdffff +1-7 l: lmfhgqschjqglrvwwnnz +12-13 g: gggggggggggfhggg +2-10 m: ntmmmdjmmmsvmm +1-2 s: sqsssssssssss +3-8 f: frnthfcfxfft +7-16 w: wwwwwwmwwnwwwwmk +11-13 j: jjkjrjjjjjjjjjd +3-4 s: ssvc +3-13 t: ddttttnnqpqztzbbdv +3-5 g: gggggg +3-4 r: rrrzlklfljqvz +5-12 m: kdgmmrszqpfsbmz +11-14 g: gqgvzgxhgbtngxggh +7-16 k: qqptmhhfkhsgkhbmkx +5-8 p: ppppptppp +2-17 x: vxtxpvnxvlctrcpfxxx +2-3 w: bwmwjwwwwwtnqwxc +4-5 g: gggggg +4-7 z: znzwzzzs +4-5 v: kvvvv +10-14 r: rrrrrrrrrbrrrx +4-5 t: xtttt +4-11 w: wwwwwwdcmkrwx +6-7 c: ccccccjc +12-14 w: wkwwwwwwwhwlwwwk +5-9 s: hmssssssssss +2-4 r: rrrjsh +12-13 m: mmmmmmmmmmmmmx +3-5 s: sshsvssss +4-5 l: xllwnshchfdfk +16-18 w: wwpwwpwwwmwwzwwtwwww +2-9 c: zsfgbrrprlszrr +10-11 n: thnmfndnnbnnbhnnnn +13-14 v: vvvcvvvvvvvvvvv +3-4 n: rwcm +14-15 t: tttttztttttttpjt +5-8 j: jjjjwhjdj +5-8 f: fffffffm +6-7 z: zzqzzzz +12-19 j: kjrfnsjnhjdzgqpcjzvh +3-7 p: pxpdvcqdptxpvk +1-4 c: wccqj +1-2 w: pwsqhwjdhcm +2-3 b: bfbn +10-19 q: qqqqqqqqqtqqqsqrqqq +5-8 p: pppppppppppppppp +10-13 g: rjghslgbggkgjdgvp +3-9 z: fnnfzzdnf +9-16 g: tlgtgggggggggggqm +3-12 r: rrrvccrrvbdbncrrr +1-4 v: jvhbv +15-16 v: vvvdvvcvvvpvvvvvvvv +3-4 g: ggggg +7-8 w: wwwwwwmpw +4-9 s: gkxshzkpssc +2-8 q: pqttnpqqqfwqs +3-4 n: nlnp +3-4 h: phhh +16-18 g: hqsxhmmpfgggmgpqhrjg +15-17 w: wwgwwwwwwwwwwwmwl +7-9 x: xxxxxxmxv +1-7 s: ssssssbs +1-3 x: dxlxxx +3-6 p: wpxppq +5-7 c: clcclcfcbccc +3-5 s: sbmst +3-5 d: xqmdn +5-10 z: zbzwfddkzzc +18-19 d: dpdddddddddddddddwcv +3-4 r: rrrr +8-9 f: ffnffffwd +12-16 h: hxnlxghzkpcpdhqqvl +6-7 m: jngclmm +5-13 m: rmmmpmrmmmmmjmmmm +1-3 f: dfwfs +7-8 l: lclllwllll +16-18 j: jjjjjjjjjjpjnjjgjbj +12-15 f: fffffffffffnfftfffff +9-13 w: qbnpmklbwxdbbwkklpwb +1-3 j: mjkj +1-3 h: hphwdh +3-5 x: vrxxb +1-15 v: mvvvvvvvvvvvvvj +8-12 v: lvzfvzvvnjtvvvvvv +4-6 g: gggvggggg +13-20 l: zdllslnlxslqpnvgwlwm +2-4 l: lllhll +3-14 k: kckzddtzbmvkpkhb +4-5 k: hbkgbxzj +2-4 p: lppp +2-11 r: rrrrrbrrbrrrrwrrrwr +4-7 k: knkqkkk +7-8 r: njrrrrrrrr +4-7 h: phhhnhdhc +4-5 r: nsnrrfktwbbhrrrh +4-5 q: qqzvzsvkq +6-7 b: jbbbbbbbkbgb +5-11 f: ffffcfffffgff +12-16 v: vfvvqvvdvvvlhvzjvmzv +9-10 v: vvzvvtvvjgvv +1-7 v: vvvvvvvv +3-12 z: zmncxhrdzdmtcbxtlrzq +3-7 r: rbfbrjrr +12-13 n: nnnnnnnnpnnldnn +5-12 j: jjjjjjjjjjjlj +3-6 s: sssfsgss +13-17 h: hhhfhhhhhhhhvhhhhhhh +5-10 g: gggxkggggvg +1-4 b: hbbtb +14-15 t: tttttttttttttnb +7-14 d: ddddddddddddddhdw +15-16 d: rbdddbdwmjdhmpdd +7-13 s: kxpdntprmskcs +3-5 m: gmdmpj +4-5 j: jjjjjvjsj +1-14 q: qmqqqntqcqxmqsqkqq +4-5 q: tqxqq +8-11 m: mmmxmmmvmmv +5-8 q: qqqqrqqw +5-15 d: dqdddddddddddvspd +1-4 t: tttttt +12-15 z: dhzzxwfjgnzhzxt +8-11 v: kdnmfnmqvvdvqdlvk +16-18 s: sssssssssssssssjstss +2-5 c: ccwdccc +3-11 x: nxjxxxxxxxxxxx +13-15 v: vvvvfvvqvlvvvvvv +4-11 s: sssszssnqjsbsvs +9-18 j: gxhjjjjjnjjsjjjrjjjj +3-4 t: ttfttt +9-10 s: qzgxjhpsss +9-10 q: qqqqnrtxrqqsqqq +6-13 k: kkkrgspkkkpwjshmk +9-12 h: xhhhmhbhhhdhh +3-12 g: gfgggggjgggggggggg +13-15 z: zzfzzszzzzzzvzzzhzw +5-15 m: mzrmmmmndchfzmmrr +5-10 z: zzzzzzmzzh +4-5 s: wscfc +3-6 m: kmmtmm +5-7 h: hhhhchh +4-14 w: wwgwwwqwsfrjvmbwj +2-9 v: vwvvwvmjcqnxv +9-10 x: qxxhfxchrx +17-18 x: xxxxxxxxxxxxxxxxwp +4-6 v: vvvvvtv +11-14 l: lcqlclllllrlddxlzll +1-4 r: trrn +10-13 h: thnsxphnfgvhvq +11-12 s: sssssssssshsss +10-11 z: rqpzszzmzdz +3-6 q: qrqqqq +5-6 h: hhkhhhh +8-16 h: wqhjvhlgwtsgvlpf +3-6 f: gqfpcfsfhfjgrbqv +3-5 l: lqllsrjlv +6-10 v: vvvvvvkvjv +3-8 t: gtttcbnkxxstttd +2-6 j: jjjjbjz +10-15 j: ftwjtfzjmjsvwjj +8-11 d: ddsksddddzfd +2-3 b: bhngbb +14-16 c: mllmcbfxwxrqlcjcw +7-8 q: qqqqqqdv +5-6 s: slkzlfvg +3-5 q: qqqqq +3-12 p: pddpdpszrppxcpjgv +11-18 r: rrrrrrrrrrprqrrrrr +3-4 c: cscckcxcn +11-13 g: gvgwmlngggqggrtgtkg +5-7 b: smfpbbb +7-18 l: sqmlklvkqfjrgtqhzr +6-7 k: kkpqqfgz +7-9 n: fnndnnxnndn +11-12 c: ccccccccccxv +6-9 d: dddvdddddddvd +1-4 v: nvjfv +3-8 g: gggggggg +6-7 x: xxxxxxx +4-5 c: scccc +6-13 q: nchlfqqqlqnqqqtq +1-8 r: srrrrrrnrrrrrrr +4-5 p: sdpscpppp +9-11 r: rrrdrkrrrqg +3-5 m: xwmscmmm +7-11 r: rrrfrrrrkfrvrf +4-6 b: bbfbbb +4-9 v: rblrvrvpvz +2-8 w: wwwvwgwww +8-9 w: wwwwwwwwzw +16-18 t: ttttttttttttttttttt +8-9 n: nfrzsdjxr +1-2 w: wwfwwmfbww +2-4 s: dfsksft +1-13 d: dwdrccnddqmndcl +1-4 f: qfflf +3-7 d: dnddjpdfgc +3-5 l: lkglx +1-13 j: jjjjgbjtpjjhd +15-16 j: jjjjjjvjjjjjjjjjdjj +4-13 t: tttxztttttttkt +4-5 m: mmmmm +4-6 j: jgjrjwjfjx +8-11 t: ttbjttvttsttdqtn +14-15 w: wwwwwwwwwwwwwkjw +1-6 x: nrscxn +3-13 w: wwwwwvgnwbwwwwwwv +12-15 p: pppppppppppjpppppppp +5-11 v: vvvkvbvwkwnvvvsxvv +1-11 m: mmmmmmmmmmtm +10-11 c: cccccccccwc +5-8 f: xvgstwfxfhxknds +12-13 t: tttttztttttttt +4-17 k: vkpkfkkkqnkqnkgkkknk +9-12 k: kkwpzpdzxhxk +14-17 v: fgvvvvvvvvvvvjpvv +7-8 k: kndnqkkk +7-11 c: gfcbccccjvcskcmrcxc +4-5 n: ngtnr +3-12 k: mtcfszkdhkdkd diff --git a/day2/main.zig b/day2/main.zig new file mode 100644 index 0000000..0df591a --- /dev/null +++ b/day2/main.zig @@ -0,0 +1,129 @@ +const std = @import("std"); + +pub const Policy = struct { + min: u32 = 0, + max: u32 = 0, + value: u8, + password: []u8, + + pub fn matches_policy_one(self: *Policy, s: []u8) bool { + var c : u32 = 0; + for(s) | v | { + if (@as(u8, v) == self.value) { + c += 1; + } + } + var valid = (c >= self.min and c <= self.max); + //std.log.debug("{} is {} for Policy {}-{} of {c} [{} found]", + // .{s, valid, self.min, self.max, self.value, c}); + return valid; + } + + pub fn matches_policy_two(self: *Policy, s: []u8) bool { + var n_matches : u32 = 0; + if (s[self.min-1] == self.value) { + n_matches += 1; + } + if (s[self.max-1] == self.value) { + n_matches += 1; + } + return n_matches == 1; + } +}; + +pub fn main() !void { + var allocator = std.heap.GeneralPurposeAllocator(.{}){}; + var f = std.fs.File { .handle = try std.os.open("input", std.os.O_RDONLY, 0) }; + var buffer : [1024]u8 = undefined; + + var byte_buffer = std.ArrayList(u8).init(&allocator.allocator); + defer byte_buffer.deinit(); + + const stdout = std.io.getStdOut().writer(); + var n_valid : u32 = 0; + var read = try f.read(&buffer); + std.log.info("Read {} bytes", .{read}); + while (read != 0) { + for (buffer) | v, k | { + // We're through the read part of the buffer + if (k >= read) { + break; + } + if (v == '\n') { + var p = parse_policy(byte_buffer.items[0..]); + if (p.matches_policy_two(p.password)) { + n_valid += 1; + } + try stdout.print("{}-{} {c}: {}\n", .{p.min, p.max, p.value, p.password}); + //std.log.debug("{}", .{x}); + // Set the position back to zero, without freeing existing memory + byte_buffer.deinit(); + byte_buffer = std.ArrayList(u8).init(&allocator.allocator); + continue; + } + try byte_buffer.append(v); + } + read = try f.read(&buffer); + std.log.info("Read {} bytes", .{read}); + } + std.log.info("{} valid items", .{n_valid}); + //part1(expenses.items[0..]); + //part2(expenses.items[0..]); +} + +fn parse_policy(line: []u8) Policy { + var min : u32 = 0; + var max : u32 = 0; + var char : u8 = 0; + var pass : []u8 = undefined; + + var start : usize = 0; + var got_min = false; + var got_max = false; + for (line) | v, k | { + if (v == '-') { + min = atoi(line[start..k]); + start = k + 1; + got_min = true; + } + if (v == ' ' and !got_max) { + max = atoi(line[start..k]); + start = k + 1; + got_max = true; + } + if (v == ':') { + char = line[start..k][0]; + start = k + 2; + } + if (k == line.len-1) { + pass = line[start..]; + } + } + return Policy { + .min = min, + .max = max, + .value = char, + .password = pass, + }; +} + +fn part2() void { +} + +fn part1() void { +} + +fn atoi(a: []u8) u32 { + var i : u32 = 0; + for(a) |v, k| { + if (! std.ascii.isDigit(v)) { + std.log.warn("Byte {x} is not a digit", .{v}); + continue; + } + // 48 is '0' in ascii + std.debug.assert(v >= 48 and v < 58); + i += @as(u32, (v - 48) * std.math.pow(u32, 10, @intCast(u32, a.len - k - 1))); + } + //std.log.debug("{x} --> {}", .{a, i}); + return i; +} diff --git a/day3/input b/day3/input new file mode 100644 index 0000000..6333a60 --- /dev/null +++ b/day3/input @@ -0,0 +1,323 @@ +..#...##...###.........#..#..#. +#.###........#..##.#......#...# +#.#.###..#.#..#.#............#. +.##............#......#...#.#.. +..#..#.....##..##..##.......... +...#...........###.#.##........ +....#.#...#..#..##............# +....#....##...##..##........#.. +.#..#..#....#...#..##.....##... +.#.###..#......####........##.. +..#...###....#......#.....##.## +..#...#.......#......#..##....# +#...##....#.#..#.......#....#.. +.#......#..#...........#....##. +.##.#......#.#.#.....##........ +.....#.................#.#..#.# +....#..#........##......#..#.#. +..#...#..##.......#..##...#..#. +..#.......#.............#.#.... +.#.................#.........#. +..#..#.#.#.#............##.#..# +.#.#.##.#.....#.....#..#......# +..#.#..#.#..........##........# +.........#...#.....#.#...#####. +##..#.....##.##........#...##.. +.#.....#....##.#..#....##...##. +.##.....#.#....#.#.....#......# +.....#..#.##.....#.#....#.#..## +#......##..##....##...###..#... +.......#..#...........#......#. +#...#......#........#..#....... +##..#.....##.....#...#...#....# +.###..##..#.#........#..#.#.... +#.#...#...#......##........#.#. +......#....#.#........##...#..# +.#.....#..#.#.....#......##.... +.....#.....#.#.#....###.....#.. +#.......##.#......#.#.#....###. +.......#..#..#...#.#.##........ +.#......##..#.........###..#... +....#..##.......##.###...###... +.##............#..#.##.....#.## +..##.#.......##....#.......##.# +#..###............#.#...#...#.# +...##.#.#.#..#.##........#.#... +.#.....#...##.#..###..##.##...# +..............#.#.#.........#.. +.....#...........#.#...#....#.. +.....#...##.##.#....#.###..#... +#..###.........#......#.#.#.... +.....#..#...##...###.#....#.... +#..........#.#.#....#..#......# +###...................#......#. +........####......#.#.......... +.......#.....#...#.......#...#. +.....#.....................#... +...#.#...#...#...........#..... +..#.........#...#....###..#.... +.....#.#..##......##........##. +..#.............#............#. +.#....##.......#..#............ +.#............#.#..#.##....#... +.####...##.#....#.....#...#.... +##..#....#.#.#...........#..#.# +...#..#...........#...#..#....# +.....##.....#..#...#.........#. +...##........#....##........#.. +.##.#...#...#..#.....#....##.#. +#.#...#.#.#.#.#..#....#....#... +#..#.#...#..#........#....#.#.. +....#.#.....#......##...#....#. +.###.##...#....##.#...###..#..# +###..#...##..#......#.........# +..#.#......##.......#.....#...# +..#...#........#.........#.#... +#....#..#.........###.#......## +...#..#....#...#.......##.#.#.. +....#.......#....###...##.#.... +..#.....#.#.....###..#####....# +##......#....#.....##..#..#...# +#...........#..#..#....#....#.. +.#...#.##.#.#.#....#......#..#. +.......#.#....#....#...#.#..#.. +..#.#..#.##..##...##..#..#..... +...##.##.................#.#... +.....#...#......##.#....#.....# +......#..##.#..#.#.........#... +.............##.#......#....... +..#.#.....#...#.#.....#..#..... +.........#..#.#......#..#...... +#..#.#.##..........#.##......## +......#.......#.....#..#.#...#. +.#....#....#.#.....#.......#... +#..#..##..................#.... +............#...........##.#... +####...#..##.#....#.##..#...... +#...#...#.....#.#...#.#........ +.......##.........#.....#.....# +.....#...........##......#.#### +.##....#.#.##......###.#.##.... +........#.####.......#.#...#... +.#.#...##.#.#.#.........##..... +....#............###.##....#... +...##........##.#...#....#..### +..#.#.........#....##.#........ +..#..##..#...##..#.##...#.....# +.#......#..#..#.........#...... +..#........##.#......#.....#... +.##.......#....#.#......#...... +#........#....#.####...#.#..... +##......#.............#....###. +..#....####.#.#.#.#...##......# +#.#.#.....#...#.......#...##... +........#...#....#..#......#.#. +#..#...#.#.##.....#.#....#....# +#...#....#......#.........##.## +..##.#..##............#........ +#.........####.........#....... +#.##.........#..##....#.#.#.#.. +.###......##..#.#.....#.#...##. +...#.........#.#...##.##....#.. +#..#......#....##..#.#...#...## +...#.......#.#.#.....#..##...#. +....................###........ +#...........###......#.#...##.# +.................#.#...###....# +...#..###..#.##...#..#....##... +###..#..#.#...#.....#.#.......# +.........#..#.#.....#.........# +.##..#.........#.#.....##...... +.....#..........#.#.##....#.... +........#.##.....#...##...#.... +#.#.#...#......##....#.###..... +.#.##.....##.....#....#.##.#.## +.#...#.....##.#.##....#.....#.# +...#.....#........#............ +##...####..#....#..##...#...... +#.......#...#.#...#........#..# +......#.....#....#..#..#.#..... +..............##.....#.##....## +.#..##.........###..#.......... +......#......#............#..#. +#.....###...###..........#..... +...###...........#....##..#.... +.....................#...#.##.. +###....#.#....#...#....#.#..##. +..#.............#.#....#..#.#.. +.......#..###....#...#...#...#. +.##..#....##..............##... +...#...#..#..#.##.#....##...#.. +#..#....##......#....###..####. +.##...#.#....#..#..#....#....#. +.#.##..#..#.........#.#......## +#..#.................#.....#... +..#............#........#...#.. +##.##.......#.#....#..#....##.# +..##...#.#.....#......#........ +......#.##.........##...#...... +......##.#......#.##....##.#..# +.#.#......####.#.#.#.#..#...... +..#.#....#...###....#.#...###.. +.#.#...#....##..###.#..#....... +..#.....##..#............#..#.# +.#...#....#.....#....#..#.#.#.. +..#....#..#......##...##......# +....#.......#.##.#.........#..# +#............#...##.....#..##.. +......#..#..........#.#..#..... +...........#.#..#...##.#...#..# +.........###..#......##.###.#.. +.....#....#......#...#....##... +..#.......#..#.#.#......#...... +.#....#.....#.#.#.##...#....##. +....#.##.##.......#..#.....#... +.#.....#......#.......#..#..... +....###.....##.....##..#.#...#. +#.......#.#....#.#.#....#...... +#...#..#.#......#...##.#....... +....##.##....#..#.......#..#.#. +.#.##.#.#..#.....#.#.......##.. +..#..#..#..#.###............... +#.#......##....##.#.#.....#.#.. +..##...#.........#.#..#.##..#.. +.........####...#.....##.#..... +..#...................#.###.... +..#.....#..#....#..#........... +.....###.#.........#.#......... +#..#..#........#..#......#..#.. +###..##...#.......#........#.#. +.#.#.#.###.#............##..... +#..............#......#....#.## +.#...#..###...###.#..#.#....... +.###....##.#.......#.#.....###. +.##.....#.#.................... +#..#.....#.....#...#.....#..##. +#.#....##..#......##..#...##..# +...........#....#..#.##.##....# +......#.......##....#.#....#.#. +###..#.#..........#.......#.#.. +..#.#..##....##............##.. +..#.....#..#....###............ +.#...#...##...#..#..#..#.#....# +...#....#........#............. +#.#......#.#.....##..........#. +....#..#...............#...##.. +........#..#....#..#..#..##.... +....#......#.#.#...#.......#.## +.#.....#.#.#........###....#... +.#..#.......#...........#...#.. +#.#.#####..#......#...#.#.###.. +...##...#.#.....#..#...#...#... +..#....#.....#..#....#.#.....#. +....#.......#.....#........###. +..##..........#...###.......#.. +#.#.##..#........##...#.#...... +....##...#......#..........#.#. +#.......#..#.##.............#.. +......#..........#...#....#...# +#.#.....#.##.#.#.............## +#...#.........##.##......#.##.. +.........##.....#....#...##..#. +#.#...##.#...#.....##...#..#..# +......##.#.....#.#.....#.##.... +....#.............#...#.......# +.#......##...#.#...#.##........ +...#..#..#...........#..#..#.#. +.#...#...........#.#.##....#... +..#...#...#.#..#....#..#..#.... +..###..##..#..#.........#.#..#. +....#.##.#...#.......#...#..... +.#.#.................#.......#. +.#..#.....#.##...#.#.....#...#. +.#.......#...#....#.......#.... +###....##....#..#...#.#..##.... +.........#.#.#.#...###.......## +....##.......#......#......##.. +......##.###.#..#...#.#.#.#.... +.#.###.#.#......#.#.......##... +.#.....##..#.#.....#...#.##.... +.#..##.#.....#........###...#.# +.......#.#...........#........# +..........#...##..##.......#.#. +...#..#..#...#....#.#......#.#. +....#...#..#....#....#.#.##.... +...#.#...##...#...##..#........ +..#........#...##.#...##.#.#.#. +...##.#..#.......###.#.#.#..... +..##......#.#.#.........###.#.. +.......#.#...##...#.#.......#.# +.#....##..#..#....#..#...#..... +.#....#.#.......#..#..##.#....# +#.#..##..#.#............#....#. +##..#....#.##.#....#...#..##... +.###.#.#..#...##........###.##. +...........#..#...#..#.#..###.. +.#.#.#...#....#...##.##........ +.....###.........#......#####.. +#.#.#.....#....#..#...#.#.#.#.. +..##.....#..#..#.#.#...#....#.# +......#.##..##..#.#.#.......#.. +...#.#..###.........#........#. +......#.##..####...#...#..#...# +#.......#.........#....#....### +#......#...#........#.##....### +.#.#..............#...#...###.# +.#....####...#..##.###.....#... +.......#......#..#...#..##.#... +...........#.......#........... +..............#...#.#.#.#...##. +.###.....##.#.....#..........#. +##.##......#....##..#.....###.# +#.......#...##...#....##...#... +##.#.##...#....#....#....#..... +.....####...........#.#......#. +......#...#....#..#......#..... +...#...##..........#.......##.# +.#....#..........#.####........ +...##...#..#...##........##..#. +.........##....#...##..#.##.#.. +##.#.....#.......#.....#....... +#..#....#.##.#........#........ +#.#...#...##........#.#.....### +....#...................#.#.#.. +.......#..#.#...#....#.##.#.... +....##...###.#.#.##...#...#.... +.#....#....#...##.#......#...#. +............##..#.#.#........#. +...#....#.....#......#........# +...#.#.....#.##.....#....#...#. +.....#..##.......#.##.......#.# +........##................#.... +....#..###...##.#..#...#......# +.#.#.......#.......#....##.#..# +..#........#............#...... +..##.......#..#..#....#....#..# +#...###.......#.##...#......... +.....#...#...#..##..#....#..#.. +.##.#..#...##.........###.#.... +..#.#..#...#...####.#...#.#.#.# +#....#..###.....#......#.##..## +##......#...##...###......#.##. +...........#.....##...#...#...# +..#..#.#.....#..#.....###...#.. +.............#..........###...# +....##............#....###.##.# +..##.#..##.....#.#.........#.#. +....#.#...........####......... +.##.###.##.#.#......#.##.#.#... +.....##.........#..#.......#... +...........#.........#....###.. +...#.#..#..........#.....#..#.. +.#..###.......##........#.#.... +.#...###.....#..#.#..#...#.##.. +##...###.#.#....#......#...#..# +....#.......#..#..##..#.#...... +#.#......#.##..#......#..#....# +....#..#..#.....#.#......#..#.. +..#...###......##.............# +..#....####...##.#...##.#...... +.....#.......###............... +.......#...#.#.......#.#.##.### +.#.#...#.....#...##.........#.. +..#..........#..#.........##... diff --git a/day3/main.zig b/day3/main.zig new file mode 100644 index 0000000..e12163d --- /dev/null +++ b/day3/main.zig @@ -0,0 +1,134 @@ +const std = @import("std"); + +pub fn main() !void { + var allocator = std.heap.GeneralPurposeAllocator(.{}){}; + var gpa = &allocator.allocator; + + var f = std.fs.File { .handle = try std.os.open("input", std.os.O_RDONLY, 0) }; + var buffer : [1024]u8 = undefined; + + var byte_buffer = std.ArrayList(u8).init(&allocator.allocator); + defer byte_buffer.deinit(); + + var map = std.ArrayList([]u8).init(&allocator.allocator); + defer map.deinit(); + + const stdout = std.io.getStdOut().writer(); + + var read = try f.read(&buffer); + std.log.info("Read {} bytes", .{read}); + while (read != 0) { + var last_pos : usize = 0; + for (buffer) | v, k | { + // We're through the read part of the buffer + if (k >= read) { + break; + } + if (v == '\n') { + try map.append(try std.mem.Allocator.dupe(gpa, u8, byte_buffer.items)); + last_pos = k + 1; + // Reset buffer + byte_buffer.deinit(); + byte_buffer = std.ArrayList(u8).init(&allocator.allocator); + continue; + } + try byte_buffer.append(v); + } + read = try f.read(&buffer); + std.log.info("Read {} bytes", .{read}); + } + + std.log.debug("Map has {} items", .{map.items.len}); + //for (map.items) | v, k | { + // try stdout.print("{s}\n", .{v}); + //} + var results : std.meta.Vector(5, u32) = [_]u32 { + sled(map, 1, 1), + sled(map, 3, 1), + sled(map, 5, 1), + sled(map, 7, 1), + sled(map, 1, 2), + }; + std.log.info("Hit {} trees on slope 1,1", .{results[0]}); + std.log.info("Hit {} trees on slope 3,1", .{results[1]}); + std.log.info("Hit {} trees on slope 5,1", .{results[2]}); + std.log.info("Hit {} trees on slope 7,1", .{results[3]}); + std.log.info("Hit {} trees on slope 1,2", .{results[4]}); + std.log.info("Multiple of each slop hits: {}", .{@reduce(.Mul, results)}); +} + +fn sled(map: std.ArrayList([]u8), right: usize, down: usize) u32 { + var map_height : usize = map.items.len; + var map_width : usize = map.items[0].len; + var x : usize = 0; + var y : usize = 0; + var n_trees : u32 = 0; + while (y < map_height) { + var char : u8 = map.items[y][x]; + std.log.debug("{},{} : {}", .{x, y, char}); + if (char == '#') { + n_trees += 1; + } + y += down; + x += right; + x %= map_width; // loop around + } + return n_trees; +} + +fn parse_policy(line: []u8) Policy { + var min : u32 = 0; + var max : u32 = 0; + var char : u8 = 0; + var pass : []u8 = undefined; + + var start : usize = 0; + var got_min = false; + var got_max = false; + for (line) | v, k | { + if (v == '-') { + min = atoi(line[start..k]); + start = k + 1; + got_min = true; + } + if (v == ' ' and !got_max) { + max = atoi(line[start..k]); + start = k + 1; + got_max = true; + } + if (v == ':') { + char = line[start..k][0]; + start = k + 2; + } + if (k == line.len-1) { + pass = line[start..]; + } + } + return Policy { + .min = min, + .max = max, + .value = char, + .password = pass, + }; +} + +fn part2() void { +} + +fn part1() void { +} + +fn atoi(a: []u8) u32 { + var i : u32 = 0; + for(a) |v, k| { + if (! std.ascii.isDigit(v)) { + std.log.warn("Byte {x} is not a digit", .{v}); + continue; + } + // 48 is '0' in ascii + std.debug.assert(v >= 48 and v < 58); + i += @as(u32, (v - 48) * std.math.pow(u32, 10, @intCast(u32, a.len - k - 1))); + } + //std.log.debug("{x} --> {}", .{a, i}); + return i; +} diff --git a/day4/build.zig b/day4/build.zig new file mode 100644 index 0000000..7f5f614 --- /dev/null +++ b/day4/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day4", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day4/input b/day4/input new file mode 100644 index 0000000..fdedcca --- /dev/null +++ b/day4/input @@ -0,0 +1,1138 @@ +eyr:2028 iyr:2016 byr:1995 ecl:oth +pid:543685203 hcl:#c0946f +hgt:152cm +cid:252 + +hcl:#733820 hgt:155cm +iyr:2013 byr:1989 pid:728471979 +ecl:grn eyr:2022 + +hgt:171cm +iyr:2013 pid:214368857 hcl:#cfa07d byr:1986 eyr:2028 ecl:grn + +hgt:167cm cid:210 ecl:brn pid:429131951 hcl:#cfa07d eyr:2029 iyr:2010 +byr:1945 + +hcl:#888785 iyr:2015 +hgt:170cm pid:893805464 ecl:amb byr:1966 eyr:2028 + +hgt:170cm ecl:amb +hcl:#c0946f eyr:2020 iyr:2016 pid:725010548 +byr:1928 + +byr:1999 hcl:#888785 +eyr:2026 +ecl:hzl +iyr:2016 hgt:193cm pid:170608679 + +eyr:2024 iyr:2016 hcl:#cfa07d ecl:grn byr:2001 pid:391942873 cid:104 hgt:164cm + +iyr:2019 +eyr:2025 pid:138912840 byr:1996 +hgt:166cm +hcl:#888785 ecl:grn + +iyr:2023 hcl:a58381 pid:#401a29 eyr:1940 +byr:1920 +ecl:utc hgt:183cm + +pid:493510244 ecl:gry hgt:153cm byr:1950 cid:181 eyr:2028 +hcl:#ceb3a1 +iyr:2020 + +iyr:2018 pid:074340974 hgt:182cm +hcl:#866857 byr:1988 ecl:hzl eyr:2023 + +hcl:#866857 ecl:oth byr:1977 iyr:2014 hgt:180cm pid:860745884 +eyr:2023 + +eyr:2026 pid:815594641 +ecl:gry iyr:2012 byr:1992 hgt:161cm hcl:#b6652a + +ecl:gry cid:338 eyr:2021 pid:777099878 hgt:193cm hcl:#efcc98 +byr:1945 +iyr:2015 + +iyr:2016 byr:1934 hcl:#b6652a +hgt:162cm ecl:hzl +cid:296 +pid:742610207 +eyr:2022 + +ecl:#ba3242 +hgt:80 byr:1931 +pid:550004054 iyr:1949 eyr:1944 hcl:fb3859 + +ecl:amb eyr:2024 +byr:1965 iyr:2010 pid:094059049 +hcl:#fffffd +hgt:168cm + +pid:159cm +iyr:1923 eyr:2032 hcl:701107 cid:343 ecl:gmt byr:2010 +hgt:177cm + +eyr:2021 +ecl:grn byr:1991 +hcl:#fffffd hgt:167cm pid:243218792 iyr:2019 + +hgt:157cm byr:2017 ecl:grn iyr:2012 +eyr:2030 hcl:#18171d pid:173cm + +pid:260101979 hgt:187cm eyr:2033 ecl:lzr +byr:2020 hcl:1058ce cid:133 iyr:2012 + +hcl:#7d3b0c +pid:307828343 byr:2001 +cid:317 iyr:2013 +eyr:2029 + +pid:472940417 eyr:1960 +hgt:181cm hcl:#c0946f cid:269 +byr:2014 +iyr:1956 + +hcl:#18171d eyr:2021 byr:2001 pid:421443124 +ecl:brn iyr:2020 hgt:156cm + +cid:347 hgt:60in pid:359783692 byr:1932 +ecl:hzl +eyr:2023 +hcl:#888785 iyr:2019 + +pid:230915137 +byr:1999 +iyr:2011 eyr:2020 hcl:#7d3b0c ecl:hzl +hgt:164cm + +iyr:1989 +byr:2008 +hgt:154cm +eyr:2028 pid:280298169 +cid:208 +ecl:oth + +byr:1954 iyr:2017 +ecl:hzl +eyr:2026 +pid:966957581 hgt:175cm hcl:#18171d + +pid:308053355 hgt:192cm eyr:2022 ecl:amb cid:146 iyr:2015 +byr:1991 hcl:#c0946f + +hcl:#a97842 pid:244441133 iyr:2019 +hgt:182cm +ecl:amb cid:172 byr:1973 eyr:2029 + +iyr:2017 +byr:1985 cid:215 +ecl:blu hcl:#623a2f hgt:160cm pid:157856689 eyr:2030 + +eyr:2027 ecl:#d72f9b hgt:162cm +iyr:2018 hcl:#a97842 +byr:1945 +pid:131243258 + +hcl:#b3f2f0 pid:204254353 cid:169 eyr:2020 +iyr:2013 hgt:172cm ecl:blu byr:1950 + +byr:1957 hcl:#c0946f hgt:152cm ecl:blu eyr:2027 pid:325917033 +iyr:2010 + +ecl:oth byr:1950 hgt:166cm pid:007352351 +hcl:#b6652a +iyr:2020 +eyr:2024 + +hgt:165 eyr:2030 iyr:2027 +ecl:#1a34f1 pid:2894591864 byr:2024 hcl:z + +byr:1971 ecl:oth +hgt:163cm eyr:2021 pid:040443396 + +hgt:177cm +byr:1955 pid:585735590 iyr:2010 ecl:grn eyr:2024 +hcl:#602927 + +cid:74 +iyr:2010 +pid:014378493 hgt:174cm eyr:2020 +ecl:grn byr:1944 + +pid:404141049 +byr:1947 ecl:blu hgt:170cm iyr:2011 +eyr:2028 +hcl:#cfa07d + +ecl:hzl byr:1938 pid:235085606 cid:180 hcl:8fb74c eyr:2021 hgt:73 iyr:2015 + +pid:860077423 ecl:gry +hcl:#3e845b +hgt:167cm byr:1933 iyr:2016 eyr:2021 + +hcl:#733820 hgt:66in eyr:1920 +ecl:oth byr:1941 pid:979460474 iyr:2010 +cid:247 + +hcl:#cfa07d ecl:#13bd36 hgt:193cm eyr:2027 pid:181cm byr:1952 iyr:1951 + +ecl:brn hcl:#602927 +hgt:161cm +eyr:2027 pid:822749462 byr:1946 +iyr:2014 + +byr:2013 +iyr:2021 ecl:zzz eyr:2032 hgt:193in hcl:#a97842 pid:163cm + +eyr:2029 cid:140 +byr:1984 +iyr:2018 hgt:187cm hcl:#b6652a pid:910674579 + +ecl:hzl hgt:173cm pid:096026282 +iyr:2014 byr:1956 +eyr:2029 hcl:#866857 + +eyr:2024 iyr:2019 pid:301205967 +cid:276 byr:1957 hcl:#3fec29 ecl:gry hgt:165cm + +iyr:2013 ecl:oth hgt:177cm hcl:#6b5442 eyr:2021 byr:1962 pid:006347857 + +ecl:grt byr:1983 hcl:#cfa07d +hgt:163cm +eyr:1979 +iyr:1958 pid:796395720 + +iyr:2011 pid:415403544 hcl:#c0946f byr:1990 ecl:oth eyr:2023 hgt:73in +cid:107 + +hgt:166cm eyr:2029 iyr:2015 +hcl:#c0946f ecl:brn +byr:1964 +pid:469449137 + +eyr:2023 +byr:1969 iyr:2010 hgt:163cm hcl:#a97842 pid:570942274 +ecl:blu + +hcl:#623a2f +ecl:brn hgt:183cm pid:524675399 +eyr:2020 iyr:2012 byr:1981 + +iyr:2017 hcl:#fffffd eyr:2026 +ecl:gry byr:1979 hgt:152cm pid:505790864 + +hgt:68in +hcl:#c0946f iyr:2012 +eyr:2023 pid:933562997 byr:1993 +ecl:grn + +pid:267705171 +hgt:166cm byr:1970 iyr:2019 hcl:#341e13 ecl:oth +eyr:2030 + +ecl:brn byr:1972 eyr:2026 pid:774637408 hgt:189cm iyr:2015 hcl:#341e13 + +hgt:175cm eyr:2026 byr:2001 iyr:2020 +hcl:#733820 ecl:blu pid:686996160 + +hgt:190cm hcl:#c0946f pid:228444464 byr:1987 +iyr:2020 eyr:2030 +ecl:blu + +byr:1990 hgt:179cm +pid:885359438 eyr:2028 iyr:2010 ecl:amb +hcl:#67067e + +byr:1945 hcl:#866857 eyr:2022 iyr:2019 +pid:708146656 cid:65 +hgt:172cm ecl:brn + +ecl:hzl hgt:191cm +cid:260 pid:010716679 iyr:2011 eyr:2029 byr:1920 hcl:#efcc98 + +iyr:2012 +cid:313 pid:264894705 byr:1951 hcl:#733820 eyr:2030 ecl:blu +hgt:178cm + +eyr:2027 pid:790510379 +iyr:2013 +ecl:amb +hgt:186cm +hcl:#866857 +byr:1926 + +pid:535750794 hgt:191cm iyr:2016 hcl:#a97842 eyr:2029 +ecl:hzl byr:1923 + +byr:2023 pid:#eb4c2a iyr:1939 ecl:grn hcl:06d729 hgt:73 eyr:2038 + +pid:792365221 iyr:2013 ecl:oth +byr:1997 +hgt:170cm hcl:#efcc98 +eyr:2022 + +hgt:192cm pid:874141668 +byr:1957 iyr:2015 +ecl:gry + +hcl:#b6652a pid:770238761 eyr:2029 byr:1934 iyr:2013 +ecl:blu cid:177 +hgt:184cm + +ecl:hzl eyr:2024 hgt:72in pid:546439165 +iyr:2013 +hcl:#c0946f cid:223 byr:1989 + +byr:1985 +ecl:utc pid:#ff1cbf +iyr:2018 hcl:#866857 hgt:169cm eyr:2026 cid:194 + +hgt:189cm +eyr:2026 pid:120642045 ecl:blu +hcl:#602927 cid:177 +byr:1954 iyr:2012 + +pid:314624973 +byr:1959 iyr:2015 hcl:#c0946f ecl:grn +eyr:2027 cid:349 hgt:156cm + +byr:1978 +iyr:2020 hgt:150cm cid:266 eyr:2026 +pid:443912835 hcl:#b6652a + +hgt:174cm byr:1974 pid:729198828 +ecl:brn iyr:2014 +hcl:#18171d eyr:2027 + +pid:472891001 ecl:xry +hgt:96 hcl:1b816a iyr:1954 +byr:2015 eyr:2037 + +byr:1966 eyr:2022 +iyr:2014 +pid:848187688 hcl:#602927 ecl:gry hgt:152cm + +hgt:129 eyr:2037 cid:61 iyr:2009 byr:2027 hcl:#c0946f +pid:3569865 +ecl:#4e3d72 + +ecl:gry +eyr:2021 pid:234525998 byr:1964 hgt:168cm cid:140 +hcl:#7d3b0c iyr:2013 + +ecl:xry +cid:86 +hgt:172in +byr:1972 +iyr:2015 hcl:#7d3b0c pid:833809421 eyr:2030 + +pid:444365280 hgt:72in +ecl:brn +hcl:#b6652a byr:1985 eyr:2027 iyr:2012 + +iyr:2010 byr:2013 hgt:181cm eyr:2021 +pid:072317444 +ecl:oth hcl:#866857 +cid:118 + +pid:4354408888 iyr:2012 +hcl:#b6652a cid:104 +hgt:96 eyr:2020 +byr:1933 ecl:amb + +eyr:2023 ecl:gry hcl:#a97842 pid:287719484 byr:1994 +iyr:2011 hgt:163cm cid:299 + +byr:1932 +hgt:170cm +iyr:2014 pid:777844412 eyr:2040 hcl:#cfa07d ecl:brn + +cid:160 hgt:191cm eyr:2020 iyr:2012 +ecl:brn byr:1981 pid:077027782 + +cid:182 hgt:176cm hcl:#7d3b0c +eyr:2030 ecl:blu pid:096742425 iyr:2010 byr:1963 + +byr:2010 cid:337 hcl:z pid:525126586 iyr:2010 hgt:73cm eyr:2040 ecl:blu + +ecl:gry +iyr:2017 +hgt:185cm hcl:#6b5442 byr:1993 +eyr:2029 pid:366083139 cid:343 + +eyr:2028 ecl:amb +pid:878658841 byr:1960 hgt:179cm hcl:#18171d iyr:2010 + +pid:537309261 iyr:2015 hgt:187cm +hcl:#4fe831 eyr:2026 +ecl:blu byr:1982 + +ecl:brn hgt:163cm +eyr:2021 hcl:#6b5442 byr:1979 iyr:2013 pid:924759517 + +pid:683651053 hcl:#179c55 +ecl:blu byr:1989 hgt:190cm +iyr:2016 +eyr:2030 + +ecl:grn +iyr:2016 hcl:#b6652a +byr:1994 eyr:2020 pid:448424292 hgt:174cm + +hgt:157cm +ecl:grn +byr:2000 +pid:734707993 hcl:#341e13 iyr:2020 + +hcl:#341e13 hgt:156cm iyr:2020 pid:299213638 +byr:1947 ecl:hzl eyr:2023 + +hgt:193cm hcl:#b6652a iyr:2014 ecl:hzl byr:1947 eyr:2025 +pid:044486467 + +byr:1975 +hgt:159cm +ecl:grn pid:318489576 eyr:2029 hcl:#6b5442 +iyr:2020 + +iyr:2018 pid:512971930 +hcl:#888785 byr:1966 eyr:2024 hgt:158cm +cid:100 ecl:gry + +ecl:amb eyr:2030 hgt:171cm hcl:#efcc98 pid:800921581 cid:339 byr:1980 iyr:2017 + +iyr:2019 cid:172 +hgt:152cm +eyr:2022 ecl:oth hcl:#602927 byr:1960 + +iyr:2019 pid:762312913 +eyr:2029 +ecl:hzl +hcl:#6b5442 +byr:1940 +hgt:169cm cid:289 + +eyr:2022 ecl:gry byr:1976 +iyr:2020 hcl:#733820 hgt:172cm pid:040331561 + +hgt:171cm ecl:brn iyr:2013 eyr:2027 byr:1940 hcl:#a6e32a pid:223986941 + +hcl:#341e13 +eyr:2028 ecl:amb byr:1942 +hgt:166cm pid:435382099 iyr:2020 + +cid:298 pid:641326891 +hgt:155cm hcl:#623a2f ecl:grn byr:1981 eyr:2025 +iyr:2010 + +iyr:2015 pid:472000322 eyr:2021 byr:1977 +ecl:gry hgt:165cm cid:270 + +eyr:2027 byr:1956 +pid:193087729 hcl:#ceb3a1 +cid:213 hgt:193cm ecl:oth + +iyr:2014 +byr:1971 cid:96 +hgt:74in +pid:136003336 +eyr:2020 ecl:hzl hcl:#efcc98 + +hcl:z pid:097595072 ecl:amb +iyr:2015 byr:2021 +eyr:2039 hgt:188cm + +pid:74823273 +hcl:#341e13 +cid:166 hgt:182cm byr:2026 iyr:2027 ecl:amb +eyr:2032 + +byr:1932 eyr:2022 pid:367248062 hgt:182cm ecl:oth hcl:#c0946f +iyr:2020 + +hgt:72cm +iyr:2015 cid:234 byr:2013 +ecl:brn pid:9401866358 + +pid:022399779 iyr:2010 byr:1969 hcl:#6b5442 +ecl:grn eyr:2020 +hgt:189cm + +byr:1971 iyr:2011 cid:161 ecl:brn hgt:153cm +eyr:2028 pid:819137905 hcl:#cfa07d + +cid:161 hgt:159cm iyr:2011 pid:815860793 hcl:#a97842 ecl:grn byr:1972 eyr:2027 + +ecl:amb +hgt:118 byr:1981 iyr:2019 +hcl:#a97842 eyr:2021 pid:270790642 + +hcl:#b6652a pid:732272914 eyr:2030 hgt:183cm ecl:hzl +byr:1934 +iyr:2018 + +eyr:2027 +pid:877388498 hcl:#ceb3a1 +byr:1925 cid:236 ecl:grn +iyr:2019 hgt:191cm + +eyr:2020 ecl:brn hcl:#fffffd hgt:181cm pid:801311341 byr:1986 iyr:2010 + +byr:1925 cid:179 ecl:hzl pid:360641953 eyr:2030 +hgt:171in iyr:2015 +hcl:#602927 + +cid:83 hgt:181cm +eyr:2028 byr:1941 pid:165937945 hcl:#888785 iyr:2014 +ecl:grn + +hcl:#a97842 byr:1928 +iyr:2013 +pid:870072019 hgt:76in +ecl:oth cid:127 eyr:2026 + +cid:169 +hgt:187cm pid:008180128 iyr:2013 byr:1991 hcl:#7d3b0c ecl:hzl eyr:2026 + +ecl:amb +eyr:2027 hgt:155cm pid:586151564 iyr:2010 +byr:1949 +hcl:#18171d + +hgt:167cm +iyr:2010 byr:1982 ecl:amb +cid:235 pid:557737957 eyr:2020 +hcl:#ceb3a1 + +ecl:grn byr:1939 hcl:#733820 +eyr:2026 pid:993218958 iyr:2010 +hgt:150cm + +hgt:68in ecl:blu +byr:1965 iyr:2017 pid:854858050 eyr:2021 + +ecl:gry pid:347763159 eyr:2024 iyr:2017 byr:1961 +hgt:151cm +hcl:#623a2f + +ecl:utc hcl:#602927 +pid:#1408ff byr:1941 +cid:82 +iyr:2015 hgt:185cm eyr:2028 + +iyr:2020 hgt:151cm eyr:2025 +byr:1934 hcl:#888785 +pid:396545094 ecl:oth + +hgt:153cm +eyr:2028 hcl:#733820 ecl:gry iyr:2019 +pid:081352630 byr:1943 + +eyr:2030 +iyr:2011 +ecl:grn pid:313741119 +hgt:161cm byr:1946 +hcl:#a97842 + +byr:1968 ecl:gry +pid:742357550 +eyr:2024 hcl:#18171d iyr:2018 +hgt:157cm + +pid:387505919 +ecl:oth byr:1945 +iyr:2014 +hgt:190cm hcl:#888785 +eyr:2028 + +iyr:2017 hgt:175cm +byr:1989 eyr:2022 +hcl:#b6652a pid:499016802 ecl:gry cid:136 + +pid:490807331 iyr:2016 +hcl:#ceb3a1 +hgt:150cm eyr:2026 +ecl:amb byr:1967 + +iyr:2011 +hgt:155in +hcl:#ceb3a1 pid:118497416 +eyr:2029 byr:2011 ecl:oth + +hcl:03a888 byr:2029 +ecl:#6f7292 eyr:1969 iyr:2028 hgt:162cm pid:73551266 + +iyr:2016 hgt:182cm +byr:1966 ecl:grn eyr:2022 +hcl:#fffffd pid:061720787 + +byr:1971 hcl:z +eyr:2035 pid:158cm +ecl:#d3ec19 + +hcl:#623a2f hgt:156cm eyr:2028 +ecl:brn iyr:2013 +byr:1980 pid:112283719 + +eyr:2020 +byr:1956 iyr:2013 +hcl:#6b5442 +ecl:grn pid:876589775 hgt:179cm + +hgt:138 +byr:2013 eyr:2040 iyr:2028 cid:197 ecl:#8844fd pid:8524414485 +hcl:z + +eyr:2040 +hgt:173in hcl:z pid:#654654 byr:2016 iyr:2022 ecl:#452d22 + +iyr:2012 cid:265 eyr:2021 hgt:192cm +byr:1993 ecl:brn + +eyr:2026 hcl:#888785 +hgt:158cm byr:1942 +iyr:2015 +ecl:amb pid:546984106 + +iyr:2019 +ecl:hzl +byr:1922 eyr:2028 hgt:172cm +pid:465052232 hcl:#602927 + +pid:710362693 eyr:2023 +hcl:#c0946f byr:1951 ecl:grn +iyr:2019 hgt:190cm + +iyr:2024 pid:#a08e69 +hcl:z byr:1966 ecl:#7b9978 eyr:2035 +hgt:69cm + +hcl:#efcc98 +pid:164cm +iyr:2010 cid:194 hgt:71cm byr:1923 eyr:2026 + +hgt:65in +iyr:2019 byr:1969 pid:466669360 eyr:2022 ecl:brn hcl:#b6652a + +pid:42472559 hcl:#6f5763 +eyr:2035 +iyr:2014 hgt:154in byr:1939 ecl:grt cid:323 + +pid:715680334 hgt:166cm cid:283 +byr:1982 +iyr:2015 eyr:2030 hcl:#ceb3a1 ecl:grn + +eyr:2018 iyr:2029 +ecl:brn +byr:2022 pid:#ff6df1 +hcl:z +hgt:68cm + +pid:094541122 +eyr:2024 byr:1940 +ecl:amb iyr:2019 hgt:64in hcl:#733820 + +hgt:163in +eyr:2022 ecl:utc hcl:#ceb3a1 iyr:2028 + +ecl:gry pid:53552934 +hgt:193 byr:2021 +eyr:2028 +iyr:2011 cid:98 hcl:90c63f + +eyr:2024 hcl:#cfa07d ecl:brn +iyr:2019 byr:1993 hgt:156cm pid:449484188 + +iyr:2020 +hgt:164cm hcl:#623a2f +pid:820731743 eyr:2025 +byr:1997 ecl:hzl + +hcl:47242b ecl:utc hgt:156 +pid:#9a9903 eyr:2030 iyr:1990 +byr:2011 + +hcl:#602927 +hgt:189cm +pid:949021883 iyr:2014 ecl:oth cid:327 +eyr:2027 byr:1953 + +hgt:189cm cid:301 +byr:1982 +ecl:grn +eyr:2028 hcl:#733820 pid:796040143 iyr:2015 + +cid:169 iyr:2013 pid:355177646 byr:1988 +ecl:oth +hcl:#cfa07d +hgt:185cm eyr:2022 + +pid:563150261 eyr:2020 ecl:brn byr:1996 hcl:#7d3b0c iyr:2018 hgt:189cm cid:84 + +cid:188 eyr:2027 +byr:1944 +pid:486184923 +iyr:2010 hgt:193cm hcl:#341e13 ecl:oth + +iyr:2019 +byr:1969 hgt:152cm pid:430698432 ecl:gry hcl:#888785 eyr:2026 cid:293 + +ecl:gry +cid:270 hcl:#602927 iyr:2017 hgt:151cm eyr:2029 pid:051398739 byr:1954 + +ecl:oth eyr:2030 pid:024655030 +hgt:184cm byr:1969 +hcl:#18171d + +eyr:2030 +pid:899973263 hgt:178cm byr:1987 hcl:#cfa07d iyr:2012 +ecl:amb + +iyr:1958 hgt:165cm pid:377677319 +ecl:grt eyr:2032 byr:2025 +hcl:bbfbe2 + +ecl:blu +iyr:2016 +hgt:152cm byr:1964 +hcl:#c4f777 +eyr:2021 +pid:044307549 cid:80 + +ecl:brn pid:330836320 +byr:1963 cid:217 hgt:169cm +eyr:2024 +iyr:2019 hcl:#ceb3a1 + +byr:1976 eyr:2027 +pid:452662874 hgt:192cm ecl:oth iyr:2018 hcl:#602927 + +eyr:2027 hgt:183cm ecl:brn iyr:2017 hcl:#341e13 pid:827463598 + +ecl:brn pid:930667228 cid:310 iyr:2020 +eyr:2027 hgt:160cm byr:1932 hcl:#c0946f + +pid:955804028 byr:1983 +hcl:#fffffd +hgt:178cm iyr:2013 +eyr:2021 ecl:gry + +hgt:189cm eyr:2021 pid:430243363 iyr:2015 hcl:#ceb3a1 +byr:2000 ecl:oth cid:284 + +pid:436671537 hcl:#cfa07d iyr:2011 cid:106 hgt:171cm +ecl:blu eyr:2021 byr:1943 + +eyr:2028 hgt:169cm +iyr:2015 pid:177443573 byr:1945 +hcl:#c0946f ecl:gry + +hcl:#fffffd byr:1995 eyr:2021 +ecl:grn +hgt:192cm iyr:2010 pid:754912745 + +pid:330882171 iyr:2015 cid:211 ecl:grn byr:1961 eyr:2021 hcl:z +hgt:169cm + +byr:1926 eyr:2029 pid:178633665 cid:141 iyr:2017 hcl:#b99eb9 +hgt:178cm ecl:brn + +eyr:2022 ecl:hzl hcl:#cfa07d hgt:168cm iyr:2015 +byr:1982 pid:645675448 + +ecl:blu byr:1980 hgt:186cm iyr:2010 cid:94 hcl:#c0946f eyr:2027 pid:384440210 + +cid:309 hcl:#602927 hgt:192cm eyr:2027 ecl:amb +pid:527932745 iyr:2012 byr:1982 + +cid:132 +ecl:blu iyr:2016 +eyr:2027 byr:1940 hcl:#341e13 hgt:166cm pid:613386501 + +pid:360563823 eyr:2028 byr:1990 iyr:2016 +ecl:blu cid:287 hgt:162cm hcl:#888785 + +hgt:161cm +byr:2002 +hcl:#623a2f pid:535361632 +ecl:gry eyr:2021 iyr:2013 + +hgt:67in +byr:1967 +cid:333 hcl:#cfa07d +iyr:2012 eyr:2024 ecl:hzl pid:538161833 + +ecl:#2bc145 eyr:1963 iyr:2030 +cid:241 hcl:2fc384 hgt:156in pid:2899917140 +byr:2005 + +eyr:2021 pid:021590229 ecl:gry +hgt:164cm iyr:2013 hcl:#efcc98 byr:1985 + +ecl:hzl byr:1943 +cid:279 pid:979130395 +iyr:2011 +hgt:165cm +eyr:2021 +hcl:#f331b3 + +hgt:161cm +hcl:#888785 byr:1981 pid:835477382 eyr:2025 iyr:2012 +cid:348 +ecl:blu + +hgt:159cm hcl:b4ce6a cid:319 eyr:2035 iyr:1965 ecl:oth +byr:2010 pid:158cm + +iyr:2020 +eyr:2026 ecl:grn hcl:#a97842 pid:126915503 +hgt:178cm byr:1986 + +hgt:184cm ecl:hzl +cid:67 iyr:2020 eyr:2026 pid:168775568 byr:1944 hcl:#a97842 + +hcl:#fffffd iyr:2016 pid:379463363 +ecl:oth +hgt:179cm byr:1988 +eyr:2028 + +hcl:#cfa07d ecl:amb eyr:2030 pid:320360020 +iyr:2016 hgt:172cm byr:1961 + +cid:221 hcl:#cfa07d byr:1946 eyr:2024 ecl:oth pid:066950409 hgt:173cm +iyr:2020 + +hcl:#602927 eyr:2028 ecl:gry iyr:2019 pid:583204134 byr:1966 hgt:178cm + +byr:1930 +iyr:2020 ecl:hzl +hcl:#ceb3a1 pid:285751767 cid:287 eyr:2023 hgt:192cm + +eyr:2024 +ecl:hzl cid:87 iyr:2015 +hgt:152cm hcl:#18171d pid:959574669 +byr:1990 + +pid:45938863 +hcl:49c7ce cid:349 hgt:181cm +eyr:2023 ecl:grn iyr:2015 byr:1948 + +hcl:#866857 iyr:2012 ecl:amb cid:132 byr:1955 hgt:162cm pid:597748286 eyr:2023 + +pid:293364535 byr:2024 +hgt:177cm eyr:2039 +iyr:2020 hcl:#dae928 ecl:hzl + +pid:212659709 iyr:2018 +hgt:188cm +hcl:#efcc98 byr:1974 eyr:2029 ecl:oth cid:244 + +cid:140 +ecl:amb +eyr:2022 hgt:181cm hcl:#efcc98 +byr:1943 +iyr:2016 + +cid:71 hgt:151cm pid:5063555219 eyr:2023 ecl:hzl +byr:2019 +hcl:#7d3b0c iyr:2023 + +hgt:157in pid:#298b06 iyr:2030 ecl:#66a631 eyr:2035 hcl:z byr:2019 + +hgt:190cm iyr:1943 +pid:644021656 hcl:#6b621c +ecl:oth eyr:2021 byr:1923 + +ecl:hzl iyr:2012 eyr:2023 pid:881271720 hcl:#ceb3a1 hgt:172cm +byr:1957 + +iyr:2017 hcl:#888785 +ecl:amb hgt:170cm byr:1967 pid:198856675 eyr:2027 + +eyr:2026 +ecl:gry +pid:834980363 hcl:#733820 byr:1930 +hgt:175cm iyr:2018 +cid:214 + +hcl:#efcc98 eyr:2029 iyr:2010 pid:980087545 +ecl:brn hgt:157cm + +pid:57513658 iyr:2011 byr:1993 ecl:brn eyr:2027 hcl:#6b5442 hgt:165cm + +ecl:hzl +eyr:2025 +hcl:#733820 +hgt:169cm iyr:2018 cid:328 byr:1999 pid:694719489 + +eyr:2023 +cid:125 byr:1925 +hgt:185cm pid:806769540 iyr:2013 ecl:hzl +hcl:#866857 + +iyr:2010 cid:225 +ecl:hzl eyr:2027 pid:615545523 +hcl:#733820 +byr:1994 +hgt:166cm + +byr:1941 ecl:gry iyr:2019 eyr:2026 hgt:73cm hcl:#602927 +pid:352996721 + +pid:140250433 +eyr:2030 ecl:grn +hcl:#fffffd iyr:2011 byr:1937 hgt:185cm + +ecl:gry byr:2002 iyr:2017 hcl:#b6652a cid:261 pid:178cm eyr:2022 hgt:166cm + +ecl:grn iyr:2010 eyr:2022 byr:1924 +pid:214641920 hcl:#ceb3a1 +hgt:155cm + +hcl:z pid:150cm ecl:utc iyr:1981 +eyr:2034 +hgt:156in cid:260 byr:2027 + +byr:1987 hgt:66in +eyr:2021 pid:876757018 iyr:2015 hcl:d596e4 ecl:hzl + +cid:116 ecl:oth hgt:180cm +iyr:2020 byr:1942 hcl:#2fc31f +eyr:2027 +pid:253569416 + +pid:509387921 +eyr:2022 +hcl:#888785 ecl:oth hgt:193cm +iyr:2012 cid:97 +byr:1975 + +hcl:#18171d hgt:190cm pid:062827417 byr:1939 +iyr:2019 eyr:2022 +ecl:hzl + +iyr:2025 +byr:2028 +hgt:165in eyr:2027 pid:6259332452 +hcl:#478251 + +iyr:2018 eyr:2026 pid:523863237 +hgt:187cm +ecl:oth +byr:1944 +hcl:#a97842 + +hgt:181cm hcl:#733820 pid:923996316 +cid:110 +iyr:2011 byr:1949 ecl:blu eyr:2023 + +pid:304792392 hcl:487823 eyr:2020 +hgt:70cm byr:2024 +iyr:1953 +ecl:blu + +pid:142200694 +ecl:oth hcl:#888785 eyr:2028 +hgt:152cm byr:1954 iyr:2018 + +ecl:utc +iyr:2015 byr:1932 hcl:#623a2f +eyr:2027 hgt:183cm pid:036300444 + +iyr:2014 ecl:hzl byr:1935 hgt:190cm hcl:#efcc98 pid:945893288 +eyr:2025 + +hcl:#efcc98 pid:252639104 hgt:188cm +byr:1998 iyr:2019 ecl:grn +eyr:2023 + +hcl:58aa4a byr:1930 hgt:193cm +iyr:1998 cid:196 ecl:brn +eyr:2032 + +iyr:2015 ecl:hzl +hgt:193cm pid:653794674 eyr:2024 +hcl:#fffffd byr:1921 + +pid:980680460 byr:1962 ecl:blu +iyr:2013 +hcl:#72cace +eyr:2030 +hgt:180cm + +eyr:2025 +hgt:182cm hcl:#ceb3a1 iyr:2010 byr:1945 cid:314 pid:597769706 ecl:amb + +pid:761757504 +hcl:#888785 hgt:161cm iyr:2015 +byr:1939 eyr:2025 +cid:326 ecl:blu + +ecl:gry +hgt:163cm byr:1981 +pid:330818500 iyr:2017 eyr:2024 +cid:71 hcl:#888785 + +pid:190cm cid:267 iyr:2015 ecl:brn +hcl:869252 +byr:1935 hgt:142 eyr:2033 + +cid:239 +eyr:2038 ecl:lzr hcl:z iyr:1987 pid:4632768239 +hgt:162in + +pid:158038227 ecl:brn byr:1995 eyr:2028 hcl:#efcc98 +cid:252 iyr:2021 +hgt:184cm + +eyr:2027 +cid:124 ecl:amb hgt:165cm byr:1949 +pid:727126101 iyr:2010 hcl:#602927 + +ecl:grn +byr:1966 pid:184245393 hgt:164cm +eyr:2022 +iyr:2014 hcl:#866857 + +cid:62 hgt:180cm eyr:2027 hcl:#18171d +iyr:2017 ecl:blu byr:1942 pid:930210027 + +ecl:grn hgt:171cm iyr:2017 hcl:#fffffd eyr:2029 byr:1946 pid:863414762 +cid:95 + +eyr:2025 ecl:grn iyr:2019 cid:226 hcl:#b6652a +byr:1932 pid:715708549 +hgt:156cm + +pid:505158338 iyr:2019 byr:1981 hgt:193cm +hcl:#696a5c cid:57 ecl:hzl eyr:2023 + +byr:1987 +hgt:155cm cid:99 ecl:grn iyr:2010 +hcl:#c0946f eyr:2023 +pid:431067921 + +hgt:190in +hcl:z eyr:2029 pid:74228790 +iyr:2016 byr:2018 ecl:brn + +eyr:2022 +ecl:xry hgt:154cm pid:62205162 +iyr:2014 byr:1936 +cid:61 + +ecl:amb eyr:2026 +byr:1966 cid:95 hcl:#733820 pid:957767251 iyr:2013 hgt:157cm + +byr:1969 +hgt:156cm iyr:2013 ecl:blu hcl:#a97842 +cid:183 +pid:960672229 eyr:2020 + +iyr:2013 +cid:243 eyr:2028 hgt:192cm hcl:#efcc98 +ecl:grn pid:222407433 byr:1978 + +iyr:2014 byr:1935 +eyr:2021 cid:235 pid:#1b34e1 +hcl:#89313f hgt:164cm ecl:blu + +ecl:hzl iyr:2016 cid:327 +byr:1923 pid:695935353 hgt:184cm +hcl:#a97842 +eyr:2028 + +pid:6010745668 +byr:1934 ecl:oth eyr:2020 hgt:164cm +hcl:#733820 +iyr:2016 + +ecl:blu pid:071991002 eyr:2021 byr:1978 cid:321 +hcl:#efcc98 +iyr:2013 hgt:68in + +ecl:grn iyr:2015 pid:137792524 cid:156 +hcl:#efcc98 +eyr:2029 byr:1955 +hgt:165cm + +byr:1949 +hgt:176cm pid:531868428 +hcl:#cfa07d ecl:brn iyr:2014 eyr:2024 + +iyr:1955 cid:108 pid:712137140 byr:2019 eyr:2040 hgt:184cm hcl:220cfe ecl:#551592 + +iyr:2016 eyr:2030 +hgt:177cm cid:137 ecl:brn +hcl:#efcc98 pid:712202745 byr:1938 + +pid:357180007 iyr:2010 ecl:grn +byr:1991 +hcl:#341e13 +eyr:2020 hgt:159cm + +eyr:2023 ecl:grn +hcl:#733820 iyr:2020 byr:1927 hgt:151cm +pid:165936826 + +ecl:gry +pid:794227261 iyr:2014 eyr:2030 +hcl:#18171d +byr:1994 +hgt:162cm + +iyr:2017 eyr:2024 +hcl:#7d3b0c cid:279 +ecl:gry byr:1981 hgt:176cm pid:973822115 + +eyr:2029 +hgt:152cm hcl:#fffffd ecl:amb byr:1946 iyr:2013 +cid:62 pid:005240023 + +iyr:2010 +ecl:amb hcl:#341e13 hgt:184cm +eyr:2027 +pid:976217816 byr:1950 + +ecl:grn hgt:178cm cid:192 hcl:#602927 pid:684333017 eyr:2022 +iyr:2011 byr:1987 + +pid:306960973 ecl:hzl hgt:168cm +byr:1954 iyr:2015 eyr:2029 hcl:#602927 + +hcl:#18171d +byr:1973 ecl:hzl hgt:174cm pid:922891164 +iyr:2013 +eyr:2023 + +byr:1998 hgt:189cm pid:472066200 ecl:gry iyr:2012 eyr:2021 hcl:#c0946f cid:299 + +iyr:2014 +eyr:2028 byr:1922 pid:594856217 hgt:158cm +ecl:oth +hcl:#623a2f + +pid:215206381 byr:1928 +hgt:163cm +hcl:#b6652a ecl:oth iyr:2011 + +cid:145 iyr:2013 +ecl:#38a290 +eyr:2034 +hcl:#602927 hgt:186cm pid:517498756 +byr:1945 + +hcl:#5637d2 eyr:2030 byr:1955 +hgt:187cm +pid:862655087 iyr:2014 ecl:grn + +hcl:#7d3b0c hgt:176cm iyr:2019 +eyr:2029 byr:1980 ecl:hzl +cid:346 pid:703908707 + +hgt:185cm +iyr:2017 +cid:120 eyr:2020 hcl:#733820 ecl:blu pid:458522542 byr:1966 + +pid:#725759 +hcl:#602927 iyr:2013 byr:2003 eyr:2023 cid:100 diff --git a/day4/src/main.zig b/day4/src/main.zig new file mode 100644 index 0000000..d95a319 --- /dev/null +++ b/day4/src/main.zig @@ -0,0 +1,215 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var record_indexes = std.ArrayList(usize).init(gpa); + + var f = std.fs.File { .handle = try std.os.open("input", std.os.O_RDONLY, 0)}; + var reader = f.reader(); + + var records = std.ArrayList([]u8).init(gpa); + var record = std.ArrayList(u8).init(gpa); + var n_newlines : u32 = 0; + var just_had_newline = false; + const state = enum { + AddingData, + CheckingNewline, + RecordEnd, + }; + var current_state = state.AddingData; + while(true) { + var n = reader.readByte() catch |err| { + // Finalize record + try records.append(try gpa.dupe(u8, record.items[0..record.items.len])); + //std.log.debug("Found record: '{}'", .{record.items}); + record.deinit(); + record = std.ArrayList(u8).init(gpa); + std.mem.set(u8, record.items, 0); + break; + }; + if (n == '\n') { + if (current_state == state.CheckingNewline) { + current_state = state.RecordEnd; + // Finalize record + try records.append(try gpa.dupe(u8, record.items[0..record.items.len])); + //std.log.debug("Found record: '{}'", .{record.items}); + record.deinit(); + record = std.ArrayList(u8).init(gpa); + std.mem.set(u8, record.items, 0); + current_state = state.AddingData; + continue; + } + else { + current_state = state.CheckingNewline; + // whitespace can always be added + try record.append(' '); + continue; + } + } + else { + if (current_state == state.CheckingNewline) { + current_state = state.AddingData; + } + try record.append(n); + } + } + std.log.debug("Found {} records", .{records.items.len}); + //std.log.debug("{}", .{records.items[0]}); + //const fields = comptime std.meta.fieldNames(RequiredFields); + const fields = comptime std.meta.fields(RequiredFields); + const valid_passport = RequiredFields { + .byr = true, + .iyr = true, + .eyr = true, + .hgt = true, + .hcl = true, + .ecl = true, + .pid = true, + }; + var n_valid : u32 = 0; + for (records.items) | r, k | { + // Everything is separated by whitespace + var passport_info = RequiredFields{}; + var iter = std.mem.tokenize(r, " "); + //std.log.debug("{}", .{r}); + while (iter.next()) |aspect| { + inline for (fields) |field| { + if (std.mem.startsWith(u8, aspect, field.name)) { + @field(passport_info, field.name) = validate_field(field.name, aspect[4..]); + std.log.debug("Field {} with contents {} is {}", + .{field.name, aspect[4..], @field(passport_info, field.name)}); + } + } + } + if (std.meta.eql(passport_info, valid_passport)) { + std.log.debug("'{}' is valid", .{r}); + n_valid += 1; + } + else { + std.log.debug("'{}' is invalid", .{r}); + } + } + std.log.info("Valid passports: {}", .{n_valid}); +} + +pub fn validate_field(field: []const u8, data: []const u8) bool { + if (std.mem.eql(u8, field, "byr")) { + if (data.len != 4) { + return false; + } + var i = atoi(data); + //std.log.debug("byr {} --> {}", .{data, i}); + return (i >= 1920 and i <= 2002); + } + if (std.mem.eql(u8, field, "iyr")) { + if (data.len != 4) { + return false; + } + var i = atoi(data); + //std.log.debug("iyr {} --> {}", .{data, i}); + return (i >= 2010 and i <= 2020); + } + if (std.mem.eql(u8, field, "eyr")) { + if (data.len != 4) { + return false; + } + var i = atoi(data); + //std.log.debug("eyr {} --> {}", .{data, i}); + return (i >= 2020 and i <= 2030); + } + if (std.mem.eql(u8, field, "hgt")) { + var unit = data[data.len-2..]; + var i = atoi(data[0..data.len-2]); + //std.log.debug("hgt {} --- > {} '{}'", .{data, i, unit}); + if (std.mem.eql(u8, unit, "in")) { + return (i >= 59 and i <= 76); + } + else if (std.mem.eql(u8, unit, "cm")) { + return (i >= 150 and i <= 193); + } + else { + return false; + } + } + if (std.mem.eql(u8, field, "hcl")) { + if (data.len != 7) { + return false; + } + if (data[0] != '#') { + return false; + } + for (data[1..]) |d| { + // less than ascii 0 + if (d < 48) return false; + // greater than ascii f + if (d > 102) return false; + // after ascii 9 but before ascii a + if (d > 57 and d < 97) return false; + } + return true; + } + if (std.mem.eql(u8, field, "ecl")) { + if (data.len != 3) { + return false; + } + for (valid_eyecolours) | colour | { + if (std.mem.eql(u8, colour, data)) { + return true; + } + } + return false; + } + if (std.mem.eql(u8, field, "pid")) { + if (data.len != 9) { + return false; + } + for (data) |d| { + if (!std.ascii.isDigit(d)) { + return false; + } + } + return true; + } + if (std.mem.eql(u8, field, "cid")) { + return true; + } + std.log.debug("Uknown field {}", .{field}); + return false; +} + +const valid_eyecolours = [_][]const u8 { + "amb", + "blu", + "brn", + "gry", + "grn", + "hzl", + "oth", +}; + +fn atoi(a: []const u8) u32 { + var i : u32 = 0; + for(a) |v, k| { + if (! std.ascii.isDigit(v)) { + std.log.warn("Byte {x} is not a digit", .{v}); + continue; + } + // 48 is '0' in ascii + std.debug.assert(v >= 48 and v < 58); + i += @as(u32, (v - 48) * std.math.pow(u32, 10, @intCast(u32, a.len - k - 1))); + } + //std.log.debug("{x} --> {}", .{a, i}); + return i; +} +pub const RequiredFields = packed struct { + byr: bool = false, + iyr: bool = false, + eyr: bool = false, + hgt: bool = false, + hcl: bool = false, + ecl: bool = false, + pid: bool = false, +}; diff --git a/day5/build.zig b/day5/build.zig new file mode 100644 index 0000000..03f1f55 --- /dev/null +++ b/day5/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day5", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day5/input b/day5/input new file mode 100644 index 0000000..6887b63 --- /dev/null +++ b/day5/input @@ -0,0 +1,814 @@ +FBFBBBFRLL +BFFFBFFRRR +BBFBFFFLLR +FBFFFBFLRR +FBFFBFBLLR +BFBBFBBRLL +BFFFFFFRLR +FBBBBFFLLR +FFBBFFFLRL +FFBFBBFLLR +FBFFFBBRRR +FBFFBFBLRR +FBBFBFFRLR +FBBBFBFRLL +FFBFFBBRLR +FBFBBBFRRL +BFFBBBFRRR +FBFBBBBLLR +FFBFFBBLLL +BFFBFBBLLR +BFFBFBBRLR +BFFBBBBLLL +FBBBBFBLLR +FFBFBBBLRR +FFBFBBFLRR +FFFBFBBRRL +FFFFFBBRLL +BFFFBFFLRR +FFFBFBBRLR +FBFFBBFLLR +BFBFFBBRRR +FBBFBBFLRL +BFBBFBFRRR +BFFFBBBLRL +BBFFFBFLLR +BFFFFBFLRR +BFFBFFBLLL +FFBBFBFRRR +BFBFFFBLLL +FBFBFFFRRR +BFBFBBBLLL +BFFFBBFLLL +BFBFFFBLLR +BFFBBBFRRL +FFFBBFFLLR +BFFBBBFLRR +FBFFBBBRLR +FBBFBBFLRR +FBBFFBFRRR +FBBFBBBRRL +FFFBFFBRRL +FBFBFFBRLL +FBFFBBFRLL +BFBFBFFRLL +FBFBFFFRLR +BFBFFBBRRL +FFBBFFBRRR +BFFBFBBLRL +FFBFBFBLLL +BBFFFBFRLL +FBFBBBFRRR +BFFBBFFLRR +BFBBFFBLRL +BFFFFFBLLL +BBFFFFFRLR +FBBFFBFRLL +FFBFBFFRRR +BFBBBBFLRR +BFFBBFFRLL +BFBBFFBLLL +BFFFFFBRRR +FBBFFFBLRL +FFFBBBFRLR +FFBBBFBRRL +BFFFBBBRRL +FFBFBFBRRR +FBBBBBFRRR +BBFBFFFRLL +FBFFFBBLRR +FBFBFFBRRR +BFBFBFBRLR +FBBBFFFRRL +BFBFFFBRLL +FBBBFFBLLL +BFBFBFFRLR +BBFFBFBLRL +BBFFBFBRLR +BBFBFFFRRR +BFBBFFFRLL +BFFBBBBRRL +FFBFFBFRLL +FBBBFBBLRR +FBFFFFFRLR +FBFFFBFLLR +BBFFBFFRRR +BFBFBFBRLL +BFFBBBBLLR +FBBBFBFLLL +FFBBFBBRLR +FFFFBBFRRR +FFFBFFFRRL +FFFFBBBLLL +FBBBBFBLLL +BFBBFBFRLL +FFBFBFFRLR +FBFBBBFLLL +BFBBBFFLLL +BBFFBFFRLL +FBFFFFFLLR +FBBBBFBLRR +BFBFFFFRRR +BFFBBBBLRL +BFFBBFFLLL +FBFFBBFLRR +BBFFFFBLRR +FBBBBFFRLL +FBFBFFBRLR +FFFFBBFRLR +FBBFFBBLLR +BFFFBBFLRL +BFFFFFFLRR +BFBFBFBRRL +FFBBFBFLLR +BFBBFBFLLR +FFBBBFBLRR +BBFFBFBRRL +BFFBBBFLRL +BFFBFFFRRR +FFFFBBFLLL +BBFFFBBRLR +FFBBBBBRLR +FFBFBBBRLR +FFFFBFBLLR +FBBBBBBLLR +FBBBFFBLRL +BFFFFFFLLL +FBBFBBFLLL +BFBBBBBLRR +FBFBBFBLLL +FBFFFBBLLL +FBFFFBBRLR +FFFBBBFRRL +FBFFFFBLLL +BBFFFFFRLL +BFBFBBFLRL +FBBBFFFLLL +BFBBFBBRLR +FFBFBBFRLL +FFBFBFBLRL +BFFBBBBRRR +FFFFBBFLRL +BBFFFFBLLR +FFFBBBFLLR +FFFBFFFLLR +FFBBBFFLRL +FBFBBBFLRL +FBBFBBFLLR +FBFBBFFLLR +BBFFBBBRRL +FBFBBFBLRR +FBBBFFFLLR +FBFBFFFRLL +FFBBFFBLLL +FBBBFBFRRR +BFBFFFBRRR +FBBBFFFRRR +BBFFBBBLLL +BFFBFFBRLR +BFFFBFBLLR +FBBBBBFLRR +FBBFBBBLRL +FFFBFFFLRR +FFFFBBBRRR +BBFFFBFLRL +FBFBBFFRRL +BBFBFFFRLR +FBFBFBBRRL +FFBFFBFLRL +FBFFBFBRLR +BFBFFFFLRL +FBFFFBFRRR +FFFFBFBRRR +BBFFFFBRLR +FBBBFFBRRL +FBBFFBBRLR +FFBBFBFLRL +BFFFBBBLLR +BFFFFFFRLL +BFFBBBBLRR +BFBFBBBRRL +FBFBBBBLLL +BBFFFBBLRR +FFFFBBFLRR +FFBBFBBLRR +FFFBBBBLLL +FFBBBBFLLL +FBBFFFFLLR +FFBFBBBRLL +FFBBFBBRRR +BFBFBBBLLR +FBBBBBFLLL +FFBBFFBRLL +BFBFFBFRLR +FBBFBFBRRL +FFBBFFFLRR +BFBFBFFLRL +FBFFBFFRRR +BBFFBFFRLR +FFBBBBBRRL +FBBBFBBLLR +FFFBBBBLLR +FFBBFBBLLR +BBFBFFBLRL +BFFFFFBLLR +FFFBFFBRLL +FFFFBFBRLR +FFBFFBBRRR +FBBBBFFLRR +BFBFFFFRLR +FFBBFFBLRL +BFBBFBBLLR +BBFBFFFLRR +FBFFFBBLLR +BFFBBBFLLR +BFFBBFFLLR +BFBBBBFRLR +FBFFBBBLLR +FFBFFFFLLR +FBBBBFFRRL +FBFBBFBRRL +FFFFBFBLRR +BBFFFFBRRR +BFBBFBFRRL +BFFBBFFRLR +FBFBFBFLLR +BBFFBFFLRL +BBFFBBBLLR +BFBBBFBLLL +BFBBBBBLLR +FBBBFFBRLL +FBFFBFBRLL +BFBFFBFLLR +BFBFFFFLLL +FBFFFFFRLL +FFBBFFFLLR +FFFBFFFRRR +FBFFFBFRLR +FFFBFBBLLL +BBFFFBBLLL +FFFBBFBLRL +FBBBFBFRRL +FFFBBFBRLR +BFBBBFFLRR +FFBBBFFLRR +FFBFBBBLLR +FBBFBFBLLR +FFBFFBBRRL +FFFBFBFLRR +FBBFBFBRLL +BBFFBBFLRL +FBBFFBFRRL +BFBFBFFRRR +BFBBBFBRRR +BFFFFBFLLR +FBBFBFBRRR +BFFFFBBLLL +FFFBFFFRLR +FBBFBFBRLR +BFFFFBFRLL +FFBFBBFRRR +BBFFBFBRRR +FFBBBFFRLR +BFBFBFFRRL +BFFFBFBLRR +BFBBFBBRRR +FFBFFBFRLR +BFFFBFFRRL +BFBFBBBLRR +FFBBBBBRLL +BFBBFFBRLR +FBFFFFFLRL +FFBBBBBRRR +FFBFFFBLLL +FFBBBBBLLR +BBFFBFBRLL +BFBFBBBLRL +FBBFFFFLRR +BBFFBFBLLR +FFBBBFBLLR +BFBFFFBRLR +FBFBBBFLRR +FBFBBBBRLL +BFFFFBFLRL +BFFFBFBRLR +FBBFFFFLRL +FFFBBBBRLL +FFFBFFFRLL +FFFFBBBLRL +BFFFBFBRLL +FBFBBBBLRR +BFBBBFFLLR +FFFBFFBRLR +FBFFBFFLRR +FFFFBFFLLL +BFFBBBFLLL +BFFFBBBRLL +FBFFFFBLRL +BBFFBBFRLL +BFBBBFBLRL +FBBFFBBRLL +BFBBBBBLLL +BFBFBFBLRL +BFFBBFBLRL +BFFBFFBRRR +FFBBBBFLRR +FBBBBFBRRR +FBBBFBFLLR +FFBFBBFLLL +BBFFBBFLRR +FFFBBFFRLR +FBBBFFFRLL +FBBBBFFRRR +FFFBFBFLLL +BBFBFFFLLL +FBFFBFBRRR +BFFFBFFLRL +FFBBBFBLLL +FBBBBFBRLR +BFBFFBFLLL +BFBFBBFLLL +FBFBFFBLLL +FBBBBFFRLR +FBFFBFFRLR +BFBFBBFLRR +FBFBBBBLRL +FFFFBBFRLL +FFBFBBBRRR +BFFBBFFRRL +BBFFBBFRLR +FBBFFBFLLR +FBFFBFFLLL +BBFFFBFRRL +FBFFFFBRLL +FBFBFBFRRL +FFBFFFBLLR +BFBFFBBLLL +BFBFBFFLRR +FBFFBFFRLL +BFFBFBFLLR +FBFBFFBLRL +FFBFBFFRRL +FBFBBBBRLR +FFFFBBBRLL +BFBBFBFLLL +FBFFFFFLLL +FFBBFBFLRR +FFBFBFBRRL +FBFFBFBRRL +FBFBFBFRLR +FFFBBBFLRL +BFBBBBBRLR +BBFFBBFLLL +FBBFBBBLRR +FFBBBFBRLL +FBFFBBFRRR +FFFFBFFLRL +FFBFBBFRLR +FBBFBFFLRR +FFBBFBFLLL +FFBFBBBLLL +BFFFBBBLLL +BFFBBBBRLR +BFBBFBBLLL +FFBBBFBLRL +BFFBBFFRRR +FFFBBFBRLL +BFBFBFFLLL +BFFBBBFRLR +BFBFFBBLRR +FBBFFFBRRR +FBBFFFFRRR +BFBFBFBLLR +BBFFBBFRRL +FFFFBBBRRL +FFFBFBFLRL +BFFFBFFLLR +FFBBFFFRRL +FFFBFBBRRR +BFFFFBBRRL +BFBBFFFLRR +BFBFFFFRLL +FFFFBBBRLR +FFFBBFBLLR +FBFBFBFRLL +BFBBFBFLRL +BFBBBBBRRR +FBFFFFBRRL +BFBFFFBLRL +FBFBBBFRLR +BFBFFBFLRR +FFBFBFFLRR +FFFBBBFRRR +FFBBFFBRLR +FFBFFFFLRR +FBBBFFFLRL +BFBBFFBLLR +BFFBFBBLRR +FBBFBFBLRL +BFFFBFBLLL +FFFBBFFLRR +FBFFFFFRRR +BFBFFBFLRL +FFBFFFBRRR +FBFBFBBLLR +FFFFBBBLLR +BFBFFFFRRL +FFBBFFFRRR +FBBBFBFLRL +BFBBBFFRLL +BFBFFBBLRL +BBFFFFFLLR +FFBBBFFLLL +FFBFFFBRLL +FFBBFFBLLR +BBFFBFFLLL +FBFBBFBRRR +FBBBBBFLLR +FFBFFFFLRL +FBBBBFFLLL +BFFBFBFRRR +FBFFFFFLRR +FFFFBBFLLR +FFFBFBFRRL +FBFBFBFLRR +FBFBBFFRLR +BFFFBBFRLR +FFBFFBBLRR +FFBBFFBRRL +BFBFFBFRRL +FFFBFFBLRR +BFBBFFFRRR +BFFBFBFLRL +FFBFBBFRRL +BFFFBFFLLL +FBFFBFBLLL +BFBBFFFLLR +BFFFFBBLRR +FFFBFFFLLL +BBFFBBBRLL +BFFBFBFLRR +FBBFBFFRLL +BFFBBBBRLL +BFBFBBFLLR +FBBBBBBRLR +BFBBBBFRRR +FFBFFBFLLL +BFFFFFBRRL +BFFFBFFRLL +BFFFBFBLRL +FFBBBBFRLR +FBBBFFFLRR +BFFBFBBRRL +BBFFFFFRRR +FBBBFBBLLL +FFBFFFBLRR +FFBBFBBRLL +FBFBBFFLLL +BFFFBFFRLR +BFBBBBBLRL +FFFBFFBRRR +FFFBBFFLRL +FBFBFBBRLL +FFFBFBBRLL +FFBFBFBRLL +FBFFFBFRLL +BFFBFBFRRL +FBBFFFBRLR +BFBBBFFRRR +FBBBBBFLRL +FFFFFBBRRL +FBFFBBFLLL +BFBBFBBLRL +BFFBBFBLLL +FFBFBFFLLL +FFFBBBFLLL +BFFBFBFLLL +FBFFFFBRLR +FBFBBFBLRL +BBFFFBFRLR +FFFBBFBLRR +BFFBFFBRLL +BFFBBFBRLL +FBBFFFFRLR +FBBFFFBLLL +FFBFFFFRRL +FFFFBFFLLR +FFFBBFFRLL +BFBBBFBRLR +BFBFFFBLRR +BFFFBBFLRR +BFBFFBFRLL +BFBBFFBRRL +FFFFBBBLRR +FBFFFBBLRL +FFBBBFFRLL +FBBBFBBRLR +FFBFFBFRRR +FBFBFFFRRL +BFBBBFFRLR +FFFBBBFLRR +FFFFBBFRRL +FFBFBFBLRR +FFFBFFBLLL +FBFFFBBRRL +FFFFBFFRLR +FFBBBBBLRR +FFFFBFFRLL +FBFFBBBRRL +BFFFFBBLRL +FBFFBBBRLL +BBFFFFFLRL +FBFBBFFLRR +FBBBBFBRLL +BFFBFFFLLL +FBBBFFFRLR +BFBBFFBLRR +FFBBFBBLLL +FBBFFBBRRL +BFBFBFBLRR +FFFBBFBRRL +BBFFFBFLRR +FBBBBBBLLL +BFFFBFBRRR +FBFBFFFLLL +FFBBBBBLLL +BFBFBFFLLR +FBBFFBBLLL +FBBBBBBLRL +BBFFBBBRLR +FBFFFBBRLL +BFBFBBBRLL +BBFBFFBLLR +FFFBBFFRRR +FBFBFBBRRR +FBBFBFFRRR +BFBBBFBRLL +FBFBFFBLLR +BBFFBFBLLL +BFFFBBFRLL +FBFBFFFLLR +FBFFFFBRRR +FFBFBBFLRL +BBFFFBFLLL +FBBFBBBLLL +FBBBFBBRRL +FBFBFBFLLL +FFFFBFBLRL +FFFFFBBRRR +FFBFFBBLLR +BBFFFFFRRL +FBFBBBFLLR +BFBBBFFRRL +FBFBBFBRLR +BFBBBFBLRR +FFBFBFFLLR +FBFBFFBRRL +FFBFBFBRLR +BFBFFBBRLL +FFBFFFFRRR +BFFBBFBRRR +FFBBBBFRRL +FFFBBBBLRL +FFBBBFFRRL +BFBBBBFRLL +BFBFBFBLLL +BFBBFFFRRL +BFFBFFBLLR +FFBBBFBRLR +FFBBFBFRRL +FBFFBBBLRR +FBBFBBBLLR +BFBFFBBLLR +BFFFFBFLLL +FFFBFBFLLR +FBFFFFBLRR +FBBFBFBLLL +BFFFFBFRLR +FBBBFBFRLR +FFBBFBFRLR +BFFFFFFLLR +BFFFFBFRRL +BBFFBBFRRR +FBFFBFFLRL +FBBBBBFRLR +FBBBBFBLRL +BFFFBBBRRR +FFFFBFFRRL +FFBFFFFLLL +FFFBFBFRLL +FFBFFBFLRR +FBBFFBFLRL +FBBFFBBLRR +FFBFFBFRRL +BFFFFFFRRR +BFBFBBBRLR +BFFBFBBRLL +BBFFBFFRRL +FBBFBBFRLL +BFFFFFBRLR +BFBBBBFLLL +BFBBFFBRRR +FFFFBFBLLL +FFBBFFFRLR +BFBBBFBRRL +BFFFBBFRRR +FBFFFFFRRL +BFFBFFFRLL +BFFFFBBRLR +FFBBFFBLRR +BBFFBBBLRR +FBBFFFFRRL +BFFFFBBRLL +BFFFFFBRLL +BFBFFFFLLR +FBBBBBFRRL +FBFBBBBRRR +FBBFBBFRRL +FBBBFBBRLL +FBFFBFFLLR +FFBFFFFRLR +BFFFFFFRRL +BFBBFFFRLR +FFBBBBFLRL +FFBFFBBRLL +FFBBFBBLRL +FBFBFFBLRR +BFFBFBFRLR +FBFFBBBRRR +FBBBBFFLRL +FBBFBFFRRL +FFBFBFFLRL +BFFBBFBRLR +BBFFFFFLRR +FBBFFFBRLL +BFFFBFBRRL +FFBFBFFRLL +BBFFBBBRRR +BBFFFFBLRL +BBFFFBBRRR +BBFFFFBRLL +FBBFFBFLLL +BFFFBBBLRR +FFBFFBFLLR +FBBFBFFLLR +FBFBBFFLRL +FBBBBFBRRL +BFBBFBFLRR +BBFFBFBLRR +FFFBBBBLRR +FBBBFFBRLR +FBFBFBBLRR +FBBBFBBRRR +BFBBFFFLLL +BFFFFBBLLR +FBBBBBBRLL +FBBBFBBLRL +FBBBBBBRRR +FFFBBBFRLL +BBFFFFFLLL +FBBFFBFRLR +BFBBBBFLRL +BFFFFBFRRR +FBFFBBBLRL +BFBBFBBRRL +FBFFBFBLRL +FFFBBFBRRR +BFBFBBBRRR +BFBBFFFLRL +BBFFFBBRRL +FFFBBBBRRL +FBBBFFBLLR +FBFBFFFLRR +FBFBFBBRLR +BFFFBBFRRL +FBFBFBFRRR +FBBFFFFLLL +FBBFFBBLRL +FBBBFBFLRR +FFFBBFFLLL +BFFBFFBRRL +BFFFFBBRRR +FFFFFBBRLR +BBFFBBBLRL +FBBFBBFRRR +BFBBFBBLRR +FFBFFFFRLL +BFBFFFBRRL +FBBFBBBRLL +FBFBBFBRLL +FBFFFBFRRL +BFFBFFBLRR +FBBFBFBLRR +BFBBBBFLLR +BFBBBFBLLR +FFFFBFBRRL +FFFBBBBRLR +FFBFFFBRLR +BFFBFFBLRL +FBBFBFFLLL +BFFBFBBLLL +FBFBBFBLLR +FBBFFBFLRR +FFBBBBFLLR +FBBFBFFLRL +FFFBFBBLRL +FBBFFFFRLL +BFBFBBFRRR +FBFFBBBLLL +FFBFBBBLRL +BBFFBBFLLR +FBFFFBFLLL +BFBFBFBRRR +BFBBBBBRRL +BBFBFFBLLL +BFFFFFFLRL +FBBFFFBRRL +FFBBFBFRLL +BBFFBFFLLR +BBFBFFFRRL +FFFBBFBLLL +BFFBFFFRRL +BFBBBBBRLL +FFFBFBFRLR +FBFFBBFRRL +BFFBFFFLLR +FFBBFFFLLL +BFFBBBFRLL +FFBBBBFRLL +FFFFBFFLRR +FFBBBBBLRL +FBBBBBBLRR +FBBFFFBLLR +BBFFFBBRLL +BFFBBFFLRL +FFFBFBFRRR +FBFBFBBLLL +FBBBBBFRLL +FBBBBBBRRL +FBFBBBBRRL +FBFFBFFRRL +BFFFBBFLLR +BFFBFFFLRR +BFFBBFBLRR +FFFFBFBRLL +BFFBFFFLRL +FFBFFFBLRL +FBBFFFBLRR +BFBBBFFLRL +FBFFBBFLRL +BFFFBBBRLR +BFFBFBBRRR +BFFFFFBLRL +BBFBFFFLRL +BFBFBBFRRL +BBFFBFFLRR +FBFBFBBLRL +BFBFBBFRLR +FFFBBBBRRR +FBFFFFBLLR +FBFBBFFRLL +BFBFFBFRRR +FFFBFFBLLR +FBFBFBFLRL +FBBFBBBRLR +FFFBFBBLLR +FFBBFFFRLL +BFBFFBBRLR +BBFFFFBLLL +FFBBBFFRRR +BFFBFFFRLR +FFBFFBBLRL +FBBBFFBRRR +BFBFBBFRLL +BFBBBBFRRL +BFBBFFBRLL +BBFFFBBLRL +FFBBBBFRRR +BBFFFBFRRR +BFBFFFFLRR +FFFBFBBLRR +BFFBBFBRRL +FBBFBBBRRR +FBFBFFFLRL +BFBBFBFRLR +FFFBFFFLRL +FFBBBFBRRR +FBBFFBBRRR +BBFFFBBLLR +FFFBFFBLRL +FFBFBBBRRL +FFBBBFFLLR +FBFFBBFRLR +FBFFFBFLRL +FFBBFBBRRL +FFFBBFFRRL +FBBFBBFRLR +FBFBBFFRRR +FFFFBFFRRR +BFFFFFBLRR +BBFFFFBRRL +FBBBFFBLRR +BFFBFBFRLL +FFBFFFBRRL +FFBFBFBLLR \ No newline at end of file diff --git a/day5/src/main.zig b/day5/src/main.zig new file mode 100644 index 0000000..990a96c --- /dev/null +++ b/day5/src/main.zig @@ -0,0 +1,99 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + var gpa = &arena.allocator; + defer arena.deinit(); + + // Read entire file + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + + var highest_id : u32 = 0; + var seat_ids : [814]u32 = undefined; + var it = std.mem.tokenize(contents, "\n"); + var i : u32 = 0; + while (it.next()) |n| { + var s = decode_seat_id(n); + var id = s.get_id(); + highest_id = std.math.max(highest_id, id); + seat_ids[i] = id; + i += 1; + } + std.log.info("Highest seat id: {}", .{highest_id}); + + // Part2: This works because the IDs are otherwise contiguous + std.sort.insertionSort(u32, seat_ids[0..], {}, asc_u32); + // Search for a gap of 3, we're the middle of the gap + var prev : u32 = 0; + for (seat_ids) |id| { + //std.log.debug("{} [prev: {} // delta {}]", .{id, prev, id - prev}); + if (prev == 0) { + prev = id; + continue; + } + if ((id - prev) != 1) { + std.log.info("Gap of {} found between {} and {}", .{id - prev, prev, id}); + std.log.info("Seat ID: {}", .{id - 1}); + } + prev = id; + } +} + +const asc_u32 = std.sort.asc(u32); +const Seat = struct { + row : u32 = 0, + col : u32 = 0, + + pub fn get_id(self: *Seat) u32 { + return (self.row*8) + self.col; + } +}; + +fn decode_seat_id(code: []const u8) Seat { + //std.log.debug("{}", .{code}); + return Seat { + .row = _bsp(code[0..7], 127), + .col = _bsp(code[7..], 7), + }; +} + +fn _bsp(code: []const u8, max_val: u32) u32 { + var min : u32 = 0; + var max : u32 = max_val; + for (code) |c| { + var half_range = (max-min)/2; + if (c == 'F' or c == 'L') { + // Low half + max = min + half_range; + } + else if (c == 'B' or c == 'R') { + min = max - half_range; + } + } + //std.log.debug("{} --> {}, {}", .{code, min, max}); + std.debug.assert(max == min); + return max; +} + +test "bsp" { + var s0 = decode_seat_id("FBFBBFFRLR"); + std.testing.expectEqual(s0.row, 44); + std.testing.expectEqual(s0.col, 5); + std.testing.expectEqual(s0.get_id(), 357); + + var s1 = decode_seat_id("BFFFBBFRRR"); + std.testing.expectEqual(s1.row, 70); + std.testing.expectEqual(s1.col, 7); + std.testing.expectEqual(s1.get_id(), 567); + + var s2 = decode_seat_id("FFFBBBFRRR"); + std.testing.expectEqual(s2.row, 14); + std.testing.expectEqual(s2.col, 7); + std.testing.expectEqual(s2.get_id(), 119); + + var s3 = decode_seat_id("BBFFBBFRLL"); + std.testing.expectEqual(s3.row, 102); + std.testing.expectEqual(s3.col, 4); + std.testing.expectEqual(s3.get_id(), 820); +} diff --git a/day6/build.zig b/day6/build.zig new file mode 100644 index 0000000..be1b13a --- /dev/null +++ b/day6/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day6", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day6/input b/day6/input new file mode 100644 index 0000000..67f02f8 --- /dev/null +++ b/day6/input @@ -0,0 +1,2079 @@ +x +x + +ygzdvpxjk +bzdgq +aulrhfwi + +tpasjur +jrutopas +rtjpaus +sraetpju +tpajsru + +vus +uvs +vwups + +r +r +r +d +j + +qohtkgcpl +yukohqglp +dobtpghlkq +hglqpaosrnk + +zathopqrnf +tfphoznqra +ornthfpqza + +xymf +yfm +yaeflpmc +mxfy + +xhjnyblvetrzcsdfgioqw +nyvjcwruaitzkbsfelxhqmo +vqlebsnycaijwxhftzor + +pvnbhgqxokzfls +ktfiphrwzyu + +snadfrzvj +huravjsfnz +wrfajsvznx + +gzqpt +htzqp +pltxqz + +dwf +fwvd +fwjxzd + +wvkaetlonsmzyxp +flamyzwpnexosvk +ylsoxwnmkpegvazf +xnozlvwayepksmj + +hegoanjwcuqr +unjghwraoecqm + +vrmuincbeax +mrxcevanu +cmanxeuqvr +xmcrunveqa +rvxcunmea + +edz +zgesn +ozqjtrewa +zdefv +czdenf + +imnklhe +flsnkj +nkljfv + +dtkhezmqarglsyujifncbpx +smyaqrdnjzutcpfkbxghl +nzupmhqkjfblrdasxgcty +ltbdpxsmhzkyjargfcunq + +khbnlsgcwdepajfqry +fcglrsedyjkbnwpahz +rngyalswjpecfktbhd +eajkdwshrclpfgnby +eqvgcfpyxdjirlwhkabsn + +nsxzlycfmhtkpr +wmxstkfoyrhlzp + +jqxfycbl +fjztavkuxeh +mxdfipon +eyrvxswhgfa + +yqutg +qytgu +ytugq +tlgquy +uqytg + +lsnvemdftqgzk +ethkglvsqdf +edxfsltqgvk +zflnhgtsvkqde + +zxqiowjp +ojziqxwp +pxwjizoq + +jxfsvcu +scqufxjv + +nmkbsdpth +ekqzlgwuyrcapt + +bvxfjegzyawqtdpkrihonl +kgdxaywnmbthueqpfjvilo + +wukhzt +ztqhipkexwo +zhkwltfu + +dosntymrebgxip +vbakzmsqnxehtyg +besntwxymgju +pbsgyntoemx + +ke +ke +ek + +gkqrxeyhmpwoavszftnid +qablonwmkpridxgcztsehy + +ejnuvyrgwkfphld +vyejdomzqcrtwuigs + +sxjnructhkifz +umktfhirxnec +iunkcfhryxt +hftciukrnx +kuctixrfhn + +m +c + +ktwhurxsgza +huntakrzxg + +bfiecpvksjzgxmtrhwndy +yewjdrpcfvmxub + +kxv +bvkx + +mpkdrilqnvgjszxhbceat +qplbdncjxgzvsimakehrt +abwpdvkcmjihleqsrxztgn +ejkotbiyranhvzpgmdsqlcx + +upykgj +lkqbapvf +wpzmkr +upkngjw + +henpvx +uhnepi +vhpn +unph +gacnoptsyh + +va +v +v +v + +mfgsejknphquwvtzic +nyfhzpkxqtmlwivsgec + +l +l +lr + +vneibmqwsuropl +qulpwvhbmirne +priwulqenbmv +uwbznlqrmpviea +nmvqulerpdbiw + +zrcedpsjlgavqhkfwyxinobmut +wvzastimlhdyeobxckurfgpnjq + +c +w +c +c + +eavhgx +axvegh +xghvae +eagvhx +xaehvg + +qhvryckj +cyqhvkj +vhyjmzcgqk + +inyetbqzdcu +cezuhin +ejaurictfnym +hrngcezuia +xkliecvuwsn + +qowvezrdukfbn +zewvyunqoambdr +zngwprusefvdbkqo +euwdbvqnzfro +xrqovndztwueb + +klpubivcyfoemgdqzasn +stujebgynqmlxvak +nvmqsubergklwyh + +pbsjdzutfgwmxieqcraklhv +bjcexgqskpvolmadnzryftwu +mvxrzwtqaujgpcebdklsf + +balwcovj +jwobvalc +bwjaolvc +lbaojcvw +cvbwlajo + +onvtx +xotnv + +y +ydg +y +fy + +ndluot +huotfw +gouqtl + +usvy +qf + +h +c +c + +vjyolxpgqfk +qbugnhjvpx +xtzaprdcvjqigm + +idryqgoevjwhpal +jwrledyhvgpaoqi +olgejvpdaqwiyrh +ajehiwrlodvypgq +oylrhqwajevgpid + +x +x +p +r + +rnqocxehf +yrjmlgdavuwihox +xrqpnkoht + +yvackuxdrbespfoz +oyxcabeuszrfvpkd +utxobrfckapdvzsey +eoxsdayfpkucvbzr + +jortnzkcqb +bznrjycktqo +zjqnkrtcob +qojktrnbcz +qktojzrncb + +uokgp +krui + +iqbhupfzg +fqklopwh +qstfhnp +nqykmsphf + +jnzpybrvctmgx +pzjbyxmgkcvn +cvxjzgpnbmy +gvynmcxzbpj + +zihyt +zihty +zhtyi +ohytiz +tyizh + +hrtmfqdnbsjceuxgiakol +lxprsezfuyw + +bnpesm +fqhcya +kdoy + +hsfj +qecixr +dyzpo + +nsviyq +isyqnv +cvqdsfnjyi +qvniys +qvysni + +olsytfpiqbcgruavnmkdj +wobyanuximplfgtrc + +fakvjrdemphinxzboygcq +rpxbevcfsodljzqmaigkh + +osh +hoprni +efzcdv +jxih +p + +qhamel +slehaz +mealyh +hela +belahtkn + +ertwyfubagxcilm +gfytuxwmrbialec +cmxybwaptedlrufig +uciewrabfxymltg +geurytlicmbawxf + +pqosuijf +qfsjiup +ifsrpujq + +iv +vi +iv +gvi +vi + +gcpsri +tsmvokr +usqagr + +svtwqplur +thzwuporavyl +ltupsqrwv +utvwlsprq + +apeidznxcr +imgtbyekslu +hseitolv + +tfhpmels +haspqmfel +kplfrjymxeh +pthlvmqef +cehdmtfpsl + +dj +caj +d +vohrlqx + +kuzcdayghrqbtpe +kcpxwmaeruqzhvb + +riwuxjg +puwhxdj +blknsvt + +jtvyr +tjrvy +vjyrt +vytjr +jvrty + +qngcme +qenc +knecpq + +psetjy +xvikrzflgdm +yco +wconu +bucqa + +kdnt +udnz +dnagt +xdkn + +jsikbcef +ksefbi +yeikfbs +snevfqxiakb + +wqtgfxruzyd +jrkfxwtzqdub + +kemcnsaxjfiubg +mankwgqsuxibcj +sbgkvujnmcxai +fgyixmnkdacbujs + +dmrkoujzbvtwsqyx +fqibxwkhmzcertd + +jbw +wryg +w +w + +y +g + +bcfztdseowilyqapun +wpmsdbozlqvciku +xqsbloudprihcwz + +intvfbkagzs +krweqxlajmtyu + +r +p +zjcogl +pv + +fljxyzkgt +ktzlcsigxyf +xygltfzki +lgyxtbkfzj +klmtrzdfegqxhny + +ejfndtrmwlyzxqavhcbspoikg +ajnlbfrcswgmdkthpxiqvz + +ysikgwrpx +rdmkqgsw +wgrchksjf +wykdasgr + +emaizfwdc +adcwsozetmf + +m +r +z + +knvpqjbasl +jqnsvklbpa +dvksqnbljpa +pawskblnqjv +blakpsqjnfv + +phioqsu +gunio +uoi + +wlqhkndiuoxtgesrmpfv +wvgsmtolekfhaxnpqui + +slu +uisal + +fsepbqldiztcwanjohruky +lsbtpoenyvuazqghijfrkcwd +kqzrdphyoacenswumblxtij + +zfbadvte +zteda +otazie +eturlyah + +gt +tgd +gvta +tg + +rjck +ymcv +lctoweb +cmqh +mruchy + +iztpec +ipeztc +zceipt +icpzet +ecptzhi + +mjubdrwxaitnvcekgslhqpz +ldhvzxbrqjtcmpuiasewk + +dkjlrwqbpa +jqlzerbpa + +svupyxrbk +grtnawqcybmdhfiz + +qzjmpxinvwked +bxfuzhany +snxotzlgc + +cfvejdxqrzlhobi +vrojlcdmzebuq + +idrjshpbqtevogmy +ysdvpeuqlmhgbioj +pgwybvmosdjiehu +pvdhcseguyomjbi +kixjgompdbnvfhzseya + +jgl +gjlez +glj +jgl + +zrbxvcuwjidklfmnqotg +lmurpfvqzoxjgwbckndti +umlqjgbxdkrivcntwzfo +wsedxcrblhmotqjkavzfuing +tnqdxjmcrofvbzkyguwil + +dmxcntqwauokif +tqmufiwnhk +inzeftquwmvpbjs +iwgfymqrutdn + +ejsfxcgdtkhoqu +kfhitexsugdj + +tnypmbxl +rxmbnltpy +xnbylmtp + +c +ksc +thcpjf +gmucyaxdz +ck + +xqizlfeksrjh +wgetzlkx + +khnawcubgpx +knctwgupa +kpwngcau +apzwqckgnu +npkawcgu + +itlec +lhectib +lctesi + +mhanjrlytudgzovf +nzjgdapevrh +inhdrjeazgv +gznhdiajrv +jazvhdrng + +itgemupjxbhvs +epsjthguxvimz +jmhxspugetvi +pjhiseuvtgmx + +beln +le +xle +elhazjy +ecl + +ev +v + +ryzfswe +sylrkzc + +vezqnasodyjxlfkgiup +vlkyixzeqdbajfruongp + +td +tkqpl +tde + +lcdkt +tcnkd +okciajvuxdqt + +usoyw +owuys +ouswy +swyou +wsyou + +xmfovdhgnlcja +qfympwaotzvchrlu + +gcx +c +c + +cxpanqwbzjeiruogsh +npqobaijrgwsecuh +vjfbmsagotwpyhckeriqu +biosrpqwgljexauch + +kriedwmbz +ykhebdsjtz + +inblqrgm +rqbimln +nbrqlim + +wdlmasxozvngrkuy +zguaymvdolnkwsxr +gvxadrlowkmzunsy + +frpv +vprasf +irapxf +unmfpe + +icgmloskedvrhfq +xzitwrbjpny + +qbvwlyext +qtblesvw +etlwbqv +tebvlw +hpbevwtl + +bmnpvz +nbvmoz +nwczgybvlkd +abvztn +bnzve + +b +c +b + +tchlzb +gz + +ndr +rdn +dnr + +sctrbhpnmzev +qedsncvaruymg +dncrsemkvaox +yarlncvdwxsem + +sfhunci +nsuhifc +siuhcfn +icufhns + +gnheqlb +ukpd + +lixtrswd +wntldgisx +spclikxftdhwzuejabo +stywildxv +stmlxdiwq + +ehsqnvgzw +neszvwgqh +qwzhsevgn + +etgcydsljko +xoyiqbumwanhr + +hvbqfdkyzupwnctr +jnchwzpsobtkfeqruy + +gvzipoldfjx +zodxivgpl +noibqzgxvldp +doqplvgzxi +olxpvdzig + +sqri +qirs + +nzhagdpqyrtuclsxojbfev +uqznepyjgfoavrthslbcdx +uxztlrfhgevopdbsancqjy +uqrtexnlzvjahcgbdpsfyo +jdhgotuxqvpzsrcfnaylbe + +anytx +mgldfs +vn +jpxn +yujnw + +zdgnamji +pmjnzgdwbcoi +jynmiguzd +jgrumdntiz +mganjdsiz + +jikqaxmebd +uolhrpecyxvda +dafxhtrse + +lbjmzepw +barycf +suxb +xuqb + +xjkpdbsycqzfml +pszjxdkycmfq +hyqzxfpjctwkdsmn +fqsdkuyxcpjmez + +tmxoylwjzas +gqbwlujd +pldwnjibrqe + +oxtwegdyarcmufj +dcfuwrgxmytejo +mwutxyorcdgfej +dctrumjwxegyfo +twpyflemcjgourxzdk + +ji +ij + +hbjzg +czbtgj +bgjz +zjbg + +hziwf +jqhgmlybvf + +sgukx +jxqts + +rbekhvqmjw +wjkmvbrghqye +qowekvthnjrb +jevhqkwbr +wreyhjvqkb + +f +f +lfi + +b +r +b +nim + +ds +dms +nsd + +reydi +clbyfjoqg +pzny +wekuiy +yhi + +ujqkgvwhybdaxfoz +joaxzvkgbufqhw + +zcyhdxriqtolasnwpmfvukg +tpolkuqmhzcyisvndargxfw +umphysgavwqixcdfrlkotzn +wgpruaotvcklnfidmxzyqhs + +ubwgxvmkjz +gzkbmuxwvj +jyuxgbkvmwz +xvjkubzmgw + +cjbalye +naero +aspe +ache + +usfcwigx +wcistfguxz +ishfguxcw + +vowtyizedpxjkuhgln +rtacogzuipjydhxlnew +gjmzenuwstlpxqbhyodfi + +humbgtvizaqnrekx +urixmqaghktbnezv +geabrihuzvtqnsxdmk + +oqdctfig +itmfgcqoyk +ijuoaqxcfthg + +slbj +bslj +lbjs +jslb + +dyhijmulgn +gcxrkbt +cogkr + +l +hl +le +el +l + +rd +dr +dr + +sx +kzfyajw +cuplmx + +yos +ys +jqyta + +b +b +b + +hwotauyxk +koufjyh +ouhyk +hklouy + +sm +s +csig +sgi +esxy + +rgukjdhytpmoewicz +dzgwtkejyacros + +dwpuknfajbeztsvlcir +nbeilkzmyqswjfdapuvgt +zbvuifewstkadpnjl + +lctyng +yncldht + +hdusmgynzxba +auzvjdmhxybgns +hbumansdxogzyek + +lnshkwetqz +enxhqolgkds + +hxczvrwn +xzrwvnfoh +khrwsbeytzil + +qr +o +o +hey + +krtpbuzgy +buztrpkgy +tupybkrgzq +pyubztkogr + +f +fx +m +x + +uvbf +awy + +odwf +fdwo +wodf +odwf + +atnskdpybvlowehzmx +aopknhzybdwtsumlvx +lsbqxonmwgthdaykvzp + +zcvgrlkiwdnjxuyeabftosqp +ijhuaexordwgtlqbpsynkcz + +rb +b +e +e +p + +rgfljswuqmnxdyzve +sdurkno +budprnsac +anruids + +s +q +q + +xq +x + +mkcounerqzvywhb +rhmuwbylqcxzedovn +wcyrzehguqknbvmol +uiosmjcwyfqzvhptrben + +cbafotnhw +ztbwievgscufo +kmrqfbwtcoy +ftwcosb + +pqbdg +lvyknqjdt +okcdy +durhfwzamsi +edkt + +rteknjgdziaxuvqpwms +euqatrgskzjdxpiwmnv +odpxerktavzujqiwsngm +xpajvmrwugsqzdyhitkne +zjpmskatnegrquxwifvd + +ucp +puc + +sbhrmvgkxlwcuizf +irughftcbsxvkzm + +jgufnkhxcrwsqyav +rhjndfxayuqgsvc + +wh +hw +hw +wh +hw + +oskmgp +pskmorb + +zbjxfa +afzujx + +lrucpk +bosmyzdf + +jxtmurs +kmou +uybvqmc + +c +cha +h +t + +yj +yj + +ubhwxkosgq +giqwkhtuesbox + +pwqjdvbzir +ijrzqdub +sjanrzbiq +jizqbry + +m +m +um +m +m + +hmgxpcyfzenjlavbrtd +yvtxmarbphjoefzgnl + +dsmcohpqxzytbefwun +vkglfzxscniymhqurpdtbeoa + +b +e +q + +dr +rd +dr +dr + +peqvdfnayt +qpjcsu + +lfq +lqf +lfq +flq +qlf + +thnkmpcl +fkiavtnux +tqpkn + +zuxche +zcxuhr +xcznhua +xhuzcd +pxuhnczs + +vdtesl +ktlmxsf + +ekrfgonxblyuqwcmithazvdjp +awlpvtybicnhqdxeofzgjkmru +zdyfgtaoilqwuhkpbexcjvrnm + +zutmxljqsbwevaog +jnouplrwkzq + +bvkwprm +xiz +i +gdc +if + +krm +rm +rmush +opjrnmeb +rmuki + +iw +ysw +kl +gtjb +hrndzmf + +z +sjcdb +d +cqs +hlot + +ehs +yabvz +hjsgx + +fgexm +xtjfe +ebfjxh +zsvfopulwnixc + +kmqupeigvojczwbadlx +gxmawjupbvkedqlzco +exlzudcqbmvawjgokp +lgkconmhwxyvqtzuedbpaj +guofmwqdjxvezlapcbk + +yzvldxhqpcregionbwmast +oxbnyzpseagchiqrtwvmld +ivmargzsdlcwhoxynpqbet +dfeczlatxrgybwpnmvisohq + +sbdtompfakqzuw +odwukmshptfizq +pquszdktmifwno + +uhgxdiptswayqref +waqdrxpltvufsciyge + +lxkvhzeruigsboft +hobvxrieltumgyzfs +bovtrghfxeiulsz + +mkxhjuygbvcno +ygoqnubvj +pyzdubtlnsjgvo +bnguvojy + +pmuxezk +odpiyevns + +iergxuojpqwskbdnyt +dtebiujnospkwyragq +roqbendjksgiwupty +nbhftycoqleusjdwpvgkri +qryzgjekwpubidtosn + +hkosdxcnztelmp +ltxcshpodmkenz +aeokdzmhlxnctps +tcohzelnsxdpmk +rlmxzsdchoipenkt + +klodupfxjg +dxouflgj +zjfugadelox + +qe +eq +qey +nkemqr + +kpyahrdgnv +vkrnygdpah +nygrkhdvpa +hngyqkrdcvpa +nhygkpravd + +pojt +tjp +tpij +tpj +ptjx + +ptudvwcsnbzlkmh +pnvuklmedhwcstzb +stpkbndzwcxulmhv +lshkvqbtnmauwpdzc +lvbkdstmhczunpw + +cjki +i +dh +nayubo +zte + +lrsyuzkehwmdi +uilhsekdmwr +ehlmdkiuwsr +mlwuiskedhr +remuhcdikwls + +nevqwlas +tafkhjrndcsgm +aizsxn +anqlswvy + +tdfxwikmqcygoja +pbmnevlsoxkiudhyctqf + +uncjptla +snpj + +mqnwhueayizvl +zwqlijnymve +pkloymxntbigqwzerdf +nvqyeilmzw +icjmlezwqyn + +echgfxinmd +ftcmixeghn +xbikghlcpfnwem +jxcfgedimnh +jehnsmgxcdif + +qorpli +ipohrq +pqirko +prioq + +vcptybfelzaihduknmwgs +hsugpzyftmeiklbawnvcd +caukmbihneywsdvfztplg +tcziphfsbdkmavwulnyge +kcmfhlgbnaztdsyuvrpwei + +yvzouqjilkgm +mgkpqyzotublsevi +iazkvluoygmq + +wphvnftyxedckbzq +dbzhwqxnpvfyce +sqebwpydfvncxhz + +jdtehlm +rz +rv + +bw +wb +bw +btw +bw + +esviqco +uceqvxj +qcvywrat + +y +qf +y + +wdopylavgxi +uomhenqjzbrcf + +gyowtsk +hplycvznxtqw + +xhlomdpznrcavebti +barocdnhpmgtlk +phrtmbdnacol +rgdomapnhbltc + +sdqiauyzgvj +uvayizq +iqyuavz +qauzyvi + +uvrs +usv +svu +suv +vsu + +zg +mge +y +vcf + +gunfyiqemws +esywnimfugq +mfwysnquieg + +ag +gab +pga +agd +ga + +npgitkbz +vxhzakcj + +rkdst +onhzibjuyg + +bha +la + +iepquktyaxmfhnlobcrwjvds +kmfpuchdwbaxqviojynrstel +jwotpldbxqnkrichseyuvmfa + +agunzk +izug + +lawqrc +fdo +dp + +ptmfuje +umfqjbedtlz +rmwxfjute +utsjmfer + +fymhpzavr +lehormypnfwx +hpljurctygmf +upylfqtrdijhbm + +ugscvjxfkh +sihzmngcjdv + +pbwjhdvlntmxuykzcqf +nmisaefgqhcoz + +orcfsxm +xcmfrs +syrxfcm +srfmxc + +yjodxnav + +smvkfxt +sutnflvk + +rgb +b +b + +uahjwtqbeklgfzixpocrvmn +kbjlqzxwuratocmfpinhegv +qrijtvkzbsclmefahpwugonx + +cnvxwskaithmrpdjzegoufly +yojesiunmzclkvghxwtrdapf +fcazyohpuliwmgdnvsjterxk +padmkvwzgyxtjcselruhofni +thjrfauldyvpcisxngokmewz + +jtr +tr +tr +rlt + +o +fx +o +o + +jviduxrqhpzykm +jrlhykixbv +hkyjilrvx +yhxivkrjl +xryhbkijv + +jx +i +rekgmt + +hdigybslxfozca +sbypgfvxzihcmlau +caliwbxzfgehy + +xwbdprtsoqzuny +smkhxcjfaived + +j +j +j + +nvwbegrypaofxq +ofvqxeyrgp + +klw +lkw +kwl + +zyrfuqhnagk +ghfzeswqkc +ekqzohgf + +rgumpkoehtndcb +gcdfkipuvbojlmn + +uqlivpmac +vplcqimua +upmalcvqi +mcuvlpqai + +woi +wio + +zycvodbiatfr +boycztjaidfrv + +kyimbvawqx +mvwkyjcqaiptr +vhiykmaqw +kqmvxyiwa +vakmqwiy + +mb +axhbf +ldpczbr +vhfbym + +zvibckofgyjqtw +fmqzswhpeklyjtbvuoi +fjixaznqkywtbvco + +vxcnagsqdmhuotwe +envfkxdroqawcgsmty +aspitmqnxwedvcbl + +tqsizydbaw +ohejgpk + +xvrzbcpogdyfuhwknmiesqa +oigwafzqnmshkevcuxbypdrl +grhcbdxyuewisvazfqpkomn +mnyvbxcsaeoufpwrqzkdhgi +dxzyrsogubncfqtmvepihwka + +n +n +n +n +n + +bmpkgzfojxelrwtc +qairymcnsuxlokj + +dewfscvkqbtzpx +cdpuewltsbzormq +wvtdngphbkeszcqj + +disryhxvpbulzw +hbzlwdirsvpyxu +irzldphyubxswv +wihdrypxvuszlb + +fxtqpck +xqkptcf + +factlhdbwurgvxiekpszqjo +gjhxkdfpsltcvoibruqewaz +tcpfirvxkjwolzasbeguqhd +vjrfpclktdeshquigxbowza + +pqabsimryhtd +uvlconjzxgwke + +pmyjflwzckdvnergq +zjprwygclekfmqvdn +wykjldrvfqecngmzp +vjfmcynwegzprdklhq +cfqnmrldegyzpwkvj + +xh +h +eh +nh +hldjq + +kapbqmo +fbakptzq +okpcqbat +xjopbqka +ubpdqrkhga + +wyaudlen +eawulynd +wueadlny +uaelndwy +aluewndy + +byzxchgujesn +ygzxanucbejh + +ehftw +lmvfa +hfsg + +wvmfzghpsy +hfm +dhgmjzux +reablkontchmq + +gzwqlcx +bgzlctwn +uzcwdpgaxlv + +nukwtrszf +rfndkzcsomwu +rusfnwzk +ufzwlrnsk + +bv +ai +b +v +v + +uxcdomyb +qrwgzvfnai +lhntkrpjsegf + +fqxugyni +ifynw +ayigfkn +qynafsgi +yfqcni + +yecqrtdzbnhp +hcrzqodnv +qhnrzdcf + +p +v + +afoxchynvipsel +nsxlcohfpeiyav +sxalyfhpwvoneci +xislpcoyefvnha + +najlhzu +zjyclua +tslumedaiq + +k +k +k +k +k + +odetwpfglrcjqmuihx +dyrqkfweansjvmhglzpu + +igskahu +esihkglu +giushk +guhxkis +suknighx + +oxemfvj +xomzsqv +mlnxvo + +tlwfvk +tlvw +ztvlxcr +vwltf +vwlt + +uwmpzlhenva +otzqhxmngylkup +whnufmlzpev +lfupmhnz +vmluszhpn + +nqsireakdvpbtfcwgxy +bkqygapisnxfwrtecvodj +enbvtdisqwaxfpgrcyk +xvdbrwgimatefqcyspkn + +ajumckognwqs +mcwbsjqtkgfdziro + +acpzwt +zlcyaet + +gvu +vg +gv + +qgcjztkuo +ojbwtrxaq + +tecrwjigkqpbnufmldavxh +fxvhgjetlrwdpziukbnc +xkvlhwrtbfydigpsocnje + +kqyn +uw + +caixsqhpgwvmo +uhxomepiqc + +naud +numdat +vuzaednw +nagtdxu +guxdna + +xdmkliqsw +kwlqxamti +vdqpmwlxik + +mixyslpha +ayihosplx +xytbdakhiplrswz +povsiyhflxa + +ynli +boyins +yin +iny + +fgjmlirc +rjfilcgm + +mohvfnrgzjkuc +ujroykmzfwa + +xljiqtkpe +glymhtqpak +etpsklnq +dtpqkl + +cefwpgnbamdzj +zyjeaxwumpdcfnbr + +vxdhgi +hgdixv +dnxrhqvgim +ixvdghb +pgxihdv + +ytbgfrm +mgoty +qjltepmgsy +tfymg + +xlgpjbkwqeavsu +exjaugptqlsbkwv +jegvpwluibkaqysx +qwbexsvfprjulz + +ugnwqbiyp +gnbqyipu +bygiqnpu +gybnpuqi + +tmldrwhgivbnq +wtgdqhvrljb + +cvlt +peoxb + +rblnmixegdwafuoyq +qgoylwxbarumifedn +arfquebxydimnvclowg + +fywzsnhitdcae +tadizcyfsnewh +sawtdziyfngpchx + +vnuhpkriz +lrupivknj +hunripvk +vdkuqsrifnp + +axdzckpvimueqjtgy +ctpymavjkxzreuqli +pedavgzqxthkcmjuiwy + +kxperoiadjgsnfbm +jpikdgrexanmbfos +jrcedfukonpbgixsma + +ugo +guos +guo + +bmhnfupxotj +bjhftongxyupmz +uxbnmjocpfht + +gdx +gk +gc + +fvwc +wkqzcfvh +wcfv +vwecf +cvywf + +w +w +w +c + +eosuimrzpqvyk +kzmicpqvexours +ivrmseztophqkug +kipmquyorvezs + +fpmkrd +tzupnklqxfa +ypfgek +jrfcpkbd +ofkgp + +qrwoydm +bgtlcxpsh + +gawqbjoyrcvizhpmsel +aveozrfgjpismdbcyhwl +rchmbojzqiweplygvsa +zbvclsxrmitehywjoapg +yjhimlberdvscgzpaowu + +qawpmhydzn +rfbyw +wgokjfy + +pnhbd +qfug +fdep +imowsvtxlzkry +ajg + +nquegztm +srnj + +wit +tusiv +qmcoftrljdyk +t + +hxbsozmwegqjkicufl +likdywshmvxuzcfqb + +vtaqrdcfoybz +cfozirq +frkqocz +qfhrzoc + +t +t + +xjqbomigwrfckhsynva +mqoniwygafbkcrsjvxh +aicnmeoqgvwjyfurxhztsbk +wfrmbcaivnskyhjxqgo + +vzad +dvaqz +udazj + +dqsvrj +jkcq +ezuqxjm +qdtavj +jtsq + +qgawvsxo +cpmaxziubdewlfnt +rjsxaw +hkwxya + +lmbopvufrxnw +mvdnioxjpaqeyfrlsgh +nzmtklorpxvf + +eqiwxhrvudokt +xumrqhvnswiaky +vupkbiqrmwxnh +hixwqvzgck + +ziedvfb +fvbezid +bidzefv +bfezvid +edizbfv + +eglq +lgeq +qlge + +pabzfmvsxdqoykhurtjl +zyleahvmbocxpkrtfs + +g +g +g +gv + +mgwxotefbiqjudn +uoniqfdtgxwbjeml + +ryzmxkwosabecqvtj +bftceznowiyskpqvjxdm +ecmxqktvoswbzjy +czjhkyvsmwoetbaqx +zqrwuyesmvbcoktjx + +ytanuz +byanf +jpoglevikmyhc +wsqdyx + +uzwbmdsgafvyk +noqlhcjwx +qxrtpowh + +vlsgakpqfjemz +kgvqauiesdjlfnz +fcegqzsjkvla +kglzqajpseyvf + +hztmnjip +cfptrw + +kaeubgqoxsfiyjtwmhcvzrnl +ikmhteubjczxyvoqsfln +vnxsukmbecqljfidozyth +ushnpjevlkbocxfmiqtyz + +mye +ezmy +mye +meysnt +yme + +xtvlmhrbdypeaf +bvxftlaephdmyr +dhuxmtryeplfvab +vxrmaybhplfdet +vxrfeyhplbdmta + +pek +pe + +dpo +gpdfjsaho +hnpo +dpamoy +wvueozqxp + +wjdqzpftmhk +vmtod +tbdmg +rytuvcdbm +rtboyemdca + +dxmsyfacqoigtuvjnwph +upojvbynselfdzhkwqrt + +d +dmo + +cymqgxwurzhdbteok +acydrugmobzlxek +xmugryzcobked +cmbyokexuldgzr + +uebznq +ubqzen +qunbez +zuqebn +buzeqn + +uewpvklzhoqifcsb +rlvdyhnkjptiwxgab + +xgdazmoqwislvb +qxodszwlvbgai +azsdiwlgqoxvb +ldzvgwoqsxiba + +ozbnvjquac +pgntbvw + +aexsklbwjydt +akjbwedsxylt +keaxswdbtjyl +leykdbstjwxqam +xewlkdytasbj + +ahzvbeqsctofui +ueabotfhvdzcsrqi +obzhuvteqapscfi +ovhbpuqcslzfieta +vbfhtqszaociue + +ugilv +ivlgm +vxigrl +gvli + +qjni +qongz +nyqj +sfdqwlvcxn + +bcgdtuaxmlkrevof +ftorcabmwueykglxd +tahfxumdobrclzikneg +xakfmdtgocruleb + +ihrobnmcpqtgwk +hwkrgmpoctuqni +nwiphcogrkqtm +whrqpktngmycboi +vjiwsothqgnkdrzecmp + +fmvhjo +fomhvjq + +pkvcijtamu +xijwkrbmluneta + +evjomncktgpu +gumxn +mnuyqgfai +luqxgmwn + +vgxsetchwpajodzmu +tubxpkqheniygjodwm + +zugtaqdsofhpe +tuqpdhgar +ugnoadthq +yvkugjhdaxbcmqt +gthudaq + +dzfmjsgaqubntpkvleo +zuwgvfbkarlyxpdihnme + +z +z +zp +zb +z + +khdj +dhj +hdkjrgz +eofuhjdta + +gauozreitvy +oeidrzyv + +zlvxcidkob +obdckzlvix +olckbzdxiv +lkxcboidvz + +rpslxjnfh +bhvuytmosdzaqwgk + +rbjloemzv +zlbeormj +rlmbjezo + +djbyqfcoknxsmtzghrp +hksxmbyzgfnpdjqocr +cjodkxfrpgnmbqhyzs + +ko +rok +kwo +kgio + +ypocjw +hyw +pwy +iyfw +yqwgjv + +hyto +hqtko + +gw +g +ag +gj + +sckdazw +fazodyc + +wofxjgyqurha +fhxjboaerg +ztsgrohfjcal +hjgxarfou +rvqyegxakhbfoj + +coat +coa +oca +coat +oack + +tzcdyrhfuxisvlgm +txuplzrcsjhmyavi + +ahcxfelbv +haxlbfevc + +owfizxugtsemclrypjvahqdnb +ugncvldopbwqjzmxhirfaet +oupwmqnzilhdtcbavrkxejfg + +fjyagkzt +gfyktjza +kayfgzqtj + +iutxmzd +dmtuzix +tzmxidu + +cndejklaphsquowi +pjocdlehukqai +hixujeqlrktapdco + +xcapfuiljwgqsevot +tlfdxuwkjpnqvsmoeg + +madurwbn +anwdbqmru +rdwubanm + +gl +lanp +wlkijdruy +zlg +hlx + +d +da +da +dmwp + +e +ey +e + +mcxndruabhvp +pnqudhcymb + +qxldtifpvshowjbkemza +hvziwsglkjepobfmqaxd +hzxeslvdomagbrwkjifpq +hbxdsfkizqvljwopae +zucafhbkvelxoqipdsnjyw + +hoeqg +fqghrt +gqh + +v +r +r + +iovxlnqsz +iosnqfxzl +ozxinsql + +pqsvfxihdmzkrnacobetjluwy +wytcbhvxsrndpafleuiqozjkm + +ngi +ogi +ticfga + +qg +drl + +mzbfwevsodakx +gdwvskin +vdskwli + +jienvauxkgfdqh +qdhxjktavizcpnuef +fkbqueiladvjnxh +ukfwjndxhaieqv + +gdlrowxahs +lusdcwhyg +dwalghs +hzdgitqeflws +dgkhlws + +pmjkz +kzpmvj +pzkjmh + +dshpxl +vbtmniafszewdkxup +opsqdxyj + +etki +eikt +tiek +iket +ktei + +yvfta +atypkqfv diff --git a/day6/src/main.zig b/day6/src/main.zig new file mode 100644 index 0000000..55b0dab --- /dev/null +++ b/day6/src/main.zig @@ -0,0 +1,118 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var records = try read_records("input", gpa); + + // part 1 + var yes_per_group = std.ArrayList(u32).init(gpa); + var yeses : u32 = 0; + for (records.items) |r| { + var map = std.hash_map.AutoHashMap(u8, bool).init(gpa); + defer map.deinit(); + try map.ensureCapacity(26); + + for (r) |c| { + if (std.ascii.isAlpha(c)) { + map.putAssumeCapacity(c, true); + } + } + var count = map.count(); + std.log.debug("{} yeses in group '{}'", .{count, r}); + try yes_per_group.append(count); + yeses += count; + } + std.log.info("{} yeses across {} groups", .{yeses, yes_per_group.items.len}); + + // part 2 + const one :u26 = comptime 1; + var and_yeses : u32 = 0; + for (records.items) |r| { + var it = std.mem.tokenize(r, " "); + var state : u26 = std.math.maxInt(u26); + while (it.next()) |answer| { + var person_yeses : u26 = 0; + for (answer) |c| { + if (std.ascii.isAlpha(c)) { + person_yeses |= (one << @intCast(u5, (c-97))); + } + } + //std.log.debug("{x} <-- {}", .{person_yeses, answer}); + state &= person_yeses; + } + //std.log.debug("{x}", .{state}); + var count = count_one_bits(state); + //std.log.debug("{} and-yeses in group '{}'", .{count, r}); + and_yeses += count; + } + std.log.info("{} and-yeses across {} groups", .{and_yeses, yes_per_group.items.len}); +} + +fn count_one_bits(a: u26) u32 { + var i : u5 = 0; + var one : u26 = 1; + var count : u32 = 0; + while (i < 26) : (i += 1) { + var b : u26 = one << i; + if ((a & b) == b) { + count +=1; + } + } + return count; +} +fn read_records(filename: []const u8, allocator: *std.mem.Allocator) !std.ArrayList([]u8) { + var file = try std.fs.cwd().openFile(filename, .{}); + var reader = file.reader(); + + var records = std.ArrayList([]u8).init(allocator); + var record = std.ArrayList(u8).init(allocator); + var n_newlines : u32 = 0; + var just_had_newline = false; + const state = enum { + AddingData, + CheckingNewline, + RecordEnd, + }; + var current_state = state.AddingData; + while(true) { + var n = reader.readByte() catch |err| { + // Finalize record + try records.append(try allocator.dupe(u8, record.items[0..record.items.len])); + //std.log.debug("Found record: '{}'", .{record.items}); + record.deinit(); + record = std.ArrayList(u8).init(allocator); + std.mem.set(u8, record.items, 0); + break; + }; + if (n == '\n') { + if (current_state == state.CheckingNewline) { + current_state = state.RecordEnd; + // Finalize record + try records.append(try allocator.dupe(u8, record.items[0..record.items.len])); + //std.log.debug("Found record: '{}'", .{record.items}); + record.deinit(); + record = std.ArrayList(u8).init(allocator); + std.mem.set(u8, record.items, 0); + current_state = state.AddingData; + continue; + } + else { + current_state = state.CheckingNewline; + // whitespace can always be added + try record.append(' '); + continue; + } + } + else { + if (current_state == state.CheckingNewline) { + current_state = state.AddingData; + } + try record.append(n); + } + } + std.log.debug("Found {} records", .{records.items.len}); + return records; +} diff --git a/day7/build.zig b/day7/build.zig new file mode 100644 index 0000000..b3ce472 --- /dev/null +++ b/day7/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day7", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day7/input b/day7/input new file mode 100644 index 0000000..8954672 --- /dev/null +++ b/day7/input @@ -0,0 +1,594 @@ +vibrant aqua bags contain 1 shiny magenta bag, 2 muted teal bags, 1 dim magenta bag, 1 muted chartreuse bag. +vibrant violet bags contain 4 pale maroon bags. +dark indigo bags contain 1 light maroon bag, 3 pale red bags, 1 drab brown bag, 4 dim magenta bags. +dark coral bags contain 5 dull aqua bags, 5 plaid green bags, 2 posh bronze bags. +dim lavender bags contain 2 muted violet bags, 5 wavy gold bags, 3 vibrant plum bags, 5 bright teal bags. +mirrored turquoise bags contain 5 muted olive bags, 5 bright gold bags, 2 vibrant violet bags. +faded brown bags contain 5 faded tomato bags. +muted orange bags contain 5 dull aqua bags, 2 light salmon bags, 1 striped black bag, 1 pale gray bag. +posh black bags contain 4 faded silver bags. +muted coral bags contain 3 mirrored turquoise bags. +clear silver bags contain 5 dark cyan bags. +clear crimson bags contain 2 dim blue bags, 4 bright indigo bags. +clear salmon bags contain 4 striped cyan bags, 1 muted maroon bag, 1 light bronze bag, 1 vibrant tan bag. +light olive bags contain 1 faded white bag, 2 dull chartreuse bags, 5 faded gray bags. +muted maroon bags contain 5 dark fuchsia bags, 5 drab violet bags. +posh plum bags contain 2 striped gray bags, 5 dim violet bags. +light orange bags contain 1 light purple bag. +drab white bags contain 4 plaid lime bags, 1 drab gold bag. +plaid indigo bags contain 5 clear lime bags, 1 dark fuchsia bag. +muted red bags contain 1 dull bronze bag. +mirrored magenta bags contain 5 plaid white bags, 1 faded plum bag, 5 wavy purple bags. +dotted lavender bags contain 5 shiny olive bags, 3 plaid blue bags, 1 shiny gold bag. +drab bronze bags contain 3 wavy silver bags, 4 light turquoise bags, 1 vibrant lavender bag, 5 light magenta bags. +plaid maroon bags contain 2 dim salmon bags, 5 muted violet bags. +dull salmon bags contain 5 striped beige bags, 2 muted plum bags, 1 posh teal bag. +dotted turquoise bags contain 5 striped orange bags. +bright yellow bags contain 2 shiny olive bags, 3 wavy teal bags, 1 pale plum bag, 3 mirrored coral bags. +dark black bags contain 5 pale gray bags. +shiny yellow bags contain 4 dark aqua bags, 2 drab lime bags, 2 bright gold bags, 4 dark cyan bags. +shiny red bags contain 2 posh blue bags. +posh olive bags contain 3 dim aqua bags. +muted chartreuse bags contain 4 posh brown bags, 5 shiny magenta bags. +mirrored orange bags contain 5 dotted salmon bags, 1 posh green bag. +muted plum bags contain 1 dull red bag, 4 posh green bags. +light green bags contain 2 wavy plum bags. +light cyan bags contain 2 dotted crimson bags, 4 faded salmon bags, 3 muted coral bags, 3 plaid blue bags. +dull lavender bags contain 3 drab gold bags, 5 plaid crimson bags. +posh red bags contain 3 dotted salmon bags, 2 pale beige bags, 2 mirrored coral bags, 5 muted teal bags. +vibrant beige bags contain 2 faded lime bags. +plaid blue bags contain 5 dull red bags, 3 light maroon bags, 4 muted gold bags, 2 drab orange bags. +dotted white bags contain 3 muted white bags. +drab fuchsia bags contain 2 shiny fuchsia bags. +drab crimson bags contain 1 posh beige bag, 4 drab violet bags. +drab beige bags contain 3 mirrored orange bags, 1 wavy silver bag, 2 pale magenta bags, 1 drab lime bag. +posh teal bags contain 2 clear brown bags. +mirrored brown bags contain 2 faded tan bags. +clear coral bags contain 1 muted chartreuse bag, 2 muted violet bags, 2 faded purple bags. +pale lime bags contain 5 vibrant aqua bags, 3 wavy purple bags, 1 drab violet bag. +vibrant red bags contain 5 shiny gold bags. +shiny fuchsia bags contain 1 dark salmon bag, 1 posh white bag. +bright gray bags contain 2 dim red bags. +drab lavender bags contain 2 clear tomato bags, 1 faded red bag, 1 pale chartreuse bag. +clear red bags contain 3 light salmon bags, 1 bright red bag, 5 dark indigo bags. +bright aqua bags contain 3 faded brown bags, 1 shiny yellow bag. +faded red bags contain 3 posh turquoise bags, 5 dark fuchsia bags. +faded turquoise bags contain 3 drab fuchsia bags. +dim aqua bags contain 1 faded white bag, 5 faded violet bags. +muted white bags contain 5 pale red bags, 4 dull red bags, 3 dotted maroon bags. +dull gold bags contain 3 posh green bags, 2 mirrored yellow bags, 2 dull olive bags, 2 bright purple bags. +faded blue bags contain 3 wavy crimson bags, 1 plaid beige bag, 3 dotted orange bags, 1 vibrant purple bag. +faded gray bags contain 1 bright gold bag. +dim bronze bags contain 2 bright gold bags, 4 light brown bags, 5 muted chartreuse bags. +light teal bags contain 5 striped tomato bags, 5 drab teal bags, 5 shiny lavender bags. +striped white bags contain 1 plaid silver bag, 2 wavy plum bags, 3 dull maroon bags, 2 muted green bags. +vibrant salmon bags contain 2 shiny violet bags, 4 light salmon bags. +dim plum bags contain 1 dull blue bag, 5 vibrant bronze bags. +dotted fuchsia bags contain 4 plaid green bags. +plaid crimson bags contain 3 clear teal bags, 5 dark gray bags, 2 mirrored tan bags, 5 shiny fuchsia bags. +pale white bags contain 2 muted silver bags, 1 muted lime bag. +bright violet bags contain 2 clear chartreuse bags, 2 dull gray bags, 2 muted cyan bags. +drab red bags contain 1 dotted white bag, 1 light plum bag, 5 muted indigo bags, 1 dull lime bag. +muted indigo bags contain 3 mirrored blue bags, 5 light fuchsia bags. +vibrant cyan bags contain 2 pale blue bags, 3 mirrored chartreuse bags. +mirrored gray bags contain 1 shiny red bag, 2 pale blue bags, 4 dotted lime bags, 1 faded violet bag. +posh lavender bags contain 3 vibrant aqua bags, 5 mirrored chartreuse bags. +dotted silver bags contain 3 dark beige bags, 5 dotted teal bags, 3 mirrored indigo bags, 2 dim yellow bags. +wavy magenta bags contain 4 wavy beige bags. +faded tomato bags contain 3 plaid black bags, 5 bright orange bags, 2 vibrant blue bags. +mirrored maroon bags contain 3 plaid gray bags. +pale bronze bags contain 4 vibrant violet bags, 2 muted white bags. +plaid turquoise bags contain 2 dotted lime bags, 3 striped beige bags, 1 pale crimson bag, 2 pale purple bags. +posh turquoise bags contain 5 clear yellow bags, 1 dotted turquoise bag, 3 dim cyan bags, 5 pale maroon bags. +wavy white bags contain 2 mirrored gray bags, 3 pale yellow bags. +vibrant tan bags contain 1 wavy lavender bag. +pale turquoise bags contain 2 dark gray bags, 4 faded green bags, 1 light maroon bag, 5 posh white bags. +faded beige bags contain 1 striped brown bag, 1 dull gray bag, 5 mirrored blue bags. +bright maroon bags contain 1 light blue bag, 5 dim bronze bags, 4 dotted beige bags. +shiny lavender bags contain 3 dim gray bags, 4 pale gray bags. +dull beige bags contain 3 dark crimson bags. +striped coral bags contain 3 dark lavender bags, 2 mirrored turquoise bags, 5 posh maroon bags, 1 striped yellow bag. +shiny magenta bags contain 1 plaid black bag. +muted magenta bags contain 2 plaid beige bags. +light salmon bags contain 5 striped black bags, 1 pale lavender bag. +shiny white bags contain 2 bright gold bags, 3 mirrored olive bags. +dark tomato bags contain 2 dark gold bags, 2 clear teal bags, 5 dull fuchsia bags, 4 dotted gold bags. +dotted violet bags contain 3 plaid teal bags, 5 mirrored aqua bags. +plaid purple bags contain 4 mirrored olive bags. +drab lime bags contain 5 bright beige bags, 4 mirrored tan bags, 5 striped black bags, 4 faded green bags. +dull blue bags contain 4 light red bags, 2 pale turquoise bags, 1 posh maroon bag. +muted tan bags contain 1 pale magenta bag, 3 mirrored turquoise bags, 3 shiny blue bags, 4 dotted salmon bags. +dim teal bags contain 1 posh turquoise bag, 3 dull red bags. +muted fuchsia bags contain 4 pale salmon bags, 1 pale silver bag, 3 pale maroon bags, 2 bright purple bags. +bright gold bags contain 2 shiny magenta bags, 4 pale red bags, 4 posh brown bags. +faded lime bags contain 5 vibrant bronze bags, 2 pale violet bags, 2 plaid coral bags. +posh tan bags contain 3 bright lavender bags, 2 striped blue bags, 5 shiny gold bags. +posh bronze bags contain 3 plaid olive bags, 3 dotted salmon bags. +shiny lime bags contain 1 bright salmon bag, 3 faded green bags, 2 wavy aqua bags. +faded lavender bags contain 2 bright silver bags. +muted black bags contain 5 mirrored coral bags. +plaid chartreuse bags contain 3 dull coral bags, 2 light tomato bags. +mirrored aqua bags contain 2 dark cyan bags, 2 dark indigo bags. +dark yellow bags contain 5 dotted lime bags, 1 dim cyan bag. +bright plum bags contain 5 dim salmon bags. +striped gray bags contain 3 plaid black bags, 1 wavy crimson bag, 5 bright orange bags. +faded salmon bags contain 3 clear lime bags, 4 drab purple bags. +pale olive bags contain 2 light magenta bags, 4 dim salmon bags, 5 light olive bags, 2 pale salmon bags. +faded crimson bags contain 2 wavy beige bags, 4 dim aqua bags, 5 light lavender bags. +posh chartreuse bags contain 5 pale lavender bags, 5 mirrored turquoise bags, 2 dark maroon bags. +posh aqua bags contain 5 faded crimson bags, 2 mirrored tan bags. +faded coral bags contain 2 dotted lime bags, 2 faded white bags. +striped bronze bags contain 4 plaid blue bags, 1 plaid coral bag. +wavy orange bags contain 5 pale tomato bags. +dim crimson bags contain 4 posh tan bags, 1 muted gold bag. +clear gray bags contain 3 striped lime bags, 4 vibrant fuchsia bags. +light gold bags contain 4 bright tan bags, 5 faded lime bags, 4 faded plum bags, 5 clear brown bags. +wavy red bags contain 4 pale red bags, 4 dotted maroon bags, 4 mirrored violet bags. +dull silver bags contain 1 striped turquoise bag, 2 striped orange bags, 1 dotted plum bag, 3 muted coral bags. +striped magenta bags contain 1 mirrored tan bag. +plaid plum bags contain 4 wavy tan bags, 5 wavy brown bags, 5 shiny olive bags, 5 clear yellow bags. +faded chartreuse bags contain 1 shiny teal bag. +clear chartreuse bags contain 2 drab tan bags, 3 plaid maroon bags, 2 drab orange bags, 2 plaid salmon bags. +wavy olive bags contain 5 dark lavender bags. +dull orange bags contain 1 dull gray bag, 2 light magenta bags. +wavy gold bags contain 5 vibrant yellow bags, 4 pale black bags, 2 light olive bags. +muted salmon bags contain 5 dotted turquoise bags, 5 dotted violet bags. +wavy tan bags contain 2 plaid green bags. +dotted cyan bags contain 4 drab gold bags, 1 dark crimson bag, 3 pale lavender bags. +wavy coral bags contain 3 mirrored blue bags, 5 wavy white bags, 1 striped indigo bag. +clear olive bags contain 4 wavy silver bags, 2 pale orange bags, 2 bright tan bags. +light indigo bags contain 1 pale purple bag, 4 clear teal bags, 1 plaid indigo bag, 4 dim blue bags. +dotted tomato bags contain 4 dim cyan bags. +pale indigo bags contain 2 muted chartreuse bags, 4 faded salmon bags, 3 dull brown bags. +bright magenta bags contain 1 vibrant salmon bag, 1 pale teal bag, 4 faded orange bags. +faded gold bags contain 4 striped cyan bags. +shiny orange bags contain 5 vibrant turquoise bags, 3 pale purple bags. +posh salmon bags contain 1 dotted crimson bag, 3 dark maroon bags. +dull violet bags contain 2 clear indigo bags. +posh gray bags contain 1 shiny fuchsia bag, 1 faded plum bag, 5 pale turquoise bags. +dull chartreuse bags contain 4 dull red bags, 1 striped black bag, 3 dark tan bags, 3 muted maroon bags. +dotted chartreuse bags contain 5 striped aqua bags. +dim magenta bags contain no other bags. +light lime bags contain 2 shiny magenta bags, 3 striped black bags. +drab maroon bags contain 2 vibrant bronze bags, 1 clear white bag, 2 dim gray bags. +drab salmon bags contain 2 wavy crimson bags, 3 dim gold bags, 5 drab chartreuse bags. +dotted crimson bags contain 4 pale purple bags, 3 plaid coral bags. +dull red bags contain 3 dark indigo bags, 2 posh white bags, 4 light maroon bags. +drab turquoise bags contain 2 striped tomato bags, 1 bright gold bag, 5 mirrored tan bags, 1 drab chartreuse bag. +shiny teal bags contain 4 bright lime bags, 2 pale red bags. +dark purple bags contain 5 mirrored beige bags, 1 posh purple bag, 5 dotted beige bags. +drab aqua bags contain 4 plaid blue bags, 3 dark salmon bags, 4 striped lime bags, 4 striped blue bags. +dull magenta bags contain 2 clear white bags, 5 muted bronze bags. +pale tan bags contain 1 pale lime bag. +dark fuchsia bags contain 3 dim coral bags, 1 muted white bag, 2 plaid blue bags. +mirrored beige bags contain 5 dotted magenta bags, 1 wavy olive bag, 1 dark tan bag. +drab tomato bags contain 4 dim cyan bags. +shiny tomato bags contain 2 shiny maroon bags, 2 dark lavender bags, 1 posh red bag, 3 vibrant green bags. +dim turquoise bags contain 4 muted salmon bags, 2 bright purple bags, 4 plaid maroon bags, 3 bright beige bags. +mirrored salmon bags contain 2 drab violet bags, 3 faded red bags. +pale crimson bags contain 3 bright white bags, 5 plaid beige bags. +shiny cyan bags contain 4 light blue bags. +clear lavender bags contain 5 bright turquoise bags. +vibrant purple bags contain 5 pale turquoise bags, 2 posh orange bags. +striped purple bags contain 5 muted orange bags, 5 dark aqua bags. +pale gray bags contain 5 dark indigo bags, 1 vibrant violet bag, 3 pale maroon bags, 4 bright gold bags. +posh brown bags contain 3 drab brown bags, 4 pale red bags, 2 posh white bags, 4 muted gold bags. +muted bronze bags contain 2 clear magenta bags, 5 shiny green bags, 2 mirrored tan bags, 4 posh gray bags. +pale brown bags contain 5 muted white bags, 3 plaid beige bags, 3 wavy lavender bags, 3 clear indigo bags. +dull yellow bags contain 5 clear lime bags, 4 plaid blue bags, 4 dotted lime bags. +light tan bags contain 5 dull blue bags, 2 drab yellow bags, 5 mirrored red bags. +posh gold bags contain 4 dull chartreuse bags, 2 dim magenta bags. +pale silver bags contain 4 dull aqua bags, 4 bright gold bags. +light beige bags contain 3 posh orange bags, 3 mirrored gray bags, 2 bright red bags. +striped turquoise bags contain 2 posh blue bags, 1 striped orange bag, 2 shiny tan bags, 5 vibrant aqua bags. +vibrant plum bags contain 4 pale gray bags. +dotted teal bags contain 2 dim magenta bags. +dull purple bags contain 5 drab brown bags, 4 dotted maroon bags, 1 muted white bag. +mirrored fuchsia bags contain 2 dark tomato bags, 4 faded tan bags, 2 faded white bags, 4 dotted orange bags. +dotted plum bags contain 2 dull aqua bags, 4 faded green bags. +bright fuchsia bags contain 2 wavy blue bags, 5 clear brown bags. +dim beige bags contain 2 pale orange bags. +dotted orange bags contain 2 faded brown bags, 1 clear tomato bag, 1 clear indigo bag. +plaid gold bags contain 1 striped turquoise bag, 3 vibrant magenta bags, 5 shiny gray bags, 5 shiny red bags. +clear plum bags contain 3 dim turquoise bags, 3 faded magenta bags, 2 dull coral bags. +muted green bags contain 3 dim crimson bags. +bright black bags contain 3 pale purple bags, 3 plaid white bags, 1 clear teal bag, 3 pale magenta bags. +dim gray bags contain 3 dull coral bags, 1 pale turquoise bag, 5 wavy cyan bags, 5 striped lime bags. +dotted beige bags contain 5 dull aqua bags, 3 dark fuchsia bags, 1 pale violet bag, 4 dim gold bags. +mirrored lime bags contain 4 plaid tomato bags, 1 pale lavender bag, 5 shiny blue bags, 1 light gray bag. +bright chartreuse bags contain 1 dotted teal bag, 3 shiny lavender bags. +vibrant tomato bags contain 1 vibrant coral bag. +mirrored purple bags contain 4 dark tan bags, 4 faded coral bags. +pale tomato bags contain 1 dull maroon bag, 2 striped tan bags, 5 muted cyan bags, 2 dark maroon bags. +vibrant brown bags contain 1 vibrant bronze bag, 2 pale yellow bags, 4 wavy coral bags. +dim green bags contain 2 striped coral bags. +muted lavender bags contain 3 clear purple bags, 4 dark red bags, 1 light silver bag, 1 dull blue bag. +wavy crimson bags contain 5 muted teal bags, 1 drab brown bag, 3 posh brown bags. +wavy tomato bags contain 4 striped blue bags, 3 mirrored lime bags, 1 shiny gray bag, 1 dark plum bag. +muted aqua bags contain 3 clear silver bags, 3 bright chartreuse bags, 4 striped teal bags, 2 clear indigo bags. +posh blue bags contain 2 posh teal bags, 4 dark maroon bags, 2 drab brown bags, 5 faded coral bags. +vibrant silver bags contain 5 drab yellow bags, 3 faded silver bags, 2 bright silver bags. +dim chartreuse bags contain 4 pale beige bags. +shiny gray bags contain 3 dotted magenta bags, 4 plaid crimson bags. +dim salmon bags contain 4 clear lime bags, 3 muted tomato bags, 2 shiny olive bags. +clear orange bags contain 4 posh beige bags, 5 dotted gray bags, 5 dotted turquoise bags. +plaid salmon bags contain 4 bright indigo bags. +posh beige bags contain 3 pale red bags. +clear lime bags contain 1 bright gold bag. +faded magenta bags contain 5 dim salmon bags, 3 dull aqua bags, 5 drab crimson bags. +drab blue bags contain 5 dark maroon bags, 4 wavy plum bags. +plaid aqua bags contain 5 mirrored orange bags, 3 dull violet bags, 3 bright salmon bags. +muted teal bags contain 4 dull red bags, 1 light maroon bag, 4 dark cyan bags. +posh green bags contain 1 mirrored chartreuse bag, 4 muted chartreuse bags, 5 plaid olive bags, 4 dark salmon bags. +posh fuchsia bags contain 3 bright cyan bags, 1 bright salmon bag, 4 dim salmon bags, 1 light black bag. +muted yellow bags contain 2 muted teal bags, 5 pale orange bags. +clear cyan bags contain 3 clear teal bags, 5 drab aqua bags, 2 drab brown bags. +wavy salmon bags contain 5 dark fuchsia bags, 2 dull gray bags, 4 pale tan bags. +dull crimson bags contain 5 faded indigo bags, 2 plaid black bags. +mirrored white bags contain 2 dotted plum bags, 2 dark coral bags, 3 faded gray bags. +striped violet bags contain 4 mirrored tan bags. +striped tan bags contain 2 posh coral bags. +striped tomato bags contain 1 muted teal bag, 1 faded tan bag. +faded aqua bags contain 5 faded red bags, 2 mirrored coral bags, 5 light red bags, 2 mirrored purple bags. +drab olive bags contain 2 drab gold bags. +bright lavender bags contain 1 dark salmon bag, 1 striped olive bag. +plaid green bags contain 2 bright gold bags. +dim purple bags contain 1 plaid yellow bag, 3 muted plum bags, 2 vibrant magenta bags. +faded violet bags contain 3 mirrored violet bags. +posh tomato bags contain 1 dark indigo bag, 2 pale yellow bags, 5 dull orange bags. +dim silver bags contain 1 dotted white bag, 5 faded white bags. +dotted red bags contain 2 dull yellow bags, 4 dim lavender bags, 1 light gold bag. +bright indigo bags contain 5 pale gray bags, 3 posh white bags. +faded fuchsia bags contain 4 muted green bags, 3 posh magenta bags. +wavy silver bags contain 1 dotted violet bag, 3 drab tomato bags, 4 dark fuchsia bags. +dim white bags contain 2 bright magenta bags. +pale beige bags contain 5 dim orange bags, 5 vibrant red bags. +vibrant orange bags contain 4 dull violet bags, 2 mirrored salmon bags, 1 drab lavender bag. +clear fuchsia bags contain 1 mirrored olive bag, 4 mirrored chartreuse bags, 1 posh beige bag. +vibrant indigo bags contain 5 dim lavender bags, 4 drab blue bags, 1 muted beige bag. +dim brown bags contain 2 posh brown bags. +plaid beige bags contain 1 dark tan bag, 5 clear teal bags, 2 light gray bags, 4 wavy lime bags. +bright crimson bags contain 4 drab chartreuse bags, 4 vibrant blue bags, 5 mirrored lime bags, 2 muted plum bags. +shiny purple bags contain 1 muted crimson bag. +wavy bronze bags contain 1 dim brown bag, 3 light salmon bags, 1 muted teal bag, 3 plaid olive bags. +faded bronze bags contain 2 striped blue bags, 2 posh white bags, 2 posh orange bags. +dark orange bags contain 2 vibrant aqua bags, 5 dark maroon bags, 1 mirrored aqua bag. +drab green bags contain 2 faded aqua bags, 5 posh crimson bags. +clear white bags contain 3 plaid black bags, 2 posh white bags, 5 posh lavender bags, 1 dull purple bag. +wavy black bags contain 4 bright magenta bags. +posh crimson bags contain 3 dark yellow bags, 1 mirrored purple bag, 2 dark maroon bags, 5 shiny olive bags. +dotted gray bags contain 4 posh maroon bags, 2 mirrored chartreuse bags, 5 wavy fuchsia bags. +vibrant lavender bags contain 2 plaid coral bags, 4 posh brown bags, 4 dim tan bags. +drab violet bags contain 4 muted gold bags. +striped maroon bags contain 4 dotted lavender bags, 2 dark fuchsia bags, 3 bright olive bags. +plaid white bags contain 2 wavy olive bags, 2 pale blue bags, 4 pale aqua bags. +pale gold bags contain 4 bright teal bags, 2 posh bronze bags, 3 shiny maroon bags, 1 pale brown bag. +vibrant olive bags contain 3 plaid green bags, 2 light maroon bags, 3 dotted salmon bags, 4 faded tomato bags. +dotted maroon bags contain no other bags. +light blue bags contain 2 dim violet bags, 1 vibrant beige bag. +mirrored tan bags contain 4 drab brown bags, 1 striped orange bag, 5 light maroon bags, 2 dotted maroon bags. +dark beige bags contain 1 drab maroon bag. +light silver bags contain 1 shiny chartreuse bag, 2 dim turquoise bags. +dull green bags contain 2 striped chartreuse bags, 2 mirrored gold bags, 4 dim fuchsia bags. +faded silver bags contain 3 drab violet bags. +bright beige bags contain 5 bright teal bags, 5 mirrored violet bags. +striped gold bags contain 2 wavy beige bags, 4 dim black bags. +wavy fuchsia bags contain 4 posh green bags. +shiny blue bags contain 3 posh maroon bags. +mirrored indigo bags contain 3 striped cyan bags, 2 vibrant blue bags, 5 wavy violet bags. +dim tomato bags contain 4 dull orange bags, 5 shiny green bags, 1 plaid olive bag. +plaid violet bags contain 1 dull violet bag, 4 plaid fuchsia bags. +dark white bags contain 3 drab orange bags. +drab indigo bags contain 3 dark red bags, 2 plaid tomato bags, 5 clear white bags. +shiny beige bags contain 2 posh tomato bags. +striped indigo bags contain 5 clear lavender bags, 5 dotted indigo bags, 1 muted cyan bag, 5 dark olive bags. +drab cyan bags contain 1 drab orange bag, 4 posh gold bags. +light red bags contain 4 dark indigo bags, 1 vibrant violet bag, 4 shiny magenta bags. +muted gold bags contain 3 light maroon bags, 1 striped orange bag, 4 pale maroon bags. +clear indigo bags contain 4 faded green bags, 3 clear crimson bags, 2 vibrant cyan bags. +faded tan bags contain 5 bright gold bags. +shiny salmon bags contain 1 bright lavender bag, 1 posh blue bag, 4 shiny coral bags. +dull turquoise bags contain 5 drab yellow bags, 5 dotted plum bags, 5 plaid magenta bags. +posh lime bags contain 4 wavy tan bags, 4 shiny tomato bags, 4 dim violet bags, 5 bright tan bags. +pale green bags contain 1 wavy gray bag, 2 faded lavender bags, 1 vibrant yellow bag. +mirrored gold bags contain 2 light gray bags, 5 wavy tan bags. +mirrored green bags contain 1 faded violet bag. +dark red bags contain 3 faded bronze bags, 4 dark green bags, 4 wavy crimson bags. +bright tomato bags contain 4 faded bronze bags. +mirrored crimson bags contain 5 faded red bags, 1 drab crimson bag. +faded orange bags contain 2 muted teal bags, 5 pale maroon bags, 1 dark yellow bag. +striped silver bags contain 4 mirrored lime bags, 1 dull tan bag, 1 pale fuchsia bag, 1 wavy purple bag. +wavy aqua bags contain 4 vibrant aqua bags, 4 shiny fuchsia bags, 4 dotted turquoise bags, 4 striped olive bags. +striped lavender bags contain 5 shiny lavender bags, 3 pale lime bags. +vibrant white bags contain 2 dim bronze bags, 2 light red bags, 5 shiny gold bags. +vibrant yellow bags contain 1 shiny turquoise bag, 5 dull beige bags, 4 dark gold bags, 5 dull tomato bags. +striped green bags contain 5 striped tomato bags. +muted silver bags contain 5 striped maroon bags, 5 light salmon bags, 4 clear maroon bags. +light plum bags contain 5 mirrored blue bags, 2 vibrant coral bags, 5 dim brown bags, 2 striped yellow bags. +posh yellow bags contain 1 mirrored salmon bag, 5 light plum bags. +plaid magenta bags contain 3 dull plum bags, 2 mirrored tan bags. +plaid tan bags contain 4 light turquoise bags, 4 faded purple bags, 3 mirrored crimson bags. +shiny black bags contain 3 striped violet bags, 1 dim cyan bag, 2 dim white bags. +wavy brown bags contain 2 plaid lavender bags. +vibrant gold bags contain 1 clear tomato bag, 1 wavy olive bag, 2 faded magenta bags. +clear brown bags contain 2 dim blue bags. +dim fuchsia bags contain 2 bright gold bags, 5 wavy purple bags, 3 posh orange bags. +muted turquoise bags contain 1 light turquoise bag, 3 vibrant plum bags, 5 posh maroon bags, 1 muted maroon bag. +shiny coral bags contain 3 striped yellow bags. +dotted coral bags contain 1 dark orange bag, 4 striped violet bags. +shiny bronze bags contain 5 mirrored yellow bags, 4 light violet bags, 4 light crimson bags. +dull cyan bags contain 2 dim cyan bags, 5 pale red bags. +bright tan bags contain 4 pale gray bags, 4 posh brown bags, 3 shiny fuchsia bags. +pale purple bags contain 5 wavy cyan bags, 5 dark salmon bags, 2 dark indigo bags, 1 plaid black bag. +shiny gold bags contain 2 pale maroon bags, 5 pale purple bags, 4 posh brown bags, 1 dotted turquoise bag. +dim tan bags contain 4 dark violet bags, 3 shiny blue bags. +wavy green bags contain 3 plaid gray bags. +pale orange bags contain 3 dim lime bags, 2 dark coral bags. +faded maroon bags contain 5 clear black bags, 3 light lavender bags, 3 light black bags, 2 muted orange bags. +drab teal bags contain 2 dotted crimson bags, 3 dim teal bags, 5 pale turquoise bags, 4 dark plum bags. +bright orange bags contain 3 pale maroon bags, 1 pale bronze bag, 3 dotted maroon bags. +posh coral bags contain 3 dim gold bags, 1 bright indigo bag, 3 clear black bags. +mirrored bronze bags contain 5 dull violet bags, 3 vibrant red bags. +pale lavender bags contain 2 pale purple bags, 1 pale red bag, 4 vibrant blue bags, 3 muted chartreuse bags. +wavy lavender bags contain 3 drab chartreuse bags, 1 posh teal bag. +pale blue bags contain 1 dark tan bag, 4 faded violet bags, 3 dim coral bags. +striped yellow bags contain 2 pale red bags. +shiny aqua bags contain 3 pale magenta bags. +faded olive bags contain 1 vibrant white bag, 4 muted cyan bags. +dark chartreuse bags contain 3 dim magenta bags, 3 dull plum bags, 2 pale lime bags. +dim lime bags contain 3 muted white bags, 4 striped blue bags. +wavy cyan bags contain 4 light maroon bags. +light bronze bags contain 1 dull lime bag. +muted beige bags contain 4 wavy blue bags, 2 dotted violet bags, 4 shiny orange bags. +dim coral bags contain 4 wavy crimson bags, 3 mirrored tan bags, 2 wavy cyan bags, 5 light maroon bags. +dark green bags contain 2 striped gray bags, 3 pale lavender bags, 1 striped lime bag. +pale cyan bags contain 2 vibrant green bags, 1 mirrored lime bag, 5 vibrant chartreuse bags, 1 shiny lime bag. +shiny crimson bags contain 4 dull aqua bags, 1 pale turquoise bag. +pale black bags contain 3 vibrant olive bags, 2 dull aqua bags, 1 drab turquoise bag. +striped crimson bags contain 4 dotted lavender bags, 2 clear orange bags. +clear maroon bags contain 2 muted bronze bags, 3 vibrant olive bags, 1 striped lavender bag. +dim olive bags contain 1 wavy lavender bag, 1 dotted salmon bag, 1 pale silver bag, 5 vibrant coral bags. +dotted indigo bags contain 3 dark salmon bags, 2 shiny turquoise bags, 4 plaid coral bags. +plaid orange bags contain 2 mirrored plum bags, 5 faded lime bags, 4 dotted brown bags, 2 pale tan bags. +light maroon bags contain no other bags. +light violet bags contain 5 clear yellow bags, 4 muted chartreuse bags. +light lavender bags contain 3 striped olive bags, 1 posh black bag. +muted lime bags contain 2 muted turquoise bags, 3 mirrored yellow bags, 5 clear gray bags. +faded black bags contain 1 bright crimson bag, 1 dotted beige bag, 2 shiny magenta bags. +wavy blue bags contain 5 vibrant plum bags, 5 shiny fuchsia bags, 2 posh orange bags, 1 wavy purple bag. +dark turquoise bags contain 5 shiny tan bags, 2 dull silver bags, 2 muted lime bags, 2 mirrored tan bags. +mirrored teal bags contain 4 pale brown bags, 5 drab lime bags, 5 striped beige bags. +vibrant gray bags contain 5 bright yellow bags, 1 vibrant teal bag. +clear purple bags contain 5 bright silver bags, 1 bright teal bag, 1 wavy lime bag, 4 striped blue bags. +striped lime bags contain 1 mirrored violet bag, 3 dim cyan bags, 3 vibrant turquoise bags, 2 muted white bags. +mirrored lavender bags contain 2 faded yellow bags. +posh maroon bags contain 1 dotted salmon bag, 5 drab violet bags, 5 striped lime bags, 3 dotted olive bags. +faded yellow bags contain 1 dull plum bag, 5 dim fuchsia bags. +dull aqua bags contain 2 pale maroon bags. +dark tan bags contain 4 dark salmon bags. +dim maroon bags contain 4 posh aqua bags, 3 striped yellow bags. +faded purple bags contain 5 clear teal bags, 2 dark olive bags. +clear tomato bags contain 2 pale maroon bags. +dull gray bags contain 5 light brown bags, 3 bright gold bags, 4 faded white bags, 3 vibrant coral bags. +dull maroon bags contain 4 clear indigo bags, 5 shiny magenta bags, 3 drab tomato bags, 4 dim violet bags. +pale coral bags contain 2 pale bronze bags, 2 wavy salmon bags. +drab silver bags contain 3 dark coral bags, 5 shiny violet bags, 5 faded indigo bags. +plaid black bags contain 1 dull red bag. +plaid silver bags contain 4 clear cyan bags. +dotted blue bags contain 2 plaid beige bags, 4 posh cyan bags, 4 shiny gray bags. +dotted magenta bags contain 1 drab orange bag, 5 wavy aqua bags, 2 wavy lavender bags. +clear aqua bags contain 4 striped magenta bags, 4 muted chartreuse bags. +pale red bags contain no other bags. +bright turquoise bags contain 1 wavy purple bag, 3 vibrant turquoise bags, 2 dark brown bags. +vibrant magenta bags contain 5 drab brown bags, 2 striped olive bags, 5 light plum bags. +dull brown bags contain 4 drab teal bags, 4 bright gold bags, 4 dim blue bags, 3 dotted teal bags. +dotted olive bags contain 5 striped orange bags, 1 wavy cyan bag, 3 wavy crimson bags. +bright teal bags contain 3 dim coral bags, 1 dark cyan bag, 4 bright indigo bags. +shiny chartreuse bags contain 1 drab brown bag. +bright lime bags contain 2 pale silver bags. +vibrant crimson bags contain 4 shiny white bags, 4 pale black bags, 5 clear cyan bags, 1 bright tan bag. +muted brown bags contain 5 drab purple bags. +dotted aqua bags contain 1 dim gray bag, 1 dark indigo bag, 3 posh tan bags, 5 dim lime bags. +muted tomato bags contain 1 faded orange bag, 3 vibrant aqua bags. +bright cyan bags contain 4 dotted coral bags, 2 dull lime bags, 5 clear maroon bags. +posh violet bags contain 1 light magenta bag, 4 pale maroon bags, 1 dark teal bag. +wavy turquoise bags contain 1 shiny gray bag, 4 drab tan bags, 3 pale lavender bags. +dark magenta bags contain 2 dull bronze bags. +drab gray bags contain 4 dotted turquoise bags, 5 light aqua bags. +dull coral bags contain 2 plaid black bags, 2 striped cyan bags, 3 faded bronze bags, 5 plaid crimson bags. +vibrant chartreuse bags contain 5 pale turquoise bags. +bright purple bags contain 5 vibrant salmon bags, 1 posh green bag, 4 vibrant beige bags. +mirrored tomato bags contain 4 wavy beige bags, 5 striped tan bags, 2 pale aqua bags. +shiny violet bags contain 3 shiny tan bags, 3 faded brown bags, 4 shiny green bags, 3 shiny orange bags. +plaid lavender bags contain 1 light maroon bag. +faded green bags contain 5 dark cyan bags, 2 clear teal bags, 5 muted olive bags. +dotted salmon bags contain 3 dotted olive bags, 1 dark cyan bag. +faded white bags contain 3 drab brown bags. +striped black bags contain 2 dark green bags, 5 pale bronze bags, 2 plaid olive bags. +dotted brown bags contain 1 drab salmon bag. +dark crimson bags contain 1 vibrant teal bag, 2 dim gray bags, 1 posh orange bag, 3 faded tan bags. +pale teal bags contain 5 dim violet bags. +striped cyan bags contain 3 pale purple bags, 4 dull red bags, 1 dark indigo bag, 3 dark yellow bags. +mirrored coral bags contain 2 shiny olive bags. +shiny maroon bags contain 5 vibrant coral bags, 3 plaid maroon bags, 1 striped turquoise bag, 2 wavy violet bags. +dull indigo bags contain 2 plaid magenta bags, 1 bright chartreuse bag. +drab magenta bags contain 4 striped olive bags, 3 posh white bags. +clear tan bags contain 4 light gold bags, 4 muted gold bags. +dark gray bags contain 4 plaid blue bags, 5 drab brown bags, 3 pale gray bags, 3 mirrored violet bags. +wavy teal bags contain 4 drab aqua bags, 3 pale salmon bags. +dotted tan bags contain 2 pale bronze bags, 3 faded orange bags. +bright brown bags contain 3 bright blue bags. +clear blue bags contain 5 shiny crimson bags, 1 dark cyan bag. +clear yellow bags contain 1 muted gold bag, 1 posh orange bag, 1 dull purple bag, 4 dark indigo bags. +pale aqua bags contain 3 dim coral bags, 2 mirrored aqua bags. +dull olive bags contain 1 dull yellow bag. +muted violet bags contain 3 shiny tan bags. +striped aqua bags contain 2 vibrant green bags, 2 faded coral bags, 2 dark cyan bags, 4 wavy beige bags. +pale fuchsia bags contain 5 dull green bags, 2 dotted aqua bags. +shiny brown bags contain 4 dim black bags. +plaid coral bags contain 3 faded bronze bags, 2 pale lavender bags, 3 dotted tan bags, 2 wavy lavender bags. +posh magenta bags contain 2 clear red bags, 4 dim brown bags. +wavy purple bags contain 4 dim magenta bags. +plaid fuchsia bags contain 2 striped olive bags, 3 light gray bags. +dim violet bags contain 3 dark brown bags, 4 muted plum bags. +light turquoise bags contain 5 clear brown bags, 5 muted chartreuse bags. +dull white bags contain 4 wavy salmon bags, 3 dotted crimson bags, 1 dark coral bag, 1 pale chartreuse bag. +light brown bags contain 2 plaid black bags, 3 light red bags. +dotted purple bags contain 1 posh crimson bag, 4 vibrant red bags, 2 wavy beige bags. +striped orange bags contain no other bags. +clear green bags contain 3 light plum bags, 1 wavy lavender bag, 1 shiny olive bag. +bright red bags contain 5 dotted turquoise bags, 3 dim aqua bags, 2 posh orange bags. +dark bronze bags contain 2 pale yellow bags, 1 striped brown bag, 3 striped chartreuse bags. +muted cyan bags contain 3 muted olive bags, 2 shiny red bags, 1 vibrant lavender bag, 5 drab gold bags. +light coral bags contain 3 shiny gray bags, 5 dull bronze bags, 5 muted fuchsia bags, 5 clear magenta bags. +shiny olive bags contain 4 dull cyan bags, 5 dark gray bags. +drab orange bags contain no other bags. +striped salmon bags contain 5 drab salmon bags, 5 pale plum bags. +plaid cyan bags contain 2 bright blue bags, 1 mirrored gray bag, 5 faded violet bags. +plaid teal bags contain 3 pale maroon bags, 1 clear teal bag. +faded cyan bags contain 1 dim bronze bag, 3 light olive bags, 1 muted beige bag, 1 wavy teal bag. +clear magenta bags contain 5 striped orange bags. +dull black bags contain 1 shiny purple bag, 1 mirrored red bag, 4 dotted fuchsia bags, 3 vibrant crimson bags. +mirrored blue bags contain 3 light brown bags. +mirrored black bags contain 3 dim coral bags, 3 plaid purple bags. +dim black bags contain 4 dim blue bags. +pale plum bags contain 4 muted coral bags, 2 light purple bags. +dark salmon bags contain 2 plaid blue bags, 4 vibrant turquoise bags, 3 posh white bags. +striped red bags contain 1 dim plum bag. +striped beige bags contain 1 dark tomato bag. +clear beige bags contain 2 posh orange bags, 4 muted coral bags. +bright blue bags contain 4 faded gold bags, 4 faded indigo bags. +light purple bags contain 4 muted violet bags, 1 pale red bag. +dim indigo bags contain 3 dim silver bags, 2 faded violet bags. +dotted green bags contain 5 dotted chartreuse bags, 1 pale black bag. +pale yellow bags contain 3 plaid tomato bags. +drab tan bags contain 3 dim plum bags, 2 dark fuchsia bags. +bright white bags contain 3 muted bronze bags. +shiny turquoise bags contain 4 drab brown bags. +pale maroon bags contain no other bags. +faded indigo bags contain 1 faded tomato bag, 2 light red bags, 5 vibrant bronze bags. +dotted black bags contain 1 clear brown bag, 5 mirrored olive bags, 4 dim brown bags, 2 drab red bags. +light chartreuse bags contain 5 muted black bags. +posh orange bags contain 4 light maroon bags, 1 muted white bag. +vibrant turquoise bags contain 1 dark maroon bag, 1 shiny magenta bag, 2 dotted maroon bags. +striped fuchsia bags contain 5 clear blue bags, 5 pale black bags, 1 mirrored maroon bag, 2 dotted maroon bags. +dark violet bags contain 5 clear white bags. +pale salmon bags contain 1 vibrant violet bag, 3 plaid olive bags. +pale violet bags contain 4 shiny chartreuse bags, 5 dark salmon bags, 3 bright indigo bags, 4 dark orange bags. +faded teal bags contain 2 dark gray bags, 2 posh black bags, 3 plaid maroon bags. +drab yellow bags contain 4 mirrored blue bags, 4 mirrored violet bags, 3 dim salmon bags, 1 clear yellow bag. +wavy indigo bags contain 2 shiny olive bags, 5 plaid aqua bags. +shiny tan bags contain 2 wavy purple bags, 1 dotted aqua bag, 1 light violet bag. +dull lime bags contain 1 dull coral bag. +clear turquoise bags contain 1 vibrant fuchsia bag, 5 dull beige bags. +dark blue bags contain 2 dark violet bags, 2 dotted maroon bags, 4 bright aqua bags, 4 clear black bags. +drab black bags contain 2 dim gold bags, 1 plaid crimson bag. +dotted bronze bags contain 5 dim bronze bags. +mirrored cyan bags contain 3 muted salmon bags. +light gray bags contain 1 faded gold bag, 4 faded coral bags, 4 faded silver bags, 2 faded tomato bags. +vibrant blue bags contain 2 muted gold bags. +dark maroon bags contain 3 mirrored violet bags, 3 muted gold bags, 3 drab brown bags, 4 plaid black bags. +pale chartreuse bags contain 5 dotted teal bags, 4 bright gold bags. +mirrored yellow bags contain 4 dim cyan bags. +shiny plum bags contain 3 dull green bags, 3 vibrant olive bags, 3 dim tan bags. +mirrored chartreuse bags contain 1 dark tan bag, 5 drab aqua bags. +dark gold bags contain 4 drab yellow bags, 4 pale bronze bags. +vibrant lime bags contain 3 dull salmon bags. +dim blue bags contain 2 dull cyan bags, 2 dull purple bags, 1 dark indigo bag. +dark brown bags contain 5 dull chartreuse bags. +light tomato bags contain 5 posh teal bags, 3 wavy yellow bags, 5 bright olive bags, 4 pale brown bags. +bright green bags contain 2 bright teal bags. +shiny silver bags contain 2 mirrored indigo bags, 4 faded silver bags, 2 dark lavender bags. +bright olive bags contain 5 drab turquoise bags. +striped teal bags contain 1 vibrant tan bag. +dotted yellow bags contain 1 clear tomato bag, 5 muted orange bags, 3 striped turquoise bags, 3 dim lime bags. +posh white bags contain no other bags. +plaid red bags contain 3 dotted teal bags, 2 light brown bags, 4 vibrant teal bags. +drab purple bags contain 5 pale purple bags, 1 shiny blue bag, 2 shiny orange bags. +vibrant maroon bags contain 3 shiny cyan bags, 5 striped lavender bags. +striped brown bags contain 5 faded salmon bags, 4 clear violet bags, 1 plaid salmon bag, 5 dotted tomato bags. +muted blue bags contain 1 drab chartreuse bag. +striped blue bags contain 4 dark cyan bags. +striped plum bags contain 2 wavy violet bags. +clear violet bags contain 2 dotted crimson bags, 3 plaid magenta bags. +clear teal bags contain 2 bright gold bags, 4 plaid black bags. +dim gold bags contain 5 pale gray bags, 3 drab orange bags, 3 plaid black bags. +wavy violet bags contain 3 dull beige bags. +wavy lime bags contain 2 bright lavender bags. +muted purple bags contain 3 wavy brown bags, 4 muted blue bags. +shiny indigo bags contain 1 shiny aqua bag, 4 bright aqua bags, 2 clear turquoise bags. +dim orange bags contain 5 striped lime bags. +clear bronze bags contain 4 pale black bags, 4 bright olive bags. +wavy gray bags contain 3 dotted teal bags, 2 striped lavender bags, 2 wavy aqua bags. +dull tan bags contain 5 vibrant violet bags, 2 muted maroon bags, 5 vibrant plum bags, 3 shiny red bags. +drab chartreuse bags contain 4 striped gray bags, 4 pale bronze bags, 5 dim aqua bags. +plaid gray bags contain 1 shiny blue bag, 4 clear brown bags, 4 shiny tan bags, 4 plaid beige bags. +drab plum bags contain 5 vibrant cyan bags, 3 vibrant aqua bags, 5 dim coral bags, 1 dull orange bag. +clear gold bags contain 1 drab olive bag, 5 drab orange bags, 4 shiny tan bags. +dull tomato bags contain 3 bright teal bags, 1 muted chartreuse bag. +bright silver bags contain 1 dull chartreuse bag, 5 bright gold bags, 4 faded silver bags. +clear black bags contain 5 dull orange bags, 3 dim black bags, 1 posh beige bag. +striped olive bags contain 2 pale maroon bags. +light fuchsia bags contain 5 pale silver bags, 4 dark olive bags, 1 clear magenta bag. +posh indigo bags contain 2 wavy purple bags, 3 striped beige bags, 4 vibrant white bags. +dark aqua bags contain 5 drab tomato bags, 4 faded red bags, 4 light magenta bags, 4 striped tomato bags. +plaid olive bags contain 2 posh brown bags. +wavy plum bags contain 3 shiny blue bags, 4 dark lavender bags, 5 pale violet bags. +vibrant teal bags contain 4 dull purple bags, 4 dull plum bags. +dotted gold bags contain 3 wavy maroon bags. +drab brown bags contain no other bags. +dull teal bags contain 5 wavy beige bags, 1 muted tomato bag, 1 drab aqua bag. +mirrored plum bags contain 4 muted chartreuse bags, 5 dull orange bags, 3 clear black bags. +wavy beige bags contain 4 pale violet bags, 5 dim tan bags, 3 pale fuchsia bags, 2 wavy tan bags. +plaid lime bags contain 3 pale crimson bags. +plaid brown bags contain 2 dull green bags. +light black bags contain 1 faded gold bag, 1 bright tan bag. +dim cyan bags contain 2 clear yellow bags, 3 plaid blue bags, 1 dull purple bag. +drab coral bags contain 1 bright gray bag, 1 muted magenta bag, 5 mirrored lime bags, 1 mirrored olive bag. +bright coral bags contain 3 plaid blue bags. +mirrored silver bags contain 5 clear white bags. +plaid tomato bags contain 5 dull red bags, 3 shiny green bags, 5 drab fuchsia bags, 3 dull tomato bags. +faded plum bags contain 5 dark violet bags, 3 dim brown bags. +light white bags contain 5 dotted teal bags, 2 dim tan bags. +dull bronze bags contain 3 vibrant turquoise bags. +vibrant coral bags contain 3 faded bronze bags. +posh silver bags contain 5 wavy olive bags, 3 dotted red bags, 3 faded violet bags. +dim yellow bags contain 4 pale tomato bags, 4 dim tan bags, 3 vibrant gold bags, 2 bright gold bags. +bright salmon bags contain 5 shiny orange bags, 2 dark yellow bags, 5 muted gold bags, 4 dark fuchsia bags. +light yellow bags contain 3 clear cyan bags. +dim red bags contain 3 clear lavender bags, 1 muted bronze bag, 4 vibrant salmon bags. +dark silver bags contain 1 dull brown bag, 1 wavy lavender bag, 2 shiny crimson bags, 1 clear tan bag. +dull fuchsia bags contain 5 striped cyan bags, 4 mirrored violet bags. +drab gold bags contain 5 posh lavender bags, 4 mirrored olive bags, 2 dark tan bags, 3 dotted olive bags. +muted gray bags contain 1 striped magenta bag, 2 dull tomato bags, 5 plaid olive bags, 1 faded gray bag. +bright bronze bags contain 1 clear silver bag, 4 dim lime bags. +dark cyan bags contain 5 dark maroon bags, 3 dull red bags, 1 bright gold bag. +dark plum bags contain 1 vibrant turquoise bag. +wavy maroon bags contain 5 shiny gold bags, 1 drab black bag. +light crimson bags contain 2 light plum bags, 3 plaid purple bags. +wavy chartreuse bags contain 2 pale gray bags, 5 dim purple bags, 2 drab turquoise bags. +plaid yellow bags contain 5 muted tan bags, 2 wavy cyan bags, 3 light gold bags, 1 dim gold bag. +mirrored violet bags contain no other bags. +wavy yellow bags contain 2 dim aqua bags, 1 dark fuchsia bag, 5 faded coral bags, 1 faded silver bag. +plaid bronze bags contain 1 striped bronze bag. +vibrant green bags contain 3 striped chartreuse bags, 3 pale lavender bags, 4 dotted lime bags, 4 plaid lavender bags. +muted crimson bags contain 3 dim blue bags, 1 dull lime bag, 3 plaid indigo bags, 1 pale plum bag. +posh cyan bags contain 5 drab brown bags, 5 faded blue bags. +vibrant black bags contain 3 pale silver bags. +light aqua bags contain 2 faded crimson bags, 3 dark bronze bags, 1 dim orange bag. +mirrored red bags contain 3 light violet bags. +dark lime bags contain 1 striped turquoise bag. +mirrored olive bags contain 1 faded bronze bag, 1 drab aqua bag, 1 dark indigo bag, 3 posh white bags. +striped chartreuse bags contain 2 mirrored gold bags. +dotted lime bags contain 1 vibrant turquoise bag, 2 dotted turquoise bags, 5 dull red bags. +vibrant bronze bags contain 1 posh green bag, 3 posh tan bags, 5 light salmon bags. +dark teal bags contain 4 shiny lavender bags, 5 dull orange bags. +shiny green bags contain 2 bright lavender bags, 3 shiny olive bags, 4 mirrored violet bags, 5 posh white bags. +light magenta bags contain 2 pale maroon bags. +pale magenta bags contain 5 dull aqua bags. +dull plum bags contain 2 vibrant violet bags, 5 pale red bags, 2 wavy fuchsia bags. +muted olive bags contain 5 bright teal bags. +vibrant fuchsia bags contain 3 posh brown bags. +dark olive bags contain 5 dim coral bags, 4 pale red bags, 5 drab aqua bags. +posh purple bags contain 2 bright red bags, 4 pale coral bags, 1 dotted bronze bag. +dark lavender bags contain 2 striped blue bags, 5 posh blue bags, 2 plaid green bags. diff --git a/day7/src/main.zig b/day7/src/main.zig new file mode 100644 index 0000000..6306bc7 --- /dev/null +++ b/day7/src/main.zig @@ -0,0 +1,188 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + + var next_id : u32 = 0; + var map = std.hash_map.StringHashMap(u32).init(gpa); + var it = std.mem.tokenize(contents, "\n"); + var bag_rules = std.ArrayList(*BagType).init(gpa); + defer bag_rules.deinit(); + + while (it.next()) |line| { + //std.log.debug("{}", .{line}); + var bag = try gpa.create(BagType); + bag.*.contains = std.ArrayList(*BagRule).init(gpa); + + var need_desc = true; + var desc = std.ArrayList(u8).init(gpa); + defer desc.deinit(); + var need_count = true; + var count: u32 = 0; + for (line) |a| { + if (need_desc) { + try desc.append(a); + if (desc.items.len > 5) { + if (std.mem.eql(u8, " bag", desc.items[desc.items.len-4..])) { + //std.log.debug("'{}'", .{desc.items}); + if (!need_count) { + var key = try std.mem.dupe(gpa, u8, std.mem.trim(u8, desc.items[0..desc.items.len-4], " ")); + var bag_id : u32 = 0; + //std.log.debug("'{} {} bags'", .{count, key}); + if (map.contains(key)) { + bag_id = map.get(key).?; + //std.log.debug("Bag '{}': {}", .{key, bag_id}); + } + else { + bag_id = next_id; + //std.log.debug("Assigned ID {} to '{}'", .{bag_id, key}); + try map.putNoClobber(key, next_id); + next_id += 1; + } + var br = try gpa.create(BagRule); + br.count = count; + br.bag_type = bag_id; + std.log.debug("Bag {} should contain {} of {}", .{bag.desc, br.count, br.bag_type}); + try bag.contains.append(br); + } + else { + var key = try std.mem.dupe(gpa, u8, desc.items[0..desc.items.len-4]); + var bag_id : u32 = 0; + bag.desc = key; + //std.log.debug("'{}'", .{bag.desc}); + if (map.contains(key)) { + bag_id = map.get(key).?; + //std.log.debug("Bag '{}': {}", .{key, bag_id}); + } + else { + bag_id = next_id; + //std.log.debug("Assigned ID {} to '{}'", .{bag_id, key}); + try map.putNoClobber(key, next_id); + next_id += 1; + } + bag.type_id = bag_id; + } + need_desc = false; + need_count = true; + desc.deinit(); + desc = std.ArrayList(u8).init(gpa); + } + } + } + else if (need_count) { + if (std.ascii.isDigit(a)) { + count = @as(u32, a - 48); + need_count = false; + need_desc = true; + } + } + } + //std.log.debug("{}", .{bag}); + try bag_rules.append(bag); + } + // for (bag_rules.items) |rule| { + // std.log.debug("{} ({})", .{rule.desc.?, rule.type_id}); + // for(rule.contains.items) |r| { + // std.log.debug("\t{} of {}", .{r.count, r.bag_type}); + // } + // } + var shiny_gold_id = map.get("shiny gold"); + std.log.debug("shiny gold: {}", .{shiny_gold_id}); + + //var types_that_can_contain_shiny_gold = try types_that_can_contain(gpa, &bag_rules, shiny_gold_id.?); + //std.log.info("{} bag types can contain shiny gold bags ({})", .{types_that_can_contain_shiny_gold.len, shiny_gold_id}); + + var shiny_gold_type = get_type_by_id(&bag_rules, shiny_gold_id.?).?; + std.log.debug("shiny gold type has {} contain rules", .{shiny_gold_type.*.contains.items.len}); + //std.log.debug("{}", .{shiny_gold_rule}); + var n_bags_needed = bag_type_has_how_many_bags_needed(shiny_gold_type, &bag_rules); + std.log.info("{} needs {} bags purchased, including itself", .{shiny_gold_type.*.desc, n_bags_needed}); +} + +fn bag_type_has_how_many_bags_needed(self: *BagType, list: *std.ArrayList(*BagType)) u32 { + var count : u32 = 1; + if (self.contains.items.len == 0) { + // We just need our self + std.log.debug("{} just has itself", .{self.type_id}); + return count; + } + std.log.debug("{}", .{self.contains.items.len}); + for (self.contains.items) |i| { + if (i.*.count == 0) { + continue; + } + var bagtype = get_type_by_id(list, i.*.bag_type).?; + var extra = (i.*.count * bag_type_has_how_many_bags_needed(bagtype, list)); + std.log.debug("{} needs {}x {} --> adding {} bags", .{self.*.desc, i.*.count, bagtype.*.desc, extra}); + count += extra; + } + return count; +} + +fn get_type_by_id(list: *std.ArrayList(*BagType), id: u32) ?*BagType { + for (list.items) |r| { + if (r.*.type_id == id) { + return r; + } + } + return null; +} + +// fn types_that_can_contain(allocator: *std.mem.Allocator, list: *std.ArrayList(BagType), id: u32) anyerror![]u32 { +// var search_ids = std.ArrayList(u32).init(allocator); +// defer search_ids.deinit(); +// for (list.items) |r| { +// if (r.can_contain(id)) { +// //std.log.debug("{} can contain {}", .{r.type_id, id}); +// try search_ids.append(r.type_id); +// } +// } +// var count : usize = search_ids.items.len; +// //std.log.debug("{} bag types can directly contain a {}", +// // .{count, id}); +// var types = std.ArrayList(u32).init(allocator); +// for (search_ids.items) |i| { +// var t = try types_that_can_contain(allocator, list, i); +// //std.log.debug("Adding {} to types that can hold {}", .{i, id}); +// try types.append(i); +// for (t) |tid| { +// var already_in_types = false; +// for (types.items) |asdf| { +// if (asdf == tid) { +// already_in_types = true; +// break; +// } +// } +// if (!already_in_types) { +// //std.log.debug("Adding {} to types that can hold {}", .{tid, id}); +// try types.append(tid); +// } +// } +// } +// return types.items[0..]; +// } + +const BagRule = struct { + bag_type: u32 = 0, + count: u32 = 0, +}; + +const BagType = struct { + type_id: u32 = 0, + desc: ?[]u8 = null, + contains: std.ArrayList(*BagRule), + + pub fn can_contain(self: *const BagType, type_id: u32) bool { + for (self.contains.items) |rule| { + if (rule.*.bag_type == type_id and rule.*.count > 0) { + return true; + } + } + return false; + } +}; diff --git a/day8/build.zig b/day8/build.zig new file mode 100644 index 0000000..f21dc9c --- /dev/null +++ b/day8/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day8", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day8/input b/day8/input new file mode 100644 index 0000000..62e61dd --- /dev/null +++ b/day8/input @@ -0,0 +1,634 @@ +acc +15 +acc +2 +acc -14 +jmp +362 +acc +22 +nop +236 +jmp +474 +acc +10 +jmp +1 +acc +0 +jmp +236 +acc +10 +acc +14 +jmp +334 +acc +12 +acc -1 +jmp +478 +jmp +90 +jmp +208 +acc +49 +jmp +94 +acc +2 +acc -8 +jmp +375 +nop +21 +acc +0 +acc +10 +nop +25 +jmp +492 +nop +182 +acc +49 +acc -12 +jmp -14 +acc -16 +jmp +140 +acc -3 +acc -18 +acc +28 +acc -6 +jmp +558 +acc +2 +acc +27 +nop +438 +acc +41 +jmp +508 +acc +13 +jmp +117 +acc +21 +acc -13 +acc +34 +jmp +1 +jmp +1 +nop +451 +acc +28 +acc +31 +acc +31 +jmp +280 +acc +32 +acc +35 +acc -18 +jmp +509 +acc -15 +acc -8 +nop +288 +acc -16 +jmp +376 +acc -19 +acc -8 +acc +11 +acc +10 +jmp +50 +acc +19 +nop -58 +acc -9 +jmp +43 +acc +10 +acc +2 +nop -63 +jmp +280 +acc -7 +jmp +175 +jmp +69 +acc +16 +acc +9 +acc -2 +acc -5 +jmp +276 +nop +195 +acc +50 +acc -8 +jmp -55 +nop +1 +nop -78 +acc +31 +jmp +535 +acc +9 +acc +33 +acc +4 +acc +48 +jmp +8 +acc +30 +acc +42 +acc +18 +acc +37 +jmp -69 +nop +121 +jmp +44 +acc +3 +acc +33 +acc -6 +acc +37 +jmp +403 +acc -6 +jmp +245 +jmp -93 +acc +5 +jmp +406 +jmp -26 +nop -47 +jmp +239 +acc +7 +acc +31 +acc +14 +acc +0 +jmp +291 +acc +46 +jmp +394 +acc +44 +acc +36 +nop +45 +jmp +137 +acc -16 +acc +10 +acc -4 +acc +7 +jmp +76 +acc +24 +jmp +93 +acc +17 +acc +0 +acc +6 +acc +4 +jmp +385 +acc -8 +acc +49 +acc +28 +jmp +95 +nop +12 +acc +33 +jmp +153 +nop +254 +acc +18 +acc -16 +acc +50 +jmp +299 +acc +27 +acc +47 +acc -17 +jmp -15 +acc +35 +acc +14 +jmp +204 +jmp +93 +acc +46 +nop -5 +nop -158 +jmp +221 +jmp +321 +acc -2 +acc +49 +acc +3 +acc -17 +jmp -52 +jmp +7 +nop +52 +acc +25 +jmp +376 +acc -3 +nop -133 +jmp +32 +jmp +328 +nop +374 +acc +37 +acc +6 +jmp +92 +acc +47 +nop +394 +jmp -13 +jmp -170 +acc +9 +jmp -47 +acc -18 +acc +27 +jmp +1 +acc +3 +acc -5 +jmp +337 +acc +21 +jmp +364 +acc +24 +acc +43 +acc +50 +jmp +58 +jmp -18 +acc +30 +jmp +144 +nop +5 +acc +50 +nop +245 +nop +133 +jmp +270 +jmp -22 +nop -76 +jmp +398 +acc +40 +acc +30 +jmp +361 +acc +36 +acc +30 +jmp +392 +acc -17 +nop +71 +acc -12 +jmp +102 +acc +17 +jmp +283 +acc -16 +jmp +65 +nop -2 +jmp +149 +jmp -103 +jmp -179 +acc +46 +jmp +289 +acc +48 +jmp +114 +acc +13 +jmp +114 +nop +215 +nop -89 +jmp +337 +acc -2 +acc +2 +acc -7 +jmp -18 +jmp -51 +acc +30 +acc +43 +acc +28 +jmp -188 +acc +36 +acc +7 +acc -5 +acc +38 +jmp +88 +jmp +225 +acc -14 +acc -3 +acc -15 +jmp +66 +acc +7 +acc +43 +nop -210 +acc -9 +jmp +109 +acc -10 +jmp +242 +acc -5 +acc +15 +acc +8 +jmp +310 +acc +31 +acc -2 +acc +11 +acc -15 +jmp +103 +acc +32 +jmp -92 +acc -10 +acc +6 +acc -1 +jmp -131 +acc +43 +acc +30 +acc +13 +acc +33 +jmp +25 +acc +9 +acc -14 +acc +19 +acc +44 +jmp -50 +acc -8 +acc +9 +jmp +312 +jmp -96 +acc -3 +acc -3 +acc +24 +jmp +94 +acc -15 +jmp +61 +acc +19 +nop -89 +acc +24 +nop -94 +jmp +5 +acc -13 +acc +25 +acc +42 +jmp +1 +jmp +137 +acc +44 +acc +44 +acc +41 +jmp +152 +jmp +144 +acc -1 +nop +293 +jmp -120 +acc -17 +nop -171 +acc +27 +jmp -173 +jmp +231 +acc +3 +jmp +109 +acc +18 +acc +32 +acc -14 +acc -8 +jmp +177 +acc +28 +jmp -134 +nop +277 +jmp -124 +jmp +167 +nop +274 +acc +6 +acc +43 +acc +10 +jmp -320 +acc +28 +acc -9 +acc +22 +jmp -90 +jmp -203 +jmp -133 +jmp -6 +jmp -181 +jmp +170 +acc +40 +acc +5 +jmp -274 +acc +36 +acc +24 +nop +6 +jmp -339 +jmp -251 +acc +10 +acc +10 +jmp -347 +jmp +263 +acc +37 +jmp -201 +acc -11 +acc +42 +jmp +153 +nop -179 +acc -9 +jmp +8 +jmp -289 +jmp -25 +acc +45 +jmp -142 +acc +42 +acc -10 +jmp +83 +acc +43 +acc +3 +acc -6 +jmp -222 +acc +41 +acc +14 +acc +7 +acc +2 +jmp -35 +jmp +168 +acc +11 +acc +18 +acc +8 +acc -4 +jmp -203 +acc +44 +jmp +10 +nop -184 +acc +0 +jmp +91 +acc -5 +nop +226 +acc +46 +acc -10 +jmp -15 +jmp -321 +acc +0 +acc +33 +jmp +82 +jmp +1 +acc -12 +acc +30 +jmp +152 +acc +6 +jmp -208 +acc +43 +jmp +39 +acc +23 +acc +23 +acc +24 +acc +26 +jmp -390 +acc +15 +acc +3 +acc +14 +acc +46 +jmp -239 +acc -10 +acc +19 +jmp +167 +acc +46 +acc +0 +jmp -280 +acc -7 +jmp -107 +acc +13 +jmp -76 +acc +48 +jmp -65 +nop +23 +nop -89 +acc +47 +jmp -304 +acc -5 +jmp +1 +acc +50 +acc +37 +jmp -129 +acc +27 +jmp +1 +jmp -212 +acc +18 +acc +29 +acc +1 +jmp -74 +acc +24 +acc -12 +jmp -173 +acc -18 +acc -6 +nop -156 +jmp -309 +acc +46 +acc -13 +acc +41 +acc +11 +jmp -188 +acc +32 +jmp -190 +acc +31 +acc +30 +jmp -122 +acc -7 +jmp +37 +acc +2 +acc +16 +acc +45 +acc +44 +jmp -376 +acc +47 +jmp +1 +jmp -147 +acc +47 +acc -18 +acc -1 +acc +2 +jmp -152 +acc +12 +acc -8 +jmp +90 +nop +67 +acc +9 +jmp +1 +jmp -377 +jmp +1 +jmp -238 +jmp +1 +acc +47 +acc +7 +acc +31 +jmp -427 +acc +10 +acc +13 +nop +13 +jmp -8 +nop -292 +acc +11 +nop -203 +jmp -164 +jmp -19 +acc +31 +jmp -289 +acc -7 +acc -16 +acc +35 +jmp -333 +jmp -500 +acc +32 +acc +29 +acc +18 +acc +14 +jmp -161 +jmp -60 +jmp +6 +acc +4 +nop -108 +acc +27 +jmp +2 +jmp -133 +acc +2 +jmp -103 +acc +40 +nop -512 +acc +48 +jmp -196 +acc +47 +acc +40 +nop -346 +acc -2 +jmp -530 +acc +17 +nop -31 +acc +1 +jmp -74 +acc -15 +acc +4 +nop -330 +acc +32 +jmp -115 +acc -3 +jmp +1 +acc +14 +acc +31 +jmp -352 +jmp -10 +acc +18 +jmp -322 +acc +41 +jmp +59 +acc -16 +nop -359 +acc +29 +acc +26 +jmp -418 +acc +10 +acc +47 +jmp -519 +acc -5 +nop +40 +acc +30 +jmp -195 +acc +31 +acc +3 +acc +8 +jmp -10 +acc -12 +acc +21 +acc -1 +jmp +30 +jmp -341 +acc -5 +jmp -405 +acc -13 +jmp -170 +acc +24 +acc -16 +acc +20 +acc +17 +jmp -145 +acc +42 +acc +33 +jmp -395 +nop -142 +acc +45 +acc +15 +jmp -399 +nop -223 +jmp -299 +jmp -453 +acc -6 +nop -498 +acc +42 +jmp -112 +acc +39 +acc +46 +acc +4 +acc +27 +jmp -234 +jmp +1 +acc +45 +acc +47 +jmp -307 +jmp -378 +jmp -431 +acc +13 +acc +29 +jmp -282 +acc +4 +acc -3 +acc +37 +acc +40 +jmp -32 +nop -148 +acc +38 +acc +40 +acc +18 +jmp -171 +nop -546 +jmp -490 +acc +36 +jmp -514 +acc +27 +acc -10 +nop -560 +acc +44 +jmp +1 diff --git a/day8/src/main.zig b/day8/src/main.zig new file mode 100644 index 0000000..13f71e4 --- /dev/null +++ b/day8/src/main.zig @@ -0,0 +1,222 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var program = try Program.init(gpa); + defer program.*.deinit(); + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + var s = try Statement.from_string(line); + try program.code.append(s); + } + std.log.debug("Loaded program with {} statements", .{program.code.items.len}); + _ = try program.run(); + + // Part 2 + // Exactly one nop should be a jmp or a jmp a noop + var i : usize = 0; + while (i < program.code.items.len) : (i += 1) { + if (program.code.items[i].op == .acc) { + continue; + } + // Mutate + program.code.items[i].op = switch(program.code.items[i].op) { + .acc => Operation.acc, + .jmp => Operation.nop, + .nop => Operation.jmp, + }; + // Test + var run_ok = program.run() catch false; + // Undo mutation + program.code.items[i].op = switch(program.code.items[i].op) { + .acc => Operation.acc, + .jmp => Operation.nop, + .nop => Operation.jmp, + }; + if (run_ok) { + std.log.info("By changing statement {}, the program exited okay", .{i}); + break; + } + } +} + +pub const Operation = enum { + nop, + acc, + jmp +}; + +pub const ParseError = error { + UnknownStatement, +}; + +pub const Statement = struct { + op: Operation, + arg: i32, + + /// Modifies acc and returns the offset for the next operation + pub fn execute(self: *Statement, acc: *i32) i32 { + var delta : i32 = switch (self.op) { + .nop => 1, + .jmp => self.arg, + .acc => 1, + }; + if (self.op == .acc) { + acc.* += self.arg; + } + return delta; + } + + pub fn from_string(line: []const u8) !Statement { + var arg : i32 = 0; + var op : Operation = undefined; + + var it = std.mem.tokenize(line, " "); + if (it.next()) |l| { + if (std.mem.eql(u8, l, "nop")) { + op = Operation.nop; + } + else if (std.mem.eql(u8, l, "acc")) { + op = Operation.acc; + } + else if (std.mem.eql(u8, l, "jmp")) { + op = Operation.jmp; + } + else { + std.log.err("Unknown statement: '{}'", .{l}); + return ParseError.UnknownStatement; + } + } + else { + // Error, and operator is required + unreachable; + } + if (it.next()) |l| { + arg = atoi(l); + } + else { + // Error, we need an arg + unreachable; + } + + while(it.next()) |l| { + // Error, there shouldn't be anything else on the line + unreachable; + } + + return Statement { + .op = op, + .arg = arg, + }; + } +}; + +pub const Program = struct { + code: std.ArrayList(Statement), + allocator: *std.mem.Allocator, + accumulator: i32 = 0, + + pub fn init(a: *std.mem.Allocator) !*Program { + const self = try a.create(Program); + errdefer a.destroy(self); + + self.* = Program { + .code = std.ArrayList(Statement).init(a), + .allocator = a, + }; + return self; + } + + pub fn deinit(self: *Program) void { + self.code.deinit(); + self.allocator.destroy(self); + } + + pub fn run(self: *Program) !bool { + self.accumulator = 0; + var next_statement_index : usize = 0; + // Statement counter + var map = std.hash_map.AutoHashMap(usize, u32).init(self.allocator); + defer map.deinit(); + + var ended_ok = false; + while (true) { + // Check if we have already exectured this index + var n_accumulator : i32 = self.accumulator; + if (map.contains(next_statement_index)) { + std.log.warn("Infinite loop detected. Statement {} would have run twice", + .{next_statement_index}); + std.log.warn("Acc value at break: {}", .{self.accumulator}); + break; + } + else { + try map.put(next_statement_index, 1); + } + + var delta = self.code.items[next_statement_index].execute(&n_accumulator); + //std.log.debug("Before {}, After {} [statement {} new offset {}] {}", + // .{self.accumulator, n_accumulator, next_statement_index, + // delta, self.code.items[next_statement_index]}); + if (delta < 0) { + next_statement_index -= @intCast(usize, try std.math.absInt(delta)); + } + else { + next_statement_index += @intCast(usize, delta); + } + std.debug.assert(next_statement_index >= 0); + if (next_statement_index >= self.code.items.len) { + std.log.warn("Reached end of code, or jumping past end ({}, {} statements).", + .{next_statement_index, self.code.items.len}); + std.log.warn("Acc value at end: {}", .{self.accumulator}); + ended_ok = true; // maybe... + break; + } + self.accumulator = n_accumulator; + } + return ended_ok; + } +}; + +fn atoi(a: []const u8) i32 { + var i : i32 = 0; + var mul : i32 = 1; + var start : usize = 0; + if (a[0] == '-' or a[0] == '+') { + start = 1; + if (a[0] == '-') { + mul *= -1; + } + } + for(a[start..]) |v, k| { + if (! std.ascii.isDigit(v)) { + std.log.warn("Byte {x} is not a digit", .{v}); + continue; + } + // 48 is '0' in ascii + std.debug.assert(v >= 48 and v < 58); + i += @as(i32, @as(i32, (v - 48)) * std.math.pow(i32, 10, @intCast(i32, a.len - k - 1 - start))); + } + //std.log.debug("{x} --> {}", .{a, i}); + return i * mul; +} + +test "atoi_regular" { + var i = atoi("1234"); + std.testing.expectEqual(i, 1234); +} + +test "atoi_pos" { + var i = atoi("+1234"); + std.testing.expectEqual(i, 1234); +} + +test "atoi_neg" { + var i = atoi("-1234"); + std.testing.expectEqual(i, -1234); +} diff --git a/day9/build.zig b/day9/build.zig new file mode 100644 index 0000000..a2d8eeb --- /dev/null +++ b/day9/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day9", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day9/input b/day9/input new file mode 100644 index 0000000..7b49b61 --- /dev/null +++ b/day9/input @@ -0,0 +1,1000 @@ +38 +18 +28 +41 +37 +17 +24 +45 +50 +35 +9 +30 +11 +8 +40 +43 +46 +36 +33 +19 +14 +32 +3 +7 +16 +42 +10 +12 +13 +25 +52 +15 +21 +18 +29 +17 +20 +22 +11 +51 +23 +24 +34 +30 +26 +33 +14 +50 +27 +28 +31 +36 +44 +32 +35 +25 +37 +38 +40 +59 +39 +41 +42 +43 +70 +55 +45 +57 +46 +47 +58 +80 +52 +68 +53 +56 +60 +95 +62 +63 +72 +75 +77 +79 +109 +174 +83 +139 +96 +91 +92 +98 +93 +99 +100 +254 +120 +428 +161 +162 +154 +149 +195 +153 +232 +334 +581 +156 +170 +175 +176 +189 +197 +187 +183 +190 +191 +199 +219 +220 +309 +269 +302 +372 +345 +751 +305 +323 +410 +331 +326 +332 +339 +346 +374 +359 +370 +769 +382 +373 +381 +419 +418 +439 +489 +592 +571 +607 +651 +669 +628 +665 +685 +709 +657 +658 +1068 +792 +705 +1151 +729 +1060 +754 +763 +791 +1010 +1342 +857 +928 +1146 +1163 +1178 +1297 +1515 +1648 +1285 +1438 +1315 +1362 +1363 +1387 +1434 +1459 +1468 +1483 +1492 +1517 +1926 +1620 +1719 +2091 +2003 +2020 +3237 +2309 +2341 +2475 +3011 +2927 +4242 +3640 +2821 +2893 +2846 +4540 +2917 +2902 +4305 +2985 +6130 +3009 +4728 +4094 +3339 +3722 +4023 +4312 +4329 +5294 +4650 +4816 +5296 +8142 +5667 +5714 +5723 +5902 +6707 +8625 +5819 +8708 +8067 +5994 +6324 +6348 +10231 +9006 +9608 +11115 +11625 +10653 +8641 +8979 +9466 +10112 +10483 +10963 +11437 +11381 +11533 +11542 +12672 +14635 +16106 +19949 +17046 +28483 +15814 +22914 +17647 +17620 +17985 +19604 +18107 +18445 +39446 +18753 +19091 +19578 +30985 +34091 +33726 +27251 +24053 +23075 +24214 +27307 +30449 +36137 +36430 +36092 +41861 +33434 +36860 +38669 +66586 +42679 +37198 +36552 +54997 +79211 +37844 +42166 +42653 +47128 +47289 +51360 +48267 +50382 +59505 +51521 +60741 +63883 +69526 +88558 +74396 +80523 +69986 +75221 +148063 +73750 +79851 +88719 +80010 +89294 +99788 +80497 +84819 +102158 +94417 +98649 +131211 +168409 +101903 +148702 +112262 +149996 +137633 +143276 +252154 +143736 +184607 +182248 +148971 +217026 +175653 +164829 +160507 +165316 +259246 +186722 +179236 +272769 +193066 +196320 +200552 +255998 +375556 +364416 +249895 +347564 +292707 +280909 +309478 +309052 +304243 +314287 +342037 +354889 +325336 +530804 +339743 +365958 +526800 +648795 +554792 +435234 +465835 +389386 +859035 +493259 +604784 +542602 +554138 +941502 +573616 +780122 +885693 +613295 +1376736 +963002 +669176 +1047397 +665079 +691294 +1567786 +1222411 +755344 +824620 +928493 +855221 +901069 +882645 +931988 +1334260 +1147386 +1096740 +1207681 +1127754 +1282471 +1186911 +1304589 +1278374 +1334255 +1446638 +1356373 +1360470 +1420423 +2010399 +1579964 +1610565 +1951961 +1656413 +2011531 +1737866 +1756290 +2660962 +1814633 +2214459 +2224494 +3076836 +3804458 +2628104 +2314665 +3184504 +2638844 +2915154 +2612629 +2690628 +4208068 +3531925 +2780893 +3000387 +5691015 +3190529 +3266978 +4537183 +3394279 +5315052 +3552499 +3570923 +4029092 +4039127 +4438953 +4539159 +5708944 +4927294 +5527783 +6661257 +5251473 +7833232 +5781280 +5303257 +5471521 +8718312 +8505581 +5971422 +7610050 +7229656 +6457507 +11162549 +6946778 +11385731 +7123422 +7581591 +8478080 +8068219 +8578286 +8978112 +9466453 +10779256 +10554730 +13849499 +11222895 +13084705 +10774778 +11084537 +11274679 +15841734 +12428929 +12918200 +21777625 +13404285 +14525726 +15601502 +14070200 +14528369 +19752759 +19532842 +15649810 +16546299 +20550990 +22870738 +18444565 +20021183 +21329508 +21639267 +21859315 +31251312 +26488990 +26926271 +26988400 +23703608 +25347129 +25833214 +26322485 +44200246 +53248756 +22406676 +47692529 +28598569 +32196109 +34094375 +38185566 +34990864 +36567482 +38465748 +43188823 +40083832 +41350691 +61082775 +43498582 +51005245 +64298962 +46110284 +47753805 +48239890 +48729161 +60824078 +52155699 +86425456 +56501051 +79888638 +67186973 +60794678 +62692944 +66290484 +69085239 +71558346 +73456612 +105881767 +78549580 +81434523 +123487622 +84849273 +98265983 +91738472 +93864089 +148239523 +94350174 +99909504 +96969051 +100884860 +123688024 +145014958 +117295729 +119193995 +142581582 +127085162 +128983428 +135375723 +139747096 +166054290 +159984103 +195235034 +163398853 +173172995 +175298612 +176587745 +178713362 +185602561 +186088646 +302401386 +191319225 +194259678 +196878555 +260868963 +243466442 +236489724 +244380891 +246279157 +248177423 +262460885 +256068590 +411576276 +321464369 +299731199 +323382956 +430469537 +494966233 +420054187 +351886357 +354011974 +355301107 +607954947 +371691207 +377407871 +668231610 +385578903 +757270110 +433368279 +479956166 +623114155 +480870615 +490660048 +494456580 +562192084 +651617556 +579451546 +621195568 +644847325 +675269313 +677394930 +723577564 +705898331 +707187464 +725703181 +862351255 +726992314 +749099078 +1108637592 +818947182 +971530663 +1430765028 +1371839639 +913324445 +970616214 +1146074136 +1322242255 +985116628 +1200647114 +1513968811 +1286639010 +1224298871 +2430879847 +1320116638 +1352664243 +1383293261 +1450569878 +1413085795 +1432890645 +1719715292 +2559207470 +1568046260 +2415881656 +1732271627 +1790477845 +2131190764 +2920362406 +1883940659 +1898441073 +1955732842 +2185763742 +3415996475 +2209415499 +3241047723 +2510937881 +3905479034 +4386612689 +2672780881 +2703409899 +4056074142 +6336358881 +3018616138 +2845976440 +3000936905 +3358524105 +3300317887 +3451986919 +3616212286 +6204500545 +4069704401 +3782381732 +3839673501 +4917057211 +3854173915 +4141496584 +7441814471 +7310752124 +5450463222 +5214347780 +5376190780 +6526954796 +5673717786 +5518757321 +6844906483 +7757708870 +5846913345 +5864592578 +6146294327 +11360642107 +9504818432 +8369044130 +7068199205 +7398594018 +12444389985 +7622055233 +7636555647 +7693847416 +7995670499 +17126873665 +9355844364 +13155312968 +10590538560 +14881009212 +11192475107 +10894948101 +11365670666 +22973787010 +11383349899 +11711505923 +11993207672 +12010886905 +12932791783 +18781943917 +14466793223 +14690254438 +15063869704 +14704754852 +15020649251 +25585202539 +19059518082 +19019905546 +25958817805 +18586209059 +20739194263 +24866818891 +21973888459 +21485486661 +22087423208 +25897229959 +22905835006 +22749020565 +23094855822 +23376557571 +23704713595 +29395009290 +24943678688 +29171548075 +29710903689 +35803063967 +34040554797 +39798712345 +29725404103 +37108072459 +37606114605 +48784922185 +39325403322 +43488214828 +40071695720 +60746742655 +43572909869 +44722909024 +44234507226 +92357832054 +45654855571 +52144029855 +46453734160 +46471413393 +47081271166 +48648392283 +54115226763 +62549793293 +58882451764 +91315778392 +73298313972 +63765958900 +66833476562 +76433475781 +90377764595 +89750144460 +79397099042 +97798885426 +83559910548 +94186922483 +89889362797 +87807417095 +114693823148 +112997678527 +92108589731 +92126268964 +98597764015 +227691501675 +100586640156 +95729663449 +152927557888 +116665020056 +121432245057 +159469091920 +130599435462 +140199434681 +143163057942 +156583621022 +243749698098 +183537080544 +167204516137 +247276509015 +171367327643 +173449273345 +177696779892 +179916006826 +235271647673 +184234858695 +187838253180 +222018885213 +187855932413 +395468158558 +307403950818 +320132074025 +535667593239 +238097265113 +371393012957 +261631679738 +297803951599 +270798870143 +545501215931 +365181943155 +323788137159 +351439374832 +573164938450 +338571843780 +351146053237 +448495650035 +353365280171 +365552712305 +364150865521 +375694185593 +449469932918 +739845051114 +559435631337 +511644069572 +569035630556 +499728944851 +568602821742 +642191883100 +508896135256 +532430549881 +600203523518 +662985894754 +594587007302 +662359980939 +907607474336 +1008905564255 +689717897017 +702722709301 +995557163271 +1564592793827 +815022645223 +717516145692 +729703577826 +887338255165 +825164118511 +1442567760415 +1008625080107 +1324290585128 +1214366778873 +1685275060288 +1032159494732 +1231588716496 +1041326685137 +1103483142558 +1948934159473 +1194790530820 +1256946988241 +1365082690240 +2880065591108 +2240213796603 +1392440606318 +2379615439050 +1420238854993 +1544726223049 +1447219723518 +2812302413758 +1542680264203 +1554867696337 +3705229709619 +1833789198618 +2298273673378 +2040784574839 +2550702866076 +2812679461311 +2811814684578 +2678808440014 +2272915401633 +2615029385813 +5426844070391 +2677185843234 +3376469462821 +2839660329836 +4259899184829 +2867458578511 +3853141369715 +5397867592764 +6320259095432 +3281008922136 +2989899987721 +5679760992269 +3097547960540 +3583464839042 +8593174497065 +3874573773457 +9554334765726 +5321793496975 +7636368647650 +5292215229047 +4887944787446 +5829560317557 +6864473761178 +4950101244867 +5454689715649 +8707852992527 +5516846173070 +6742032351968 +6573364826763 +5965006539051 +5857358566232 +6087447948261 +11208203882878 +8954906526772 +8614394133610 +6972121733997 +8047649205407 +6681012799582 +9166789002504 +8824675018324 +17781183136114 +9838046032313 +10180160016493 +10404790960516 +10242316473914 +10342634503095 +10466947417937 +12197858972652 +14812265093004 +10971535888719 +11374204739302 +11481852712121 +11822365105283 +11944806514493 +17214438207911 +12538371365814 +12768460747843 +13653134533579 +20709263891851 +21554364755795 +17085803760098 +14728662004989 +21724169186035 +18662721050637 +19004835034817 +20018206048806 +20080362506227 +24908822021482 +20809581921032 +20584950977009 +21314170391814 +21438483306656 +39472302971669 +32291434633153 +22345740628021 +42309120163044 +23304217817404 +23767171619776 +36219273242728 +38743083556864 +25306832113657 +26421595281422 +28381796538568 +35538243926021 +31814465765087 +33391383055626 +45387194619884 +39023041083623 +38680927099443 +39085197541044 +45649958445425 +78108238624667 +41394532898041 +42023434283665 +41899121368823 +42752653698470 +87044491343466 +70495392864530 +47071389437180 +59986444862504 +49725813098826 +48611049931061 +59812978337048 +51728427395079 +67352709691108 +75032645212483 +54803391819990 +67062723638011 +81433580797913 +88465922335221 +75414817339291 +77766124640487 +84735155986469 +80984318909867 +80479730439085 diff --git a/day9/src/main.zig b/day9/src/main.zig new file mode 100644 index 0000000..9ad1d8f --- /dev/null +++ b/day9/src/main.zig @@ -0,0 +1,163 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var gpa = &arena.allocator; + + var stream = std.ArrayList(u64).init(gpa); + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + //std.log.debug("{}", .{atoi(line)}); + try stream.append(atoi(line)); + } + + var first_not_matching = find_first_with_no_sum_property(stream.items[0..], 25); + std.log.info("First with no sum property: {} (at index {})", + .{stream.items[first_not_matching.?], first_not_matching.?}); + + // Part 2 + // 22406676 + var ranges = std.ArrayList(Range).init(gpa); + try find_contiguous_sets_matching(stream.items[0..], 22406676, &ranges); + std.log.debug("Found {} ranges summing to {}", .{ranges.items.len, 22406676}); + for (ranges.items) |r| { + std.log.info("Range: {}, len {}. Sum of edge indices: {}", + .{r, r.y - r.x + 1, stream.items[r.x] + stream.items[r.y-1]}); + var s : u64 = 0; + var min: u64 = std.math.maxInt(u64); + var max: u64 = 0; + for (stream.items[r.x..r.y]) |v| { + std.log.debug("{}", .{v}); + s += v; + min = std.math.min(v, min); + max = std.math.max(v, max); + } + std.log.debug("Sum of items in range: {}, min: {}, max: {}; sum min+max {}", + .{s, min, max, min+max}); + } +} + +const Range = struct { + x : usize = 0, + y : usize = 0, +}; + +pub fn find_contiguous_sets_matching(stream: []u64, match: u64, ranges: *std.ArrayList(Range)) !void { + var i : usize = 0; + // start create a window from 0 ... end of list breaking when + // the sum is greater than the match value + // then go on 1 ... end of list + while (i < stream.len) : (i += 1) { + var j : usize = i+1; + while (j < stream.len) : (j += 1) { + std.log.debug("Checking range {}..{}", .{i, j}); + var sum : u64 = 0; + for (stream[i..j]) |v| { + sum += v; + } + if (sum > match) { + break; + } + if (sum == match) { + try ranges.append(Range{.x = i, .y = j}); + break; + } + } + } +} + +/// returns the INDEX of the first non-matching +pub fn find_first_with_no_sum_property(stream: []u64, preamble: u64) ?u64 { + var i : u64 = preamble; + while (i < stream.len) : (i += 1) { + //std.log.debug("Searching for match for {} in indicess {} to {}: {}", + // .{stream[i], i-preamble, i, stream[i-preamble..i]}); + if (!has_sum_property(stream[i], stream[i-preamble..i])) { + return i; + } + } + return null; +} + +pub fn has_sum_property(value: u64, preceding_values: []u64) bool { + for (preceding_values) |v, k| { + for (preceding_values) |w, k2| { + if (k == k2) { + continue; // don't sum against our selves + } + //std.log.debug("[{}, {}] -> {} + {} => {} (searching for {})", + // .{k, k2, v, w, v+w, value}); + if ((v+w) == value) { + return true; + } + } + } + return false; +} + +test "first not having a sum of 5 preamble" { + const preamble : u64 = 5; + var stream = [_]u64 { + 35, + 20, + 15, + 25, + 47, + 40, + 62, + 55, + 65, + 95, + 102, + 117, + 150, + 182, + 127, + 219, + 299, + 277, + 309, + 576, + }; + var idx_not_matching = find_first_with_no_sum_property(stream[0..], preamble); + var i = stream[idx_not_matching.?]; + std.testing.expectEqual(i, 127); +} + + +fn atoi(a: []const u8) u64 { + var i : u64 = 0; + var mul : u64 = 1; + var start : usize = 0; + if (a[0] == '-' or a[0] == '+') { + start = 1; + if (a[0] == '-') { + //mul *= -1; + unreachable; + } + } + for(a[start..]) |v, k| { + if (! std.ascii.isDigit(v)) { + std.log.warn("Byte {x} is not a digit", .{v}); + continue; + } + // 48 is '0' in ascii + std.debug.assert(v >= 48 and v < 58); + i += @as(u64, @as(u64, (v - 48)) * std.math.pow(u64, 10, @intCast(u64, a.len - k - 1 - start))); + } + //std.log.debug("0x{x} --> {}", .{a, i}); + return i * mul; +} + +test "atoi_regular" { + var i = atoi("1234"); + std.testing.expectEqual(i, 1234); +} + +test "atoi_pos" { + var i = atoi("+1234"); + std.testing.expectEqual(i, 1234); +}