diff options
| author | Louis Burda <quent.burda@gmail.com> | 2023-04-08 12:40:30 -0400 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2023-04-09 10:21:36 -0400 |
| commit | 9282e95e8844afe856ba76ceb6d2c3010df8bb1a (patch) | |
| tree | e35affc89b20324371381e079f7cb5f8a06aa81b /src/17 | |
| parent | 2b5d4232879dc74491dabf54a0ddc958d66ebcec (diff) | |
| download | aoc2020-zig-master.tar.gz aoc2020-zig-master.zip | |
Diffstat (limited to 'src/17')
| -rw-r--r-- | src/17/input | 8 | ||||
| -rw-r--r-- | src/17/input-test | 3 | ||||
| -rw-r--r-- | src/17/main.zig | 195 | ||||
| -rw-r--r-- | src/17/part1 | 169 | ||||
| -rw-r--r-- | src/17/part2 | 265 |
5 files changed, 640 insertions, 0 deletions
diff --git a/src/17/input b/src/17/input new file mode 100644 index 0000000..1ea63ff --- /dev/null +++ b/src/17/input @@ -0,0 +1,8 @@ +.###..#. +##.##... +....#.#. +#..#.### +...#...# +##.#...# +#..##.## +#....... diff --git a/src/17/input-test b/src/17/input-test new file mode 100644 index 0000000..eedd3d2 --- /dev/null +++ b/src/17/input-test @@ -0,0 +1,3 @@ +.#. +..# +### diff --git a/src/17/main.zig b/src/17/main.zig new file mode 100644 index 0000000..a6e1622 --- /dev/null +++ b/src/17/main.zig @@ -0,0 +1,195 @@ +const std = @import("std"); +const aoc = @import("aoc"); + +fn PosVec(comptime N: u32) type { + return struct { data: [N]i64 }; +} + +const Active = bool; + +fn forNeighbors(comptime dims: u32, map: *std.AutoHashMap(PosVec(dims), Active), p: PosVec(dims), data: anytype, func: fn (map: *std.AutoHashMap(PosVec(dims), Active), p: PosVec(dims), d: @TypeOf(data)) anyerror!void) !void { + var i: u32 = 0; + while (i < comptime std.math.pow(u32, 3, dims)) : (i += 1) { + var np: PosVec(dims) = undefined; + var d: u32 = 0; + var skip = true; + while (d < dims) : (d += 1) { + const offset = (i / std.math.pow(u32, 3, d)) % 3; + np.data[d] = p.data[d] + @intCast(i64, offset) - 1; + if (skip and offset != 1) skip = false; + } + if (skip) continue; + try func(map, np, data); + } +} + +fn posStr(comptime dims: u32, p: PosVec(dims)) void { + var d: u32 = 0; + while (d < dims) : (d += 1) { + aoc.debugfmt("{} ", .{p.data[d]}); + } +} + +fn countActive(comptime dims: u32) fn (map: *std.AutoHashMap(PosVec(dims), Active), p: PosVec(dims), d: *u32) anyerror!void { + const impl = struct { + fn func(map: *std.AutoHashMap(PosVec(dims), Active), p: PosVec(dims), d: *u32) anyerror!void { + d.* += @boolToInt(map.get(p) != null); + } + }; + return impl.func; +} + +fn addNew(comptime dims: u32) fn (oldmap: *std.AutoHashMap(PosVec(dims), Active), p: PosVec(dims), newmap: *std.AutoHashMap(PosVec(dims), Active)) anyerror!void { + const impl = struct { + fn func(oldmap: *std.AutoHashMap(PosVec(dims), Active), p: PosVec(dims), newmap: *std.AutoHashMap(PosVec(dims), Active)) anyerror!void { + if (newmap.get(p) != null) return; + + var v = oldmap.get(p); + var state = (v != null); + + var count: u32 = 0; + try forNeighbors(dims, oldmap, p, &count, countActive(dims)); + if (state and count >= 2 and count <= 3 or !state and count == 3) { + try newmap.put(p, true); + } + } + }; + return impl.func; +} + +fn simulateRound(comptime dims: u32, map: *std.AutoHashMap(PosVec(dims), Active), allocator: std.mem.Allocator) !void { + var newmap = std.AutoHashMap(PosVec(dims), Active).init(allocator); + errdefer newmap.deinit(); + + var mapit = map.iterator(); + while (mapit.next()) |kv| { + try forNeighbors(dims, map, kv.key_ptr.*, &newmap, addNew(dims)); + try addNew(dims)(map, kv.key_ptr.*, &newmap); + } + + std.mem.swap(std.AutoHashMap(PosVec(dims), Active), map, &newmap); + newmap.deinit(); +} + +fn sliceProduct(data: []i64) i64 { + var product: i64 = 1; + for (data) |v| { + product *= v; + } + return product; +} + +fn printMap(comptime dims: u32, map: *std.AutoHashMap(PosVec(dims), Active)) void { + var min: ?PosVec(dims) = null; + var max: ?PosVec(dims) = null; + + var mapit = map.iterator(); + while (mapit.next()) |kv| { + if (min == null) min = kv.key_ptr.*; + if (max == null) max = kv.key_ptr.*; + + var d: u32 = 0; + while (d < dims) : (d += 1) { + if (min.?.data[d] > kv.key_ptr.data[d]) min.?.data[d] = kv.key_ptr.data[d]; + if (max.?.data[d] < kv.key_ptr.data[d]) max.?.data[d] = kv.key_ptr.data[d]; + } + } + + if (min == null or max == null) return; + + var space: PosVec(dims) = undefined; + { + var d: u32 = 0; + while (d < dims) : (d += 1) { + space.data[d] = max.?.data[d] - min.?.data[d]; + } + } + + var i: usize = 0; + while (i < sliceProduct(space.data[0..])) : (i += @intCast(usize, space.data[0] * space.data[1])) { + var np: PosVec(dims) = undefined; + var d: u32 = 0; + while (d < dims) : (d += 1) { + np.data[d] = min.?.data[d] + @mod(@divFloor(@intCast(i64, i), sliceProduct(space.data[0..d])), space.data[d]); + } + + d = 2; + aoc.debugfmt("Slice at: ", .{}); + while (d < dims) : (d += 1) { + if (d > 2) aoc.debugfmt(",", .{}); + aoc.debugfmt("{}.Dim = {} ", .{ d + 1, np.data[d] }); + } + aoc.debugfmt("\n", .{}); + + var y = min.?.data[1]; + while (y <= max.?.data[1]) : (y += 1) { + var x = min.?.data[0]; + while (x <= max.?.data[0]) : (x += 1) { + var v = np; + v.data[0] = x; + v.data[1] = y; + var c: u8 = '.'; + if (map.get(v) != null) c = '#'; + aoc.debugfmt("{c}", .{c}); + } + aoc.debugfmt("\n", .{}); + } + aoc.debugfmt("\n", .{}); + } +} + +fn part1(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 { + _ = args; + + var map = std.AutoHashMap(PosVec(3), Active).init(allocator); + defer map.deinit(); + + var lineit = std.mem.tokenize(u8, input, "\n"); + var y: i64 = 0; + while (lineit.next()) |line| : (y += 1) { + for (line) |c, x| { + if (c != '#') continue; + try map.put(PosVec(3){ .data = [_]i64{ @intCast(i64, x), y, 0 } }, true); + } + } + + var i: usize = 0; + while (i < 6) : (i += 1) { + try simulateRound(3, &map, allocator); + if (aoc.debug) { + aoc.debugfmt("AFTER ROUND {}:\n", .{i + 1}); + printMap(3, &map); + } + } + + return try std.fmt.allocPrint(allocator, "{}", .{map.count()}); +} + +fn part2(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 { + _ = args; + + var map = std.AutoHashMap(PosVec(4), Active).init(allocator); + defer map.deinit(); + + var lineit = std.mem.tokenize(u8, input, "\n"); + var y: i64 = 0; + while (lineit.next()) |line| : (y += 1) { + for (line) |c, x| { + if (c != '#') continue; + try map.put(PosVec(4){ .data = [_]i64{ @intCast(i64, x), y, 0, 0 } }, true); + } + } + + var i: usize = 0; + while (i < 6) : (i += 1) { + try simulateRound(4, &map, allocator); + if (aoc.debug) { + aoc.debugfmt("AFTER ROUND {}:\n", .{i + 1}); + printMap(4, &map); + } + } + + return try std.fmt.allocPrint(allocator, "{}", .{map.count()}); +} + +pub const main = aoc.main(part1, part2, .{ "304", "1868" }); diff --git a/src/17/part1 b/src/17/part1 new file mode 100644 index 0000000..0e7db4a --- /dev/null +++ b/src/17/part1 @@ -0,0 +1,169 @@ +--- Day 17: Conway Cubes --- + +As your flight slowly drifts through the sky, the Elves at the Mythical Information Bureau at the +North Pole contact you. They'd like some help debugging a malfunctioning experimental energy source +aboard one of their super-secret imaging satellites. + +The experimental energy source is based on cutting-edge technology: a set of Conway Cubes contained +in a pocket dimension! When you hear it's having problems, you can't help but agree to take a look. + +The pocket dimension contains an infinite 3-dimensional grid. At every integer 3-dimensional +coordinate (x,y,z), there exists a single cube which is either [1m[37mactive[0m or +[1m[37minactive[0m. + +In the initial state of the pocket dimension, almost all cubes start [1m[37minactive[0m. The only +exception to this is a small flat region of cubes (your puzzle input); the cubes in this region +start in the specified [1m[37mactive[0m (#) or [1m[37minactive[0m (.) state. + +The energy source then proceeds to boot up by executing six [1m[37mcycles[0m. + +Each cube only ever considers its [1m[37mneighbors[0m: any of the 26 other cubes where any of +their coordinates differ by at most 1. For example, given the cube at x=1,y=2,z=3, its neighbors +include the cube at x=2,y=2,z=2, the cube at x=0,y=2,z=3, and so on. + +During a cycle, [1m[37mall[0m cubes [1m[37msimultaneously[0m change their state according to +the following rules: + + + - If a cube is [1m[37mactive[0m and [1m[37mexactly 2 or 3[0m of its neighbors are also +active, the cube remains [1m[37mactive[0m. Otherwise, the cube becomes [1m[37minactive[0m. + - If a cube is [1m[37minactive[0m but [1m[37mexactly 3[0m of its neighbors are active, the +cube becomes [1m[37mactive[0m. Otherwise, the cube remains [1m[37minactive[0m. + + +The engineers responsible for this experimental energy source would like you to simulate the pocket +dimension and determine what the configuration of cubes should be at the end of the six-cycle boot +process. + +For example, consider the following initial state: + +.#. +..# +### + +Even though the pocket dimension is 3-dimensional, this initial state represents a small +2-dimensional slice of it. (In particular, this initial state defines a 3x3x1 region of the +3-dimensional space.) + +Simulating a few cycles from this initial state produces the following configurations, where the +result of each cycle is shown layer-by-layer at each given z coordinate (and the frame of view +follows the active cells in each cycle): + +Before any cycles: + +z=0 +.#. +..# +### + + +After 1 cycle: + +z=-1 +#.. +..# +.#. + +z=0 +#.# +.## +.#. + +z=1 +#.. +..# +.#. + + +After 2 cycles: + +z=-2 +..... +..... +..#.. +..... +..... + +z=-1 +..#.. +.#..# +....# +.#... +..... + +z=0 +##... +##... +#.... +....# +.###. + +z=1 +..#.. +.#..# +....# +.#... +..... + +z=2 +..... +..... +..#.. +..... +..... + + +After 3 cycles: + +z=-2 +....... +....... +..##... +..###.. +....... +....... +....... + +z=-1 +..#.... +...#... +#...... +.....## +.#...#. +..#.#.. +...#... + +z=0 +...#... +....... +#...... +....... +.....## +.##.#.. +...#... + +z=1 +..#.... +...#... +#...... +.....## +.#...#. +..#.#.. +...#... + +z=2 +....... +....... +..##... +..###.. +....... +....... +....... + +After the full six-cycle boot process completes, [1m[37m112[0m cubes are left in the +[1m[37mactive[0m state. + +Starting with your given initial configuration, simulate six cycles. [1m[37mHow many cubes are +left in the active state after the sixth cycle?[0m + + diff --git a/src/17/part2 b/src/17/part2 new file mode 100644 index 0000000..a824996 --- /dev/null +++ b/src/17/part2 @@ -0,0 +1,265 @@ +--- Part Two --- + +For some reason, your simulated results don't match what the experimental energy source engineers +expected. Apparently, the pocket dimension actually has [1m[37mfour spatial dimensions[0m, not +three. + +The pocket dimension contains an infinite 4-dimensional grid. At every integer 4-dimensional +coordinate (x,y,z,w), there exists a single cube (really, a [1m[37mhypercube[0m) which is still +either [1m[37mactive[0m or [1m[37minactive[0m. + +Each cube only ever considers its [1m[37mneighbors[0m: any of the 80 other cubes where any of +their coordinates differ by at most 1. For example, given the cube at x=1,y=2,z=3,w=4, its neighbors +include the cube at x=2,y=2,z=3,w=3, the cube at x=0,y=2,z=3,w=4, and so on. + +The initial state of the pocket dimension still consists of a small flat region of cubes. +Furthermore, the same rules for cycle updating still apply: during each cycle, consider the +[1m[37mnumber of active neighbors[0m of each cube. + +For example, consider the same initial state as in the example above. Even though the pocket +dimension is 4-dimensional, this initial state represents a small 2-dimensional slice of it. (In +particular, this initial state defines a 3x3x1x1 region of the 4-dimensional space.) + +Simulating a few cycles from this initial state produces the following configurations, where the +result of each cycle is shown layer-by-layer at each given z and w coordinate: + +Before any cycles: + +z=0, w=0 +.#. +..# +### + + +After 1 cycle: + +z=-1, w=-1 +#.. +..# +.#. + +z=0, w=-1 +#.. +..# +.#. + +z=1, w=-1 +#.. +..# +.#. + +z=-1, w=0 +#.. +..# +.#. + +z=0, w=0 +#.# +.## +.#. + +z=1, w=0 +#.. +..# +.#. + +z=-1, w=1 +#.. +..# +.#. + +z=0, w=1 +#.. +..# +.#. + +z=1, w=1 +#.. +..# +.#. + + +After 2 cycles: + +z=-2, w=-2 +..... +..... +..#.. +..... +..... + +z=-1, w=-2 +..... +..... +..... +..... +..... + +z=0, w=-2 +###.. +##.## +#...# +.#..# +.###. + +z=1, w=-2 +..... +..... +..... +..... +..... + +z=2, w=-2 +..... +..... +..#.. +..... +..... + +z=-2, w=-1 +..... +..... +..... +..... +..... + +z=-1, w=-1 +..... +..... +..... +..... +..... + +z=0, w=-1 +..... +..... +..... +..... +..... + +z=1, w=-1 +..... +..... +..... +..... +..... + +z=2, w=-1 +..... +..... +..... +..... +..... + +z=-2, w=0 +###.. +##.## +#...# +.#..# +.###. + +z=-1, w=0 +..... +..... +..... +..... +..... + +z=0, w=0 +..... +..... +..... +..... +..... + +z=1, w=0 +..... +..... +..... +..... +..... + +z=2, w=0 +###.. +##.## +#...# +.#..# +.###. + +z=-2, w=1 +..... +..... +..... +..... +..... + +z=-1, w=1 +..... +..... +..... +..... +..... + +z=0, w=1 +..... +..... +..... +..... +..... + +z=1, w=1 +..... +..... +..... +..... +..... + +z=2, w=1 +..... +..... +..... +..... +..... + +z=-2, w=2 +..... +..... +..#.. +..... +..... + +z=-1, w=2 +..... +..... +..... +..... +..... + +z=0, w=2 +###.. +##.## +#...# +.#..# +.###. + +z=1, w=2 +..... +..... +..... +..... +..... + +z=2, w=2 +..... +..... +..#.. +..... +..... + +After the full six-cycle boot process completes, [1m[37m848[0m cubes are left in the +[1m[37mactive[0m state. + +Starting with your given initial configuration, simulate six cycles in a 4-dimensional space. +[1m[37mHow many cubes are left in the active state after the sixth cycle?[0m + + |
