day 18, part 2 (unfinished: refactored part 1 to produce same result but with part 2 logic)

main
Inga 🏳‍🌈 4 months ago
parent dba2aeadc8
commit 4d772cb786
  1. 70
      day18-hard/build.zig
  2. 722
      day18-hard/easy.in
  3. 14
      day18-hard/sample.in
  4. 380
      day18-hard/src/main.zig

@ -0,0 +1,70 @@
const std = @import("std");
// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
// runner.
pub fn build(b: *std.Build) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "day18-hard",
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// This declares intent for the executable to be installed into the
// standard location when the user invokes the "install" step (the default
// step when running `zig build`).
b.installArtifact(exe);
// This *creates* a Run step in the build graph, to be executed when another
// step is evaluated that depends on it. The next line below will establish
// such a dependency.
const run_cmd = b.addRunArtifact(exe);
// By making the run step depend on the install step, it will be run from the
// installation directory rather than directly from within the cache directory.
// This is not necessary, however, if the application depends on other installed
// files, this ensures they will be present and in the expected location.
run_cmd.step.dependOn(b.getInstallStep());
// This allows the user to pass arguments to the application in the build
// command itself, like this: `zig build run -- arg1 arg2 etc`
if (b.args) |args| {
run_cmd.addArgs(args);
}
// This creates a build step. It will be visible in the `zig build --help` menu,
// and can be selected like this: `zig build run`
// This will evaluate the `run` step rather than the default, which is "install".
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const unit_tests = b.addTest(.{
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
const run_unit_tests = b.addRunArtifact(unit_tests);
// Similar to creating the run step earlier, this exposes a `test` step to
// the `zig build --help` menu, providing a way for the user to request
// running the unit tests.
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_unit_tests.step);
}

@ -0,0 +1,722 @@
R 5 (#2f3630)
U 9 (#54a1a3)
R 5 (#05bce0)
U 3 (#008843)
R 5 (#6690d0)
U 4 (#008841)
R 5 (#651d10)
U 7 (#830023)
R 8 (#4750a2)
U 7 (#6a1001)
R 3 (#114a72)
D 5 (#21dbf3)
R 3 (#4523f2)
U 4 (#3a1e43)
R 4 (#2eef10)
D 4 (#352183)
R 5 (#2eef12)
D 6 (#1fd943)
L 7 (#5c0bd2)
D 5 (#32d3b1)
L 5 (#47d3d0)
D 3 (#3032e1)
R 2 (#47d3d2)
D 4 (#4dee61)
R 4 (#044a92)
D 4 (#494b23)
R 2 (#132772)
D 3 (#2186a3)
R 7 (#49e542)
U 3 (#864783)
R 3 (#3afdd2)
U 5 (#2ab8d1)
R 6 (#2d5072)
D 5 (#362ab1)
R 4 (#2d5070)
U 5 (#46eaa1)
R 9 (#183c12)
U 3 (#494b21)
R 3 (#584d32)
U 4 (#6a1003)
R 3 (#618682)
U 4 (#5a1853)
R 6 (#30cf00)
U 6 (#6b3a23)
R 5 (#5e1260)
U 2 (#20b7d3)
R 3 (#1d2ec0)
U 10 (#89f613)
R 5 (#16c5b0)
U 3 (#26b1d3)
R 4 (#475e70)
U 3 (#007223)
R 5 (#3cf870)
U 3 (#851f83)
R 8 (#326e40)
U 5 (#043ad3)
R 4 (#2eb0a0)
U 5 (#26e791)
R 3 (#0b6950)
U 7 (#323af1)
L 3 (#0b6952)
U 3 (#4ffc41)
L 4 (#721f70)
U 8 (#0137b1)
R 4 (#5c9d22)
U 3 (#55ff21)
R 5 (#5c9d20)
U 3 (#3b2d71)
R 5 (#721f72)
U 7 (#1fa921)
R 8 (#3012f0)
D 5 (#4c6a91)
R 8 (#61af70)
D 4 (#4c6a93)
R 6 (#2e21b0)
D 2 (#7df243)
R 2 (#108f72)
D 9 (#239da3)
R 5 (#1f8fb0)
D 8 (#8e8b71)
R 5 (#5a6f50)
D 2 (#8e8b73)
R 3 (#159190)
D 5 (#5f70a3)
L 5 (#012372)
D 3 (#04bf23)
L 5 (#72bbe2)
D 6 (#04bf21)
L 3 (#1bb142)
D 3 (#0f6693)
L 4 (#108f70)
D 6 (#0ecae3)
L 6 (#407170)
D 8 (#10ff11)
L 7 (#18f910)
D 6 (#10ff13)
R 2 (#483d30)
D 6 (#30a891)
R 4 (#1ed8b0)
D 5 (#688901)
R 4 (#130de0)
D 6 (#4d20e1)
R 5 (#4b1000)
U 7 (#877bf1)
R 2 (#395410)
U 4 (#877bf3)
R 4 (#167f10)
D 2 (#486f11)
R 7 (#54e8d0)
D 2 (#504301)
R 2 (#8035e2)
D 7 (#433471)
R 3 (#8035e0)
D 3 (#26cad1)
R 3 (#4b3dc0)
D 5 (#802d11)
R 2 (#05af00)
D 4 (#3b3f31)
R 5 (#0dfed0)
D 8 (#3b4341)
L 6 (#489830)
D 3 (#3b4343)
L 3 (#4e0bd0)
D 7 (#0f7fd1)
R 6 (#1c6dd0)
D 2 (#318d21)
R 3 (#0cb8f2)
D 6 (#68acd1)
R 2 (#432822)
D 3 (#218ee1)
R 11 (#661ec2)
U 3 (#218ee3)
R 5 (#0b10d2)
U 4 (#2233f1)
L 3 (#2a5330)
U 3 (#0df7d1)
L 9 (#5ff680)
U 4 (#2b9701)
R 12 (#8b68d0)
U 3 (#2b9703)
L 5 (#086f10)
U 7 (#1f1431)
R 4 (#6937b0)
U 5 (#2cce51)
R 3 (#26cb50)
D 8 (#3ee1c1)
R 6 (#3c8a40)
D 5 (#7e7211)
R 7 (#7190e0)
D 3 (#036101)
R 6 (#6110b0)
D 3 (#89da01)
L 12 (#1f2cc0)
D 3 (#2b7181)
L 4 (#3942b0)
D 5 (#10f821)
L 2 (#61ae90)
D 6 (#04dee1)
L 6 (#2fc950)
D 2 (#04dee3)
L 8 (#353d90)
D 4 (#1e21b1)
L 3 (#46fa00)
D 4 (#3ea393)
R 5 (#5c2e32)
D 5 (#361be3)
R 6 (#2ddc12)
U 4 (#4b1a83)
R 6 (#135722)
U 6 (#521483)
R 9 (#7382b2)
D 6 (#239da3)
R 3 (#3ed420)
D 4 (#3a0c73)
R 6 (#5a68d0)
D 3 (#76f053)
L 5 (#244ec0)
D 4 (#062573)
L 8 (#053c50)
D 5 (#0bfac3)
R 3 (#123e30)
D 7 (#21c2c3)
R 6 (#0b11b0)
D 3 (#6781f3)
R 9 (#720e70)
D 3 (#7ddd13)
L 11 (#33d6f0)
D 2 (#1b2d83)
L 7 (#5f0280)
D 5 (#579183)
R 4 (#5f0282)
D 6 (#5c9303)
R 3 (#3c6770)
D 4 (#2b6333)
R 5 (#4f28a0)
U 5 (#55d573)
R 6 (#2b03a0)
U 5 (#244bd3)
R 5 (#644122)
U 7 (#08ab63)
R 7 (#232bc2)
U 5 (#71f5e3)
R 4 (#060d22)
U 3 (#168c63)
R 4 (#44efa2)
D 3 (#17c163)
R 9 (#2ed822)
D 6 (#17c161)
R 10 (#4b9682)
D 6 (#168c61)
R 6 (#1ab282)
D 3 (#490b43)
L 6 (#639022)
D 4 (#447151)
L 5 (#0596c0)
U 4 (#2fba61)
L 5 (#0596c2)
D 4 (#201131)
L 3 (#1f9c52)
D 3 (#0c4a23)
R 9 (#266412)
D 3 (#68bea3)
R 7 (#266410)
D 4 (#1f3423)
R 3 (#51d9c2)
D 6 (#1f6633)
R 8 (#7382b0)
U 8 (#01fca3)
R 7 (#3271f0)
U 4 (#7ee903)
R 6 (#581210)
D 7 (#7ee901)
R 2 (#12dd60)
U 7 (#15a1a3)
R 6 (#7c30f0)
U 2 (#591961)
R 3 (#69efd0)
U 4 (#591963)
L 9 (#32e7e0)
U 3 (#574071)
L 3 (#50c6a0)
U 3 (#0be261)
L 5 (#6ae5c0)
U 3 (#5c08b1)
L 3 (#7158d0)
U 2 (#36fe01)
L 4 (#325c22)
U 9 (#305be1)
R 3 (#325c20)
U 2 (#36c0a1)
R 3 (#1687d0)
U 7 (#6e3d91)
R 4 (#69abb2)
U 4 (#0a66d1)
R 4 (#3091a2)
U 6 (#548a01)
R 3 (#47a5c2)
U 3 (#2a9553)
R 5 (#795b32)
U 3 (#2a9551)
R 8 (#181b72)
U 7 (#43b071)
R 4 (#443e90)
U 2 (#3926e1)
R 4 (#6c3760)
U 4 (#694dd3)
R 6 (#4b1d30)
U 3 (#032dd1)
R 6 (#101060)
U 4 (#032dd3)
L 6 (#49c630)
U 7 (#694dd1)
L 2 (#1df000)
U 3 (#2ff181)
L 8 (#3617e2)
D 6 (#3a3c41)
L 3 (#51c8c2)
D 4 (#5c01b1)
L 11 (#0ca2b0)
U 2 (#4333b1)
L 3 (#812b52)
U 8 (#6f4601)
L 3 (#379b22)
U 2 (#07d291)
L 7 (#49e292)
U 7 (#709721)
L 4 (#1db7a2)
U 8 (#58c9d1)
L 6 (#52d210)
U 5 (#64a341)
L 3 (#1054c0)
U 7 (#64a343)
L 4 (#61a0b0)
U 10 (#187211)
L 4 (#5b9920)
U 4 (#05d301)
L 3 (#0c8ef0)
U 8 (#09f161)
L 4 (#7fa590)
U 4 (#516f31)
L 3 (#408e12)
D 6 (#3ccd51)
L 2 (#4ba672)
D 10 (#1fb771)
L 3 (#3d8200)
U 8 (#195531)
L 3 (#6bcfe0)
U 9 (#484041)
L 5 (#3ae112)
U 5 (#6d6931)
R 4 (#3ae110)
U 7 (#05dd71)
L 4 (#4c5332)
U 6 (#5df683)
L 10 (#3aebd2)
U 3 (#5f3f53)
L 3 (#815352)
U 6 (#5f3f51)
L 4 (#28ac32)
U 4 (#5df681)
R 4 (#3cb5e2)
U 2 (#7662f1)
R 4 (#322d10)
U 8 (#1a81a3)
R 5 (#3e2ba0)
D 4 (#1a81a1)
R 3 (#362bc0)
D 6 (#3e19c1)
R 5 (#234960)
U 5 (#2d2853)
R 7 (#56bab0)
U 4 (#2d2851)
R 8 (#4d6be0)
U 5 (#5ad541)
R 8 (#1d6e52)
U 6 (#077851)
L 7 (#45b722)
U 3 (#077853)
L 7 (#52cf22)
U 4 (#07d441)
R 7 (#77bb62)
U 4 (#1a8641)
R 7 (#4c1bf2)
U 3 (#2ca611)
R 3 (#18b8e2)
D 3 (#57ff81)
R 4 (#60c622)
D 7 (#42e791)
R 4 (#1a7550)
D 6 (#2645b1)
R 5 (#1a7552)
D 8 (#4ea9d1)
R 6 (#797f00)
D 2 (#02b451)
R 4 (#375b52)
D 7 (#28c491)
R 7 (#5e30f2)
D 9 (#3f4341)
L 7 (#11cf50)
D 5 (#82e171)
R 3 (#655ee0)
D 3 (#189ea1)
R 3 (#772e32)
D 10 (#177941)
R 4 (#06baa2)
D 11 (#561461)
R 2 (#5c8dd2)
D 7 (#561463)
R 6 (#36fc22)
D 5 (#0cea13)
R 2 (#4cc760)
D 4 (#4dfe53)
R 6 (#323630)
U 9 (#566003)
R 7 (#7efd92)
D 9 (#40f433)
R 6 (#080d32)
D 8 (#6cf311)
R 5 (#35bf72)
D 3 (#3b7973)
R 8 (#06a632)
D 4 (#252293)
R 4 (#06a630)
D 5 (#35ed03)
R 7 (#4d1cd2)
D 2 (#4cf4f3)
R 3 (#1dd4e2)
D 3 (#2b92f3)
R 4 (#117530)
D 4 (#5ac883)
R 12 (#117532)
U 4 (#48ca43)
R 7 (#708b12)
D 5 (#068663)
R 5 (#4247e2)
D 7 (#704161)
R 4 (#4b2b22)
D 8 (#13ea71)
R 4 (#699472)
D 5 (#4d6551)
R 5 (#8503c0)
D 2 (#281c91)
R 2 (#8503c2)
D 9 (#33a0c1)
L 5 (#4e8ad2)
D 3 (#825f21)
L 5 (#26aab2)
D 8 (#097c71)
L 6 (#169832)
D 4 (#457031)
L 7 (#8cee10)
U 5 (#251221)
L 3 (#71dce0)
U 3 (#331751)
L 6 (#7cfe10)
D 5 (#617961)
L 9 (#7cfe12)
U 5 (#04b4d1)
L 8 (#379ae0)
D 8 (#0c88f1)
L 4 (#0ee942)
D 8 (#297c01)
R 5 (#5a78a2)
D 6 (#3db043)
R 5 (#7eadd2)
D 4 (#3db041)
R 5 (#4e5622)
D 2 (#381fa1)
R 6 (#2cfd90)
D 4 (#36bd23)
R 3 (#4d18c0)
D 4 (#36bd21)
R 3 (#1a3d70)
D 2 (#6644a1)
R 12 (#868912)
D 4 (#5cb351)
R 3 (#868910)
D 4 (#3b3501)
R 5 (#1cddb0)
D 4 (#4cc9b1)
L 9 (#040250)
D 6 (#38c721)
L 7 (#23e920)
D 3 (#08dde3)
L 8 (#2c48f0)
D 4 (#08dde1)
L 2 (#414710)
D 4 (#3c36b1)
L 8 (#467ab0)
D 3 (#034323)
L 4 (#67f960)
D 6 (#034321)
L 9 (#675f90)
D 6 (#338083)
L 5 (#2b4702)
D 6 (#035ab3)
L 6 (#4d5642)
D 7 (#035ab1)
L 8 (#40ff22)
D 3 (#495523)
L 5 (#83a372)
D 5 (#1a5d23)
L 8 (#4ef3c2)
D 4 (#7515a3)
L 9 (#40d0f0)
D 5 (#143e73)
L 8 (#2ec480)
U 8 (#070d81)
R 4 (#344d10)
U 4 (#070d83)
R 5 (#2eb4b0)
U 5 (#681243)
R 3 (#51a710)
U 5 (#8a2821)
R 7 (#2faba0)
U 5 (#8a2823)
R 3 (#3849b0)
U 6 (#375b63)
L 8 (#3790d0)
U 7 (#2f77d1)
L 6 (#444dd0)
U 3 (#85afe3)
L 6 (#656d90)
U 6 (#85afe1)
L 2 (#1152b0)
U 3 (#334491)
R 4 (#362670)
U 7 (#819361)
L 4 (#4fd202)
U 3 (#718a21)
L 5 (#17bf92)
D 10 (#3334f1)
L 2 (#43c272)
D 4 (#40f041)
L 5 (#3afbc2)
D 6 (#742533)
L 8 (#0ae4c2)
U 6 (#146731)
L 8 (#2aec82)
D 2 (#89fa61)
L 3 (#044562)
D 4 (#1e14a1)
R 2 (#7b0a82)
D 4 (#1e14a3)
R 7 (#4b7812)
D 2 (#09cdc1)
R 5 (#3c3502)
D 2 (#70eb41)
R 12 (#4b7400)
D 3 (#5c8043)
L 12 (#6085c0)
D 3 (#5c8041)
L 4 (#5b0330)
D 4 (#74bce1)
L 12 (#6f6142)
D 2 (#0f2211)
L 5 (#40e5b0)
D 5 (#72afc1)
L 7 (#40e5b2)
D 3 (#160a51)
L 3 (#7a6c72)
D 6 (#3ade81)
L 4 (#6c12d2)
U 10 (#0d3851)
L 5 (#4e1680)
D 10 (#65ba61)
L 5 (#185f10)
D 3 (#65ba63)
L 6 (#3ca040)
D 7 (#6970e1)
L 3 (#49ad52)
D 2 (#0c8481)
L 8 (#3e7a82)
D 3 (#0c8483)
L 5 (#1aee02)
D 4 (#35e721)
L 4 (#39f672)
D 5 (#07f333)
L 6 (#730842)
D 6 (#0fe7b3)
L 3 (#6079e2)
D 9 (#74e4d3)
L 7 (#6079e0)
D 4 (#1c77b3)
L 3 (#3299b2)
U 4 (#6649e3)
L 5 (#496642)
U 5 (#618563)
L 4 (#36e332)
D 4 (#084843)
L 6 (#670e22)
D 9 (#164f23)
L 5 (#3c5360)
D 5 (#467003)
L 3 (#3c5362)
U 3 (#3980d3)
L 3 (#275e32)
U 6 (#19ea63)
L 4 (#855df0)
U 2 (#5ec993)
L 9 (#66f342)
U 7 (#4ac7a3)
L 5 (#1e6ab2)
U 8 (#2bd3a3)
L 4 (#5f6272)
U 5 (#3b2031)
L 4 (#1c1fa0)
U 5 (#534711)
R 3 (#1c1fa2)
U 5 (#3474d1)
R 5 (#572be2)
D 4 (#2cdf53)
R 6 (#3bb0e2)
U 4 (#5e9073)
R 4 (#3bb0e0)
U 4 (#376c53)
L 3 (#193f72)
U 3 (#484e83)
L 4 (#799b82)
U 5 (#52f273)
R 4 (#376190)
U 5 (#3650a3)
L 5 (#7def10)
D 2 (#20fa83)
L 2 (#089240)
D 11 (#49c3a3)
L 3 (#768be0)
U 4 (#42fa23)
L 5 (#5ab362)
U 4 (#593983)
L 8 (#5e6ba2)
D 4 (#593981)
R 4 (#7b4fc2)
D 9 (#44a9c3)
L 2 (#086692)
D 3 (#7ce9f3)
L 4 (#68b430)
U 6 (#5ab7c1)
L 4 (#430330)
D 6 (#0b1593)
L 5 (#1ca4a0)
D 5 (#0b1591)
R 10 (#429f80)
D 2 (#5ab7c3)
R 2 (#292be0)
D 4 (#7a8693)
R 3 (#12dfd2)
D 10 (#2244f3)
L 4 (#4eeb62)
D 10 (#4831c3)
L 6 (#25aa50)
U 8 (#379b33)
L 3 (#25aa52)
U 3 (#145863)
L 5 (#480492)
U 4 (#69feb1)
L 7 (#593592)
U 4 (#4c6b91)
L 5 (#312212)
U 3 (#26df43)
R 12 (#68b362)
U 4 (#6e94f3)
L 5 (#28bd52)
U 4 (#1aea03)
L 8 (#615f22)
U 2 (#6fb163)
L 2 (#40b8a2)
U 7 (#09d633)
L 7 (#044e02)
U 8 (#1a4333)
L 4 (#172d00)
U 2 (#4509c3)
L 6 (#4de1d0)
U 7 (#818a41)
L 4 (#0ce4b0)
U 7 (#0745d1)
R 6 (#520370)
U 2 (#5a7db3)
R 8 (#2f93c0)
U 4 (#2e5263)
L 4 (#147e00)
U 3 (#44d303)
L 7 (#245640)
U 4 (#17d933)
L 3 (#4f6820)
U 3 (#17d931)
L 10 (#488c50)
D 3 (#108b33)
L 4 (#300e60)
D 3 (#887d43)
R 7 (#4272d0)
D 8 (#657091)
L 7 (#63d120)
D 3 (#230cb1)
R 4 (#04e1b0)
D 6 (#4ba9a3)
L 7 (#055c40)
U 2 (#3ee173)
L 4 (#454062)
U 6 (#2af563)
L 3 (#40a642)
U 6 (#4ddf13)
L 6 (#85e6a0)
U 6 (#090df3)
L 9 (#055c42)
U 2 (#4ac2b3)
L 3 (#2ae1a0)
U 5 (#43af51)
R 6 (#860900)
U 5 (#43af53)
L 6 (#057bb0)
U 3 (#570c13)
R 4 (#515d92)
U 3 (#09a031)
L 7 (#45b7f2)
U 5 (#09a033)
R 6 (#1f50d2)
U 7 (#4e6373)
L 6 (#5df030)
U 7 (#004663)
R 7 (#10f120)
U 4 (#5f4883)
L 12 (#10f122)
U 2 (#441aa3)
L 3 (#1c7242)
U 4 (#4849a3)
R 7 (#7026d2)
U 4 (#442943)
R 8 (#5c5152)
U 5 (#563813)
L 4 (#5c5150)
U 4 (#1460b3)
L 5 (#1d3272)
U 6 (#1d15d3)
R 5 (#4fe282)
U 3 (#6a04c1)
L 6 (#2ca912)
U 5 (#1d2623)
L 6 (#298bb2)
U 3 (#1d2621)
L 9 (#3a4e82)
U 4 (#2abf71)
L 5 (#01c5d2)
U 4 (#7f5d41)
L 6 (#0149b2)
U 4 (#66f8c3)
L 5 (#53acd2)
U 6 (#55caa3)
L 3 (#676e82)
U 8 (#5c69a3)
R 5 (#5d7ed2)
U 2 (#1d90a3)
R 3 (#579cb2)
U 3 (#631003)
R 9 (#6ffcb2)
U 5 (#2e98f3)
R 2 (#036c22)
U 3 (#2bd763)
L 5 (#478442)
U 7 (#7a8373)
L 9 (#5da862)
U 4 (#13a8d3)

@ -0,0 +1,14 @@
R 6 (#70c710)
D 5 (#0dc571)
L 2 (#5713f0)
D 2 (#d2c081)
R 2 (#59c680)
D 2 (#411b91)
L 5 (#8ceee2)
U 2 (#caa173)
L 1 (#1b58a2)
U 2 (#caa171)
R 2 (#7807d2)
U 3 (#a77fa3)
L 2 (#015232)
U 2 (#7a21e3)

@ -0,0 +1,380 @@
const std = @import("std");
fn Order(comptime T: type) type {
return struct {
fn order(context: void, lhs: T, rhs: T) std.math.Order {
_ = context;
return std.math.order(lhs, rhs);
}
};
}
fn StackList(comptime T: type, comptime capacity_type: type, comptime capacity: capacity_type) type {
return struct {
const Self = @This();
mem: [capacity]T,
length: capacity_type,
fn add(self: *Self, value: T) void {
self.mem[self.length] = value;
self.length += 1;
}
fn addIfNotNull(self: *Self, nullable_value: ?T) void {
if (nullable_value) |value| {
self.add(value);
}
}
fn has(self: *const Self, needle: T) bool {
for (0..self.length) |i| {
if (self.mem[i] == needle) {
return true;
}
}
return false;
}
fn addUnique(self: *Self, value: T) void {
if (!self.has(value)) {
self.add(value);
}
}
fn getMutableSlice(self: *Self) []T {
return (&self.mem)[0..self.length];
}
fn getSlice(self: *const Self) []const T {
return self.mem[0..self.length];
}
fn init() Self {
return Self{
.mem = undefined,
.length = 0,
};
}
};
}
fn RingQueueWrapper(comptime T: type, comptime size: usize) type {
return struct {
const Self = @This();
mem: *[size]T,
first: usize,
next: usize,
fn add(self: *Self, value: T) void {
std.debug.assert(self.next - self.first < size);
self.mem.*[self.next % size] = value;
self.next += 1;
}
fn take(self: *Self) T {
const result = self.mem.*[self.first % size];
self.first += 1;
return result;
}
fn isEmpty(self: *const Self) bool {
return self.next == self.first;
}
fn init(mem: *[size]T) Self {
return Self{
.mem = mem,
.first = 0,
.next = 0,
};
}
};
}
fn readNumber(comptime T: type, line: []const u8, index: *usize) T {
var result: T = 0;
while (index.* < line.len and line[index.*] == ' ') : (index.* += 1) {}
var is_negative = false;
if (index.* < line.len and line[index.*] == '-') {
is_negative = true;
index.* += 1;
}
std.debug.assert(index.* < line.len);
while (index.* < line.len) : (index.* += 1) {
const char = line[index.*];
switch (char) {
'0'...'9' => {
result = result * 10 + (char - '0');
},
else => {
break;
},
}
}
return if (is_negative) (0 - result) else result;
}
fn Coordinates(comptime CoordinateType: type) type {
return struct {
const Self = @This();
x: CoordinateType,
y: CoordinateType,
fn isSameX(self: *const Self, other: Self) bool {
return self.x == other.x;
}
fn approachX(self: *Self, other: Self) void {
if (self.x < other.x) {
self.x += 1;
} else {
self.x -= 1;
}
}
fn isSameY(self: *const Self, other: Self) bool {
return self.y == other.y;
}
fn approachY(self: *Self, other: Self) void {
if (self.y < other.y) {
self.y += 1;
} else {
self.y -= 1;
}
}
};
}
fn GenericTerrain(comptime CoordinateType: type, comptime height: CoordinateType, comptime width: CoordinateType, comptime CellType: type) type {
return struct {
const Self = @This();
coordinates: Coordinates(CoordinateType),
cells: [height][width]CellType,
fn initZeroes() Self {
return .{
.coordinates = .{
.x = height / 2,
.y = width / 2,
},
.cells = std.mem.zeroes([height][width]CellType),
};
}
fn getCurrentCell(self: *const Self) CellType {
return self.cells[self.coordinates.x][self.coordinates.y];
}
fn setCurrentCell(self: *Self, value: CellType) void {
self.cells[self.coordinates.x][self.coordinates.y] = value;
}
};
}
const CellStatus = enum(u2) {
Default = 0,
NotDug = 1,
Dug = 2,
};
const TerrainCoordinate = u16;
const Terrain = GenericTerrain(TerrainCoordinate, 1024, 1024, CellStatus);
const TerrainCoordinates = Coordinates(TerrainCoordinate);
const Direction = enum(u8) {
Right = 0,
Down = 1,
Left = 2,
Up = 3,
};
const RawCommand = packed struct(u32) {
direction: Direction,
length: u24,
};
const RawCoordinates = Coordinates(u24);
fn floodTerrain(terrain: *Terrain) void {
var queue_mem: [65_536]TerrainCoordinates = undefined;
var tasks = RingQueueWrapper(TerrainCoordinates, queue_mem.len).init(&queue_mem);
tasks.add(.{ .x = 0, .y = 0 });
while (!tasks.isEmpty()) {
const task = tasks.take();
terrain.coordinates = task;
//std.debug.print("Processing task for {d},{d} (current status: {any})\n", .{ x, y, terrain.*.cells[x][y] });
if (terrain.getCurrentCell() == .Default) {
terrain.setCurrentCell(.NotDug);
//std.debug.print("Marked {d},{d} as NotDug\n", .{ x, y });
const x = task.x;
const y = task.y;
if (x > 0) {
tasks.add(.{ .x = x - 1, .y = y });
}
if (x + 1 < terrain.*.cells.len) {
tasks.add(.{ .x = x + 1, .y = y });
}
if (y > 0) {
tasks.add(.{ .x = x, .y = y - 1 });
}
if (y + 1 < terrain.*.cells[x].len) {
tasks.add(.{ .x = x, .y = y + 1 });
}
}
}
}
fn getTargetRawCoordinates(coordinates: RawCoordinates, command: RawCommand) RawCoordinates {
return @TypeOf(coordinates){
.x = switch (command.direction) {
.Right => coordinates.x + command.length,
.Left => coordinates.x - command.length,
.Up, .Down => coordinates.x,
},
.y = switch (command.direction) {
.Down => coordinates.y + command.length,
.Up => coordinates.y - command.length,
.Left, .Right => coordinates.y,
},
};
}
fn getCoordinate(known_values: []const u24, raw_coordinate: u24) TerrainCoordinate {
const maybe_index = std.sort.binarySearch(u24, raw_coordinate, known_values, {}, Order(u24).order);
return @as(TerrainCoordinate, @intCast(maybe_index.?));
}
fn solveForCommands(raw_commands: []const RawCommand) usize {
const start_value = 1 << 23;
var raw_coordinates = RawCoordinates{
.x = start_value,
.y = start_value,
};
var known_values = StackList(u24, u16, 2048).init();
known_values.addUnique(0);
known_values.addUnique(start_value - 1);
known_values.addUnique(start_value);
known_values.addUnique(start_value + 1);
known_values.addUnique(std.math.maxInt(u24));
for (raw_commands) |raw_command| {
raw_coordinates = getTargetRawCoordinates(raw_coordinates, raw_command);
known_values.addUnique(raw_coordinates.x - 1);
known_values.addUnique(raw_coordinates.x);
known_values.addUnique(raw_coordinates.x + 1);
known_values.addUnique(raw_coordinates.y - 1);
known_values.addUnique(raw_coordinates.y);
known_values.addUnique(raw_coordinates.y + 1);
}
std.sort.heap(u24, known_values.getMutableSlice(), {}, std.sort.asc(u24));
var known_values_slice = known_values.getSlice();
raw_coordinates = RawCoordinates{
.x = start_value,
.y = start_value,
};
var terrain = Terrain.initZeroes();
terrain.coordinates = .{
.x = getCoordinate(known_values_slice, start_value),
.y = getCoordinate(known_values_slice, start_value),
};
for (raw_commands) |raw_command| {
raw_coordinates = getTargetRawCoordinates(raw_coordinates, raw_command);
const target = TerrainCoordinates{
.x = getCoordinate(known_values_slice, raw_coordinates.x),
.y = getCoordinate(known_values_slice, raw_coordinates.y),
};
while (!terrain.coordinates.isSameX(target)) {
terrain.coordinates.approachX(target);
terrain.setCurrentCell(.Dug);
}
while (!terrain.coordinates.isSameY(target)) {
terrain.coordinates.approachY(target);
terrain.setCurrentCell(.Dug);
}
}
floodTerrain(&terrain);
const cells = terrain.cells;
var result: u64 = 0;
for (0..cells.len) |x| {
for (0..cells[x].len) |y| {
if (cells[x][y] != .NotDug) {
// Doesn't really matter whether we take x..x+1 or x-1..x here, because boundary blocks will always have size 1
result += @as(u64, known_values_slice[x + 1] - known_values_slice[x]) * @as(u64, known_values_slice[y + 1] - known_values_slice[y]);
}
}
}
return result;
}
fn parseCommand(command: []const u8) RawCommand {
var index: usize = 2;
const length = readNumber(u24, command, &index);
const direction: Direction = switch (command[0]) {
'R' => .Right,
'L' => .Left,
'U' => .Up,
'D' => .Down,
else => unreachable,
};
return .{
.length = length,
.direction = direction,
};
}
fn solveAll(reader: anytype) !usize {
var result: usize = 0;
while (true) {
var commands = StackList(RawCommand, usize, 1024).init();
var empty_line_reached = false;
var line_buffer: [1000]u8 = undefined;
while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |line| {
if (line.len == 0) {
empty_line_reached = true;
break;
}
commands.add(parseCommand(line));
}
result += solveForCommands(commands.getSlice());
if (!empty_line_reached) {
return result;
}
}
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const raw_in = std.io.getStdIn();
var buffered_reader = std.io.bufferedReader(raw_in.reader());
var reader = buffered_reader.reader();
const result = try solveAll(&reader);
try stdout.print("{d}\n", .{result});
}
Loading…
Cancel
Save