@nickymeuleman/aoc2021
TypeScript icon, indicating that this package has built-in type declarations

0.4.5 • Public • Published

Advent of Code 2021 solver

Solutions to every problem of advent of code 2021 written in Rust.

Meant to be compiled to WebAssembly and used on the web.

Exposes a solve function to WASM that takes in a day number and an input string, returns the answers in a struct.

After optimizing the output .wasm file for size, the solutions run significantly slower. This consisted of:

  • Using the "-Oz" flag for wasm-opt and the "z" flag for opt-level in Cargo.toml.
  • Replacing the faster hashbrown with the standard HashMap and HashSet found in std::collections.
  • Replacing usage of the format! macro with equivalent logic.

Day19 might pose a practical time constraint now since the browser blocks while executing a function.

Output of wc -c pkg/aoc2021_bg.wasm: 207800 pkg/aoc2021_bg.wasm

and after making solve an async function so it returns a Promise in JS: 218328 pkg/aoc2021_bg.wasm

That is, unfortunately, a huge increase in size.

Day 01

Part 1

Benchmark

[1.0398 us 1.0458 us 1.0528 us]

After size optimizations

[1.3266 us 1.3475 us 1.3709 us]

Part 2

Benchmark

[4.0967 us 4.1735 us 4.2572 us]

After size optimizations

[8.6006 us 8.6983 us 8.8200 us]

Day 02

Part 1

Benchmark

[1.5897 us 1.6265 us 1.6736 us]

After size optimizations

[1.3061 us 1.3429 us 1.3882 us]

Part 2

Benchmark

[1.2958 us 1.3273 us 1.3613 us]

After size optimizations

[1.3980 us 1.4292 us 1.4611 us]

Day 03

Part 1

Benchmark

[64.042 us 66.476 us 69.339 us]

After size optimizations

[68.542 us 71.163 us 73.841 us]

Part 2

Benchmark

[164.05 us 169.21 us 174.88 us]

After size optimizations

[191.49 us 200.65 us 211.10 us]

Day 04

Part 1

Benchmark

[207.48 us 212.46 us 218.10 us]

After size optimizations

[261.79 us 268.69 us 276.97 us]

Part 2

Benchmark

[677.47 us 694.06 us 713.34 us]

After size optimizations

[797.75 us 813.56 us 832.00 us]

Day 05

Part 1

Benchmark

[4.2040 ms 4.3197 ms 4.4431 ms]

After size optimizations

[11.803 ms 11.873 ms 11.954 ms]

Part 2

Benchmark

[7.8825 ms 8.0998 ms 8.3261 ms]

After size optimizations

[24.712 ms 24.826 ms 24.957 ms]

Day 06

Part 1

Benchmark

[5.6814 us 5.7887 us 5.9209 us]

After size optimizations

[5.6522 us 5.6756 us 5.7004 us]

Part 2

Benchmark

[6.3091 us 6.3808 us 6.4785 us]

After size optimizations

[6.5222 us 6.5428 us 6.5657 us]

Day 07

Part 1

Benchmark

[1.1787 ms 1.1845 ms 1.1910 ms]

After size optimizations

[1.3380 ms 1.3426 ms 1.3479 ms]

Part 2

Benchmark

[2.0990 ms 2.1065 ms 2.1141 ms]

After size optimizations

[5.8722 ms 5.8925 ms 5.9152 ms]

Day 08

Part 1

Benchmark

[921.17 ns 934.28 ns 949.27 ns]

After size optimizations

[1.1516 us 1.1571 us 1.1635 us]

Part 2

Benchmark

[145.11 us 147.86 us 150.99 us]

After size optimizations

[549.63 us 551.68 us 553.91 us]

Day 09

Part 1

Benchmark

[73.821 us 74.566 us 75.644 us

After size optimizations

[82.482 us 82.798 us 83.152 us]

Part 2

Benchmark

[893.55 us 896.08 us 898.92 us]

After size optimizations

[2.8614 ms 2.8894 ms 2.9288 ms]

Day 10

Part 1

Benchmark

[74.966 us 76.239 us 77.746 us]

After size optimizations

[68.886 us 69.470 us 70.317 us]

Part 2

Benchmark

[141.26 us 146.02 us 151.06 us]

After size optimizations

[136.67 us 137.11 us 137.62 us]

Day 11

Part 1

Benchmark

[200.92 us 201.79 us 202.78 us]

After size optimizations

[291.47 us 292.46 us 293.54 us]

Part 2

Benchmark

[501.64 us 509.96 us 519.56 us]

After size optimizations

[673.40 us 675.50 us 677.97 us]

Day 12

Part 1

Benchmark

[2.0978 ms 2.1319 ms 2.1806 ms]

After size optimizations

[3.2680 ms 3.2784 ms 3.2898 ms]

Part 2

Benchmark

[50.819 ms 51.288 ms 51.788 ms]

After size optimizations

[111.84 ms 112.33 ms 112.97 ms]

Day 13

Part 1

Benchmark

without mutating fold instructions:

[11.951 us 12.238 us 12.569 us]

with mutating fold instructions:

[12.419 us 12.470 us 12.525 us]
change: [+2.5203% +4.2624% +5.9012%] (p = 0.00 < 0.05)
Performance has regressed.

After refactoring fold execution to a seperate function, not a method on Data:

[10.885 us 10.931 us 10.981 us]

After size optimizations

[37.471 us 37.635 us 37.837 us]

Part 2

Benchmark

without mutating fold instructions:

[83.771 us 85.367 us 87.226 us] 

with mutating fold instructions:

[82.032 us 82.971 us 84.093 us]
change: [-9.2115% -7.2411% -4.9832%] (p = 0.00 < 0.05)
Performance has improved.

After refactoring fold execution to a seperate function, not a method on Data:

[79.433 us 80.550 us 82.121 us]

After adding logic to recognize characters instead of printing out the ASCII

[83.661 us 84.447 us 85.291 us]

After size optimizations

[207.91 us 208.76 us 209.70 us]

Day 14

Part 1

Benchmark

[53.869 us 54.090 us 54.342 us]

After size optimizations

[157.03 us 157.64 us 158.40 us]

Part 2

Benchmark

[248.48 us 250.10 us 251.92 us] 

After size optimizations

[729.82 us 731.85 us 734.01 us]

Day 15

Part 1

Benchmark

with a HashMap as datastructure to store shortest path to a certain point

[2.6342 ms 2.6547 ms 2.6761 ms]

with a 1D vector as datastructure to store shortest path to a certain point

[1.9476 ms 1.9558 ms 1.9643 ms]
change: [-26.981% -26.328% -25.664%] (p = 0.00 < 0.05)

After size optimizations

[2.4650 ms 2.4850 ms 2.5084 ms]

Part 2

Benchmark

with a HashMap as datastructure to store shortest path to a certain point

[76.923 ms 78.024 ms 79.276 ms]

with a 1D vector as datastructure to store shortest path to a certain point

[53.251 ms 53.464 ms 53.690 ms]
change: [-32.613% -31.477% -30.468%] (p = 0.00 < 0.05)

After size optimizations

[65.226 ms 65.441 ms 65.681 ms]

Day 16

Part 1

Benchmark

Storing bits as chars and using ::from_str_radix() to get numbers:

[87.264 us 88.040 us 88.992 us]

After storing bits as bools and using math to get numbers:

[42.396 us 42.632 us 42.877 us]
change: [-52.498% -51.711% -50.886%] (p = 0.00 < 0.05)

After using bit operations to get the decimal number from bits: (from .fold(0, |acc, digit| acc * 2 + if digit { 1 } else { 0 })) to .fold(0, |acc, bit| (acc << 1) ^ if bit { 1 } else { 0 }))

[42.018 us 42.161 us 42.310 us]
change: [-2.2989% -0.9042% +0.3506%] (p = 0.20 > 0.05)

After size optimizations

[48.239 us 48.461 us 48.721 us]

Part 2

Benchmark

Storing bits as chars and using ::from_str_radix() to get numbers:

[91.922 us 92.952 us 94.166 us]

After storing bits as bools and using math to get numbers:

[48.997 us 50.510 us 52.263 us]
change: [-45.295% -43.619% -41.479%] (p = 0.00 < 0.05)

After using bit operations to get the decimal number from bits: (from .fold(0, |acc, digit| acc * 2 + if digit { 1 } else { 0 })) to .fold(0, |acc, bit| (acc << 1) | if bit { 1 } else { 0 }))

[47.572 us 47.697 us 47.822 us]
change: [-10.960% -7.7181% -4.6726%] (p = 0.00 < 0.05)

Conclusion: Is the bit shifting thing more readable? Depends on who's reading.

After size optimizations

[48.817 us 48.978 us 49.189 us]

Day 17

Part 1

Benchmark

[35.678 ns 36.522 ns 37.610 ns]

After size optimizations

[41.424 ns 41.548 ns 41.691 ns]

Part 2

Benchmark

[587.48 us 602.45 us 618.62 us]

After size optimizations

[538.67 us 540.32 us 542.18 us]

Day 18

Part 1

Benchmark

[300.43 us 302.66 us 305.30 us]

After size optimizations

[674.25 us 676.38 us 678.78 us]

Part 2

Benchmark

[7.7538 ms 7.7788 ms 7.8057 ms]

After size optimizations

[15.751 ms 15.804 ms 15.864 ms]

Day 19

This day takes a long time to run. Decreased sample size to 10, because I'm not waiting for 100 measurements.

First day where I've implemented a custom solve method on the AoCDay trait to avoid duplicate work when asking for both part1 and 2 at once. This will make the usage from WASM much faster, since that's the only method it calls currently.

Part 1

Benchmark

[1.7463 s 1.7580 s 1.7725 s]

After size optimizations

[9.2029 s 11.494 s 14.106 s]

wow, this is incredible. The effect of the speed optimizations the compiler did were huge here.

Part 2

Benchmark

[1.7438 s 1.7702 s 1.8116 s]

After size optimizations

[8.4435 s 8.5749 s 8.7118 s]

Day 20

Part 1

Benchmark

With a 2D-VecDeque storing rows and cols

[547.49 us 548.93 us 550.44 us]

With a 2D-Vec storing rows and cols

[441.71 us 443.00 us 444.36 us]

After size optimizations

[1.1968 ms 1.2213 ms 1.2504 ms]

Part 2

Benchmark

With a 2D-VecDeque storing rows and cols

[30.728 ms 31.506 ms 32.428 ms]

With a 2D-Vec storing rows and cols

[25.448 ms 25.821 ms 26.211 ms]]

After size optimizations

[65.185 ms 66.377 ms 67.696 ms]

Day 21

Part 1

Benchmark

[2.9967 us 3.0359 us 3.0783 us]

After size optimizations

[4.7205 us 4.8601 us 5.0192 us]

Part 2

Benchmark

[5.5877 ms 5.6601 ms 5.7407 ms]

After size optimizations

[20.328 ms 20.488 ms 20.657 ms]

Day 22

Part 1

Benchmark

[988.51 us 1.0037 ms 1.0260 ms]

commented out approach

[1.3082 ms 1.3272 ms 1.3506 ms]

After size optimizations

[1.5193 ms 1.5497 ms 1.5819 ms]

Part 2

Benchmark

[2.4163 ms 2.4292 ms 2.4437 ms]

commented out approach

[53.378 ms 55.485 ms 57.885 ms]

After size optimizations

[2.6511 ms 2.6884 ms 2.7272 ms]

Day 23

Part 1

Benchmark

[46.637 ms 46.829 ms 47.036 ms]

After size optimizations

[128.67 ms 129.66 ms 130.78 ms]

Part 2

Part2 takes less time to complete somehow. Wow.

Benchmark

[40.298 ms 40.427 ms 40.561 ms]

After size optimizations

[115.58 ms 116.65 ms 118.02 ms]

Day 24

Part 1

Benchmark

[1.0734 s 1.0823 s 1.0937 s]

After size optimizations

[2.0489 s 2.0831 s 2.1218 s]

Part 2

Benchmark

[144.04 ms 155.46 ms 162.40 ms]

After size optimizations

[274.41 ms 281.92 ms 289.90 ms]

Day 25

Part 1

Benchmark

[105.07 ms 105.55 ms 106.12 ms]

After size optimizations

[124.53 ms 126.48 ms 128.63 ms]

Part 2

Benchmark

However quickly you can click a button to complete it.

Readme

Keywords

none

Package Sidebar

Install

npm i @nickymeuleman/aoc2021

Weekly Downloads

0

Version

0.4.5

License

none

Unpacked Size

247 kB

Total Files

6

Last publish

Collaborators

  • nickymeuleman