Merge remote-tracking branch '2020/master'
This commit is contained in:
commit
834924850b
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
// }
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
61,151,59,101,173,71,103,167,127,157,137,73,181,97,179,149,131,139,67,53
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
class: 1-3 or 5-7
|
||||
row: 6-11 or 33-44
|
||||
seat: 13-40 or 45-50
|
|
@ -0,0 +1,3 @@
|
|||
class: 0-1 or 4-19
|
||||
row: 0-5 or 8-19
|
||||
seat: 0-13 or 16-19
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
####...#
|
||||
......#.
|
||||
#..#.##.
|
||||
.#...#.#
|
||||
..###.#.
|
||||
##.###..
|
||||
.#...###
|
||||
.##....#
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,323 @@
|
|||
..#...##...###.........#..#..#.
|
||||
#.###........#..##.#......#...#
|
||||
#.#.###..#.#..#.#............#.
|
||||
.##............#......#...#.#..
|
||||
..#..#.....##..##..##..........
|
||||
...#...........###.#.##........
|
||||
....#.#...#..#..##............#
|
||||
....#....##...##..##........#..
|
||||
.#..#..#....#...#..##.....##...
|
||||
.#.###..#......####........##..
|
||||
..#...###....#......#.....##.##
|
||||
..#...#.......#......#..##....#
|
||||
#...##....#.#..#.......#....#..
|
||||
.#......#..#...........#....##.
|
||||
.##.#......#.#.#.....##........
|
||||
.....#.................#.#..#.#
|
||||
....#..#........##......#..#.#.
|
||||
..#...#..##.......#..##...#..#.
|
||||
..#.......#.............#.#....
|
||||
.#.................#.........#.
|
||||
..#..#.#.#.#............##.#..#
|
||||
.#.#.##.#.....#.....#..#......#
|
||||
..#.#..#.#..........##........#
|
||||
.........#...#.....#.#...#####.
|
||||
##..#.....##.##........#...##..
|
||||
.#.....#....##.#..#....##...##.
|
||||
.##.....#.#....#.#.....#......#
|
||||
.....#..#.##.....#.#....#.#..##
|
||||
#......##..##....##...###..#...
|
||||
.......#..#...........#......#.
|
||||
#...#......#........#..#.......
|
||||
##..#.....##.....#...#...#....#
|
||||
.###..##..#.#........#..#.#....
|
||||
#.#...#...#......##........#.#.
|
||||
......#....#.#........##...#..#
|
||||
.#.....#..#.#.....#......##....
|
||||
.....#.....#.#.#....###.....#..
|
||||
#.......##.#......#.#.#....###.
|
||||
.......#..#..#...#.#.##........
|
||||
.#......##..#.........###..#...
|
||||
....#..##.......##.###...###...
|
||||
.##............#..#.##.....#.##
|
||||
..##.#.......##....#.......##.#
|
||||
#..###............#.#...#...#.#
|
||||
...##.#.#.#..#.##........#.#...
|
||||
.#.....#...##.#..###..##.##...#
|
||||
..............#.#.#.........#..
|
||||
.....#...........#.#...#....#..
|
||||
.....#...##.##.#....#.###..#...
|
||||
#..###.........#......#.#.#....
|
||||
.....#..#...##...###.#....#....
|
||||
#..........#.#.#....#..#......#
|
||||
###...................#......#.
|
||||
........####......#.#..........
|
||||
.......#.....#...#.......#...#.
|
||||
.....#.....................#...
|
||||
...#.#...#...#...........#.....
|
||||
..#.........#...#....###..#....
|
||||
.....#.#..##......##........##.
|
||||
..#.............#............#.
|
||||
.#....##.......#..#............
|
||||
.#............#.#..#.##....#...
|
||||
.####...##.#....#.....#...#....
|
||||
##..#....#.#.#...........#..#.#
|
||||
...#..#...........#...#..#....#
|
||||
.....##.....#..#...#.........#.
|
||||
...##........#....##........#..
|
||||
.##.#...#...#..#.....#....##.#.
|
||||
#.#...#.#.#.#.#..#....#....#...
|
||||
#..#.#...#..#........#....#.#..
|
||||
....#.#.....#......##...#....#.
|
||||
.###.##...#....##.#...###..#..#
|
||||
###..#...##..#......#.........#
|
||||
..#.#......##.......#.....#...#
|
||||
..#...#........#.........#.#...
|
||||
#....#..#.........###.#......##
|
||||
...#..#....#...#.......##.#.#..
|
||||
....#.......#....###...##.#....
|
||||
..#.....#.#.....###..#####....#
|
||||
##......#....#.....##..#..#...#
|
||||
#...........#..#..#....#....#..
|
||||
.#...#.##.#.#.#....#......#..#.
|
||||
.......#.#....#....#...#.#..#..
|
||||
..#.#..#.##..##...##..#..#.....
|
||||
...##.##.................#.#...
|
||||
.....#...#......##.#....#.....#
|
||||
......#..##.#..#.#.........#...
|
||||
.............##.#......#.......
|
||||
..#.#.....#...#.#.....#..#.....
|
||||
.........#..#.#......#..#......
|
||||
#..#.#.##..........#.##......##
|
||||
......#.......#.....#..#.#...#.
|
||||
.#....#....#.#.....#.......#...
|
||||
#..#..##..................#....
|
||||
............#...........##.#...
|
||||
####...#..##.#....#.##..#......
|
||||
#...#...#.....#.#...#.#........
|
||||
.......##.........#.....#.....#
|
||||
.....#...........##......#.####
|
||||
.##....#.#.##......###.#.##....
|
||||
........#.####.......#.#...#...
|
||||
.#.#...##.#.#.#.........##.....
|
||||
....#............###.##....#...
|
||||
...##........##.#...#....#..###
|
||||
..#.#.........#....##.#........
|
||||
..#..##..#...##..#.##...#.....#
|
||||
.#......#..#..#.........#......
|
||||
..#........##.#......#.....#...
|
||||
.##.......#....#.#......#......
|
||||
#........#....#.####...#.#.....
|
||||
##......#.............#....###.
|
||||
..#....####.#.#.#.#...##......#
|
||||
#.#.#.....#...#.......#...##...
|
||||
........#...#....#..#......#.#.
|
||||
#..#...#.#.##.....#.#....#....#
|
||||
#...#....#......#.........##.##
|
||||
..##.#..##............#........
|
||||
#.........####.........#.......
|
||||
#.##.........#..##....#.#.#.#..
|
||||
.###......##..#.#.....#.#...##.
|
||||
...#.........#.#...##.##....#..
|
||||
#..#......#....##..#.#...#...##
|
||||
...#.......#.#.#.....#..##...#.
|
||||
....................###........
|
||||
#...........###......#.#...##.#
|
||||
.................#.#...###....#
|
||||
...#..###..#.##...#..#....##...
|
||||
###..#..#.#...#.....#.#.......#
|
||||
.........#..#.#.....#.........#
|
||||
.##..#.........#.#.....##......
|
||||
.....#..........#.#.##....#....
|
||||
........#.##.....#...##...#....
|
||||
#.#.#...#......##....#.###.....
|
||||
.#.##.....##.....#....#.##.#.##
|
||||
.#...#.....##.#.##....#.....#.#
|
||||
...#.....#........#............
|
||||
##...####..#....#..##...#......
|
||||
#.......#...#.#...#........#..#
|
||||
......#.....#....#..#..#.#.....
|
||||
..............##.....#.##....##
|
||||
.#..##.........###..#..........
|
||||
......#......#............#..#.
|
||||
#.....###...###..........#.....
|
||||
...###...........#....##..#....
|
||||
.....................#...#.##..
|
||||
###....#.#....#...#....#.#..##.
|
||||
..#.............#.#....#..#.#..
|
||||
.......#..###....#...#...#...#.
|
||||
.##..#....##..............##...
|
||||
...#...#..#..#.##.#....##...#..
|
||||
#..#....##......#....###..####.
|
||||
.##...#.#....#..#..#....#....#.
|
||||
.#.##..#..#.........#.#......##
|
||||
#..#.................#.....#...
|
||||
..#............#........#...#..
|
||||
##.##.......#.#....#..#....##.#
|
||||
..##...#.#.....#......#........
|
||||
......#.##.........##...#......
|
||||
......##.#......#.##....##.#..#
|
||||
.#.#......####.#.#.#.#..#......
|
||||
..#.#....#...###....#.#...###..
|
||||
.#.#...#....##..###.#..#.......
|
||||
..#.....##..#............#..#.#
|
||||
.#...#....#.....#....#..#.#.#..
|
||||
..#....#..#......##...##......#
|
||||
....#.......#.##.#.........#..#
|
||||
#............#...##.....#..##..
|
||||
......#..#..........#.#..#.....
|
||||
...........#.#..#...##.#...#..#
|
||||
.........###..#......##.###.#..
|
||||
.....#....#......#...#....##...
|
||||
..#.......#..#.#.#......#......
|
||||
.#....#.....#.#.#.##...#....##.
|
||||
....#.##.##.......#..#.....#...
|
||||
.#.....#......#.......#..#.....
|
||||
....###.....##.....##..#.#...#.
|
||||
#.......#.#....#.#.#....#......
|
||||
#...#..#.#......#...##.#.......
|
||||
....##.##....#..#.......#..#.#.
|
||||
.#.##.#.#..#.....#.#.......##..
|
||||
..#..#..#..#.###...............
|
||||
#.#......##....##.#.#.....#.#..
|
||||
..##...#.........#.#..#.##..#..
|
||||
.........####...#.....##.#.....
|
||||
..#...................#.###....
|
||||
..#.....#..#....#..#...........
|
||||
.....###.#.........#.#.........
|
||||
#..#..#........#..#......#..#..
|
||||
###..##...#.......#........#.#.
|
||||
.#.#.#.###.#............##.....
|
||||
#..............#......#....#.##
|
||||
.#...#..###...###.#..#.#.......
|
||||
.###....##.#.......#.#.....###.
|
||||
.##.....#.#....................
|
||||
#..#.....#.....#...#.....#..##.
|
||||
#.#....##..#......##..#...##..#
|
||||
...........#....#..#.##.##....#
|
||||
......#.......##....#.#....#.#.
|
||||
###..#.#..........#.......#.#..
|
||||
..#.#..##....##............##..
|
||||
..#.....#..#....###............
|
||||
.#...#...##...#..#..#..#.#....#
|
||||
...#....#........#.............
|
||||
#.#......#.#.....##..........#.
|
||||
....#..#...............#...##..
|
||||
........#..#....#..#..#..##....
|
||||
....#......#.#.#...#.......#.##
|
||||
.#.....#.#.#........###....#...
|
||||
.#..#.......#...........#...#..
|
||||
#.#.#####..#......#...#.#.###..
|
||||
...##...#.#.....#..#...#...#...
|
||||
..#....#.....#..#....#.#.....#.
|
||||
....#.......#.....#........###.
|
||||
..##..........#...###.......#..
|
||||
#.#.##..#........##...#.#......
|
||||
....##...#......#..........#.#.
|
||||
#.......#..#.##.............#..
|
||||
......#..........#...#....#...#
|
||||
#.#.....#.##.#.#.............##
|
||||
#...#.........##.##......#.##..
|
||||
.........##.....#....#...##..#.
|
||||
#.#...##.#...#.....##...#..#..#
|
||||
......##.#.....#.#.....#.##....
|
||||
....#.............#...#.......#
|
||||
.#......##...#.#...#.##........
|
||||
...#..#..#...........#..#..#.#.
|
||||
.#...#...........#.#.##....#...
|
||||
..#...#...#.#..#....#..#..#....
|
||||
..###..##..#..#.........#.#..#.
|
||||
....#.##.#...#.......#...#.....
|
||||
.#.#.................#.......#.
|
||||
.#..#.....#.##...#.#.....#...#.
|
||||
.#.......#...#....#.......#....
|
||||
###....##....#..#...#.#..##....
|
||||
.........#.#.#.#...###.......##
|
||||
....##.......#......#......##..
|
||||
......##.###.#..#...#.#.#.#....
|
||||
.#.###.#.#......#.#.......##...
|
||||
.#.....##..#.#.....#...#.##....
|
||||
.#..##.#.....#........###...#.#
|
||||
.......#.#...........#........#
|
||||
..........#...##..##.......#.#.
|
||||
...#..#..#...#....#.#......#.#.
|
||||
....#...#..#....#....#.#.##....
|
||||
...#.#...##...#...##..#........
|
||||
..#........#...##.#...##.#.#.#.
|
||||
...##.#..#.......###.#.#.#.....
|
||||
..##......#.#.#.........###.#..
|
||||
.......#.#...##...#.#.......#.#
|
||||
.#....##..#..#....#..#...#.....
|
||||
.#....#.#.......#..#..##.#....#
|
||||
#.#..##..#.#............#....#.
|
||||
##..#....#.##.#....#...#..##...
|
||||
.###.#.#..#...##........###.##.
|
||||
...........#..#...#..#.#..###..
|
||||
.#.#.#...#....#...##.##........
|
||||
.....###.........#......#####..
|
||||
#.#.#.....#....#..#...#.#.#.#..
|
||||
..##.....#..#..#.#.#...#....#.#
|
||||
......#.##..##..#.#.#.......#..
|
||||
...#.#..###.........#........#.
|
||||
......#.##..####...#...#..#...#
|
||||
#.......#.........#....#....###
|
||||
#......#...#........#.##....###
|
||||
.#.#..............#...#...###.#
|
||||
.#....####...#..##.###.....#...
|
||||
.......#......#..#...#..##.#...
|
||||
...........#.......#...........
|
||||
..............#...#.#.#.#...##.
|
||||
.###.....##.#.....#..........#.
|
||||
##.##......#....##..#.....###.#
|
||||
#.......#...##...#....##...#...
|
||||
##.#.##...#....#....#....#.....
|
||||
.....####...........#.#......#.
|
||||
......#...#....#..#......#.....
|
||||
...#...##..........#.......##.#
|
||||
.#....#..........#.####........
|
||||
...##...#..#...##........##..#.
|
||||
.........##....#...##..#.##.#..
|
||||
##.#.....#.......#.....#.......
|
||||
#..#....#.##.#........#........
|
||||
#.#...#...##........#.#.....###
|
||||
....#...................#.#.#..
|
||||
.......#..#.#...#....#.##.#....
|
||||
....##...###.#.#.##...#...#....
|
||||
.#....#....#...##.#......#...#.
|
||||
............##..#.#.#........#.
|
||||
...#....#.....#......#........#
|
||||
...#.#.....#.##.....#....#...#.
|
||||
.....#..##.......#.##.......#.#
|
||||
........##................#....
|
||||
....#..###...##.#..#...#......#
|
||||
.#.#.......#.......#....##.#..#
|
||||
..#........#............#......
|
||||
..##.......#..#..#....#....#..#
|
||||
#...###.......#.##...#.........
|
||||
.....#...#...#..##..#....#..#..
|
||||
.##.#..#...##.........###.#....
|
||||
..#.#..#...#...####.#...#.#.#.#
|
||||
#....#..###.....#......#.##..##
|
||||
##......#...##...###......#.##.
|
||||
...........#.....##...#...#...#
|
||||
..#..#.#.....#..#.....###...#..
|
||||
.............#..........###...#
|
||||
....##............#....###.##.#
|
||||
..##.#..##.....#.#.........#.#.
|
||||
....#.#...........####.........
|
||||
.##.###.##.#.#......#.##.#.#...
|
||||
.....##.........#..#.......#...
|
||||
...........#.........#....###..
|
||||
...#.#..#..........#.....#..#..
|
||||
.#..###.......##........#.#....
|
||||
.#...###.....#..#.#..#...#.##..
|
||||
##...###.#.#....#......#...#..#
|
||||
....#.......#..#..##..#.#......
|
||||
#.#......#.##..#......#..#....#
|
||||
....#..#..#.....#.#......#..#..
|
||||
..#...###......##.............#
|
||||
..#....####...##.#...##.#......
|
||||
.....#.......###...............
|
||||
.......#...#.#.......#.#.##.###
|
||||
.#.#...#.....#...##.........#..
|
||||
..#..........#..#.........##...
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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,
|
||||
};
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue