feat: optimisation and introduce criterion and log

thecoded.prof 05cafbcb 8d554a58

verified
Changed files
+862 -73
2025
+729
2025/Cargo.lock
··· 3 3 version = 4 4 4 5 5 [[package]] 6 + name = "aho-corasick" 7 + version = "1.1.4" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" 10 + dependencies = [ 11 + "memchr", 12 + ] 13 + 14 + [[package]] 15 + name = "alloca" 16 + version = "0.4.0" 17 + source = "registry+https://github.com/rust-lang/crates.io-index" 18 + checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" 19 + dependencies = [ 20 + "cc", 21 + ] 22 + 23 + [[package]] 24 + name = "anes" 25 + version = "0.1.6" 26 + source = "registry+https://github.com/rust-lang/crates.io-index" 27 + checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" 28 + 29 + [[package]] 30 + name = "anstream" 31 + version = "0.6.21" 32 + source = "registry+https://github.com/rust-lang/crates.io-index" 33 + checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" 34 + dependencies = [ 35 + "anstyle", 36 + "anstyle-parse", 37 + "anstyle-query", 38 + "anstyle-wincon", 39 + "colorchoice", 40 + "is_terminal_polyfill", 41 + "utf8parse", 42 + ] 43 + 44 + [[package]] 45 + name = "anstyle" 46 + version = "1.0.13" 47 + source = "registry+https://github.com/rust-lang/crates.io-index" 48 + checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" 49 + 50 + [[package]] 51 + name = "anstyle-parse" 52 + version = "0.2.7" 53 + source = "registry+https://github.com/rust-lang/crates.io-index" 54 + checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" 55 + dependencies = [ 56 + "utf8parse", 57 + ] 58 + 59 + [[package]] 60 + name = "anstyle-query" 61 + version = "1.1.5" 62 + source = "registry+https://github.com/rust-lang/crates.io-index" 63 + checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" 64 + dependencies = [ 65 + "windows-sys", 66 + ] 67 + 68 + [[package]] 69 + name = "anstyle-wincon" 70 + version = "3.0.11" 71 + source = "registry+https://github.com/rust-lang/crates.io-index" 72 + checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" 73 + dependencies = [ 74 + "anstyle", 75 + "once_cell_polyfill", 76 + "windows-sys", 77 + ] 78 + 79 + [[package]] 6 80 name = "anyhow" 7 81 version = "1.0.100" 8 82 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 14 88 dependencies = [ 15 89 "anyhow", 16 90 "atoi_simd", 91 + "criterion", 92 + "env_logger", 93 + "log", 17 94 "memchr", 18 95 ] 19 96 ··· 27 104 ] 28 105 29 106 [[package]] 107 + name = "autocfg" 108 + version = "1.5.0" 109 + source = "registry+https://github.com/rust-lang/crates.io-index" 110 + checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 111 + 112 + [[package]] 113 + name = "bumpalo" 114 + version = "3.19.0" 115 + source = "registry+https://github.com/rust-lang/crates.io-index" 116 + checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 117 + 118 + [[package]] 119 + name = "cast" 120 + version = "0.3.0" 121 + source = "registry+https://github.com/rust-lang/crates.io-index" 122 + checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" 123 + 124 + [[package]] 125 + name = "cc" 126 + version = "1.2.48" 127 + source = "registry+https://github.com/rust-lang/crates.io-index" 128 + checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" 129 + dependencies = [ 130 + "find-msvc-tools", 131 + "shlex", 132 + ] 133 + 134 + [[package]] 135 + name = "cfg-if" 136 + version = "1.0.4" 137 + source = "registry+https://github.com/rust-lang/crates.io-index" 138 + checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 139 + 140 + [[package]] 141 + name = "ciborium" 142 + version = "0.2.2" 143 + source = "registry+https://github.com/rust-lang/crates.io-index" 144 + checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" 145 + dependencies = [ 146 + "ciborium-io", 147 + "ciborium-ll", 148 + "serde", 149 + ] 150 + 151 + [[package]] 152 + name = "ciborium-io" 153 + version = "0.2.2" 154 + source = "registry+https://github.com/rust-lang/crates.io-index" 155 + checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" 156 + 157 + [[package]] 158 + name = "ciborium-ll" 159 + version = "0.2.2" 160 + source = "registry+https://github.com/rust-lang/crates.io-index" 161 + checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 162 + dependencies = [ 163 + "ciborium-io", 164 + "half", 165 + ] 166 + 167 + [[package]] 168 + name = "clap" 169 + version = "4.5.53" 170 + source = "registry+https://github.com/rust-lang/crates.io-index" 171 + checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" 172 + dependencies = [ 173 + "clap_builder", 174 + ] 175 + 176 + [[package]] 177 + name = "clap_builder" 178 + version = "4.5.53" 179 + source = "registry+https://github.com/rust-lang/crates.io-index" 180 + checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" 181 + dependencies = [ 182 + "anstyle", 183 + "clap_lex", 184 + ] 185 + 186 + [[package]] 187 + name = "clap_lex" 188 + version = "0.7.6" 189 + source = "registry+https://github.com/rust-lang/crates.io-index" 190 + checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" 191 + 192 + [[package]] 193 + name = "colorchoice" 194 + version = "1.0.4" 195 + source = "registry+https://github.com/rust-lang/crates.io-index" 196 + checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 197 + 198 + [[package]] 199 + name = "criterion" 200 + version = "0.8.0" 201 + source = "registry+https://github.com/rust-lang/crates.io-index" 202 + checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab" 203 + dependencies = [ 204 + "alloca", 205 + "anes", 206 + "cast", 207 + "ciborium", 208 + "clap", 209 + "criterion-plot", 210 + "itertools", 211 + "num-traits", 212 + "oorandom", 213 + "page_size", 214 + "plotters", 215 + "rayon", 216 + "regex", 217 + "serde", 218 + "serde_json", 219 + "tinytemplate", 220 + "walkdir", 221 + ] 222 + 223 + [[package]] 224 + name = "criterion-plot" 225 + version = "0.8.0" 226 + source = "registry+https://github.com/rust-lang/crates.io-index" 227 + checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6" 228 + dependencies = [ 229 + "cast", 230 + "itertools", 231 + ] 232 + 233 + [[package]] 234 + name = "crossbeam-deque" 235 + version = "0.8.6" 236 + source = "registry+https://github.com/rust-lang/crates.io-index" 237 + checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 238 + dependencies = [ 239 + "crossbeam-epoch", 240 + "crossbeam-utils", 241 + ] 242 + 243 + [[package]] 244 + name = "crossbeam-epoch" 245 + version = "0.9.18" 246 + source = "registry+https://github.com/rust-lang/crates.io-index" 247 + checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 248 + dependencies = [ 249 + "crossbeam-utils", 250 + ] 251 + 252 + [[package]] 253 + name = "crossbeam-utils" 254 + version = "0.8.21" 255 + source = "registry+https://github.com/rust-lang/crates.io-index" 256 + checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 257 + 258 + [[package]] 259 + name = "crunchy" 260 + version = "0.2.4" 261 + source = "registry+https://github.com/rust-lang/crates.io-index" 262 + checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" 263 + 264 + [[package]] 30 265 name = "debug_unsafe" 31 266 version = "0.1.3" 32 267 source = "registry+https://github.com/rust-lang/crates.io-index" 33 268 checksum = "85d3cef41d236720ed453e102153a53e4cc3d2fde848c0078a50cf249e8e3e5b" 34 269 35 270 [[package]] 271 + name = "either" 272 + version = "1.15.0" 273 + source = "registry+https://github.com/rust-lang/crates.io-index" 274 + checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 275 + 276 + [[package]] 277 + name = "env_filter" 278 + version = "0.1.4" 279 + source = "registry+https://github.com/rust-lang/crates.io-index" 280 + checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" 281 + dependencies = [ 282 + "log", 283 + "regex", 284 + ] 285 + 286 + [[package]] 287 + name = "env_logger" 288 + version = "0.11.8" 289 + source = "registry+https://github.com/rust-lang/crates.io-index" 290 + checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" 291 + dependencies = [ 292 + "anstream", 293 + "anstyle", 294 + "env_filter", 295 + "jiff", 296 + "log", 297 + ] 298 + 299 + [[package]] 300 + name = "find-msvc-tools" 301 + version = "0.1.5" 302 + source = "registry+https://github.com/rust-lang/crates.io-index" 303 + checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" 304 + 305 + [[package]] 306 + name = "half" 307 + version = "2.7.1" 308 + source = "registry+https://github.com/rust-lang/crates.io-index" 309 + checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" 310 + dependencies = [ 311 + "cfg-if", 312 + "crunchy", 313 + "zerocopy", 314 + ] 315 + 316 + [[package]] 317 + name = "is_terminal_polyfill" 318 + version = "1.70.2" 319 + source = "registry+https://github.com/rust-lang/crates.io-index" 320 + checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" 321 + 322 + [[package]] 323 + name = "itertools" 324 + version = "0.13.0" 325 + source = "registry+https://github.com/rust-lang/crates.io-index" 326 + checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 327 + dependencies = [ 328 + "either", 329 + ] 330 + 331 + [[package]] 332 + name = "itoa" 333 + version = "1.0.15" 334 + source = "registry+https://github.com/rust-lang/crates.io-index" 335 + checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 336 + 337 + [[package]] 338 + name = "jiff" 339 + version = "0.2.16" 340 + source = "registry+https://github.com/rust-lang/crates.io-index" 341 + checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" 342 + dependencies = [ 343 + "jiff-static", 344 + "log", 345 + "portable-atomic", 346 + "portable-atomic-util", 347 + "serde_core", 348 + ] 349 + 350 + [[package]] 351 + name = "jiff-static" 352 + version = "0.2.16" 353 + source = "registry+https://github.com/rust-lang/crates.io-index" 354 + checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" 355 + dependencies = [ 356 + "proc-macro2", 357 + "quote", 358 + "syn", 359 + ] 360 + 361 + [[package]] 362 + name = "js-sys" 363 + version = "0.3.83" 364 + source = "registry+https://github.com/rust-lang/crates.io-index" 365 + checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" 366 + dependencies = [ 367 + "once_cell", 368 + "wasm-bindgen", 369 + ] 370 + 371 + [[package]] 372 + name = "libc" 373 + version = "0.2.178" 374 + source = "registry+https://github.com/rust-lang/crates.io-index" 375 + checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" 376 + 377 + [[package]] 378 + name = "log" 379 + version = "0.4.29" 380 + source = "registry+https://github.com/rust-lang/crates.io-index" 381 + checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" 382 + 383 + [[package]] 36 384 name = "memchr" 37 385 version = "2.7.6" 38 386 source = "registry+https://github.com/rust-lang/crates.io-index" 39 387 checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" 388 + 389 + [[package]] 390 + name = "num-traits" 391 + version = "0.2.19" 392 + source = "registry+https://github.com/rust-lang/crates.io-index" 393 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 394 + dependencies = [ 395 + "autocfg", 396 + ] 397 + 398 + [[package]] 399 + name = "once_cell" 400 + version = "1.21.3" 401 + source = "registry+https://github.com/rust-lang/crates.io-index" 402 + checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 403 + 404 + [[package]] 405 + name = "once_cell_polyfill" 406 + version = "1.70.2" 407 + source = "registry+https://github.com/rust-lang/crates.io-index" 408 + checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" 409 + 410 + [[package]] 411 + name = "oorandom" 412 + version = "11.1.5" 413 + source = "registry+https://github.com/rust-lang/crates.io-index" 414 + checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" 415 + 416 + [[package]] 417 + name = "page_size" 418 + version = "0.6.0" 419 + source = "registry+https://github.com/rust-lang/crates.io-index" 420 + checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" 421 + dependencies = [ 422 + "libc", 423 + "winapi", 424 + ] 425 + 426 + [[package]] 427 + name = "plotters" 428 + version = "0.3.7" 429 + source = "registry+https://github.com/rust-lang/crates.io-index" 430 + checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" 431 + dependencies = [ 432 + "num-traits", 433 + "plotters-backend", 434 + "plotters-svg", 435 + "wasm-bindgen", 436 + "web-sys", 437 + ] 438 + 439 + [[package]] 440 + name = "plotters-backend" 441 + version = "0.3.7" 442 + source = "registry+https://github.com/rust-lang/crates.io-index" 443 + checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" 444 + 445 + [[package]] 446 + name = "plotters-svg" 447 + version = "0.3.7" 448 + source = "registry+https://github.com/rust-lang/crates.io-index" 449 + checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" 450 + dependencies = [ 451 + "plotters-backend", 452 + ] 453 + 454 + [[package]] 455 + name = "portable-atomic" 456 + version = "1.11.1" 457 + source = "registry+https://github.com/rust-lang/crates.io-index" 458 + checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" 459 + 460 + [[package]] 461 + name = "portable-atomic-util" 462 + version = "0.2.4" 463 + source = "registry+https://github.com/rust-lang/crates.io-index" 464 + checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" 465 + dependencies = [ 466 + "portable-atomic", 467 + ] 468 + 469 + [[package]] 470 + name = "proc-macro2" 471 + version = "1.0.103" 472 + source = "registry+https://github.com/rust-lang/crates.io-index" 473 + checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" 474 + dependencies = [ 475 + "unicode-ident", 476 + ] 477 + 478 + [[package]] 479 + name = "quote" 480 + version = "1.0.42" 481 + source = "registry+https://github.com/rust-lang/crates.io-index" 482 + checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" 483 + dependencies = [ 484 + "proc-macro2", 485 + ] 486 + 487 + [[package]] 488 + name = "rayon" 489 + version = "1.11.0" 490 + source = "registry+https://github.com/rust-lang/crates.io-index" 491 + checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" 492 + dependencies = [ 493 + "either", 494 + "rayon-core", 495 + ] 496 + 497 + [[package]] 498 + name = "rayon-core" 499 + version = "1.13.0" 500 + source = "registry+https://github.com/rust-lang/crates.io-index" 501 + checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" 502 + dependencies = [ 503 + "crossbeam-deque", 504 + "crossbeam-utils", 505 + ] 506 + 507 + [[package]] 508 + name = "regex" 509 + version = "1.12.2" 510 + source = "registry+https://github.com/rust-lang/crates.io-index" 511 + checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" 512 + dependencies = [ 513 + "aho-corasick", 514 + "memchr", 515 + "regex-automata", 516 + "regex-syntax", 517 + ] 518 + 519 + [[package]] 520 + name = "regex-automata" 521 + version = "0.4.13" 522 + source = "registry+https://github.com/rust-lang/crates.io-index" 523 + checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" 524 + dependencies = [ 525 + "aho-corasick", 526 + "memchr", 527 + "regex-syntax", 528 + ] 529 + 530 + [[package]] 531 + name = "regex-syntax" 532 + version = "0.8.8" 533 + source = "registry+https://github.com/rust-lang/crates.io-index" 534 + checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" 535 + 536 + [[package]] 537 + name = "rustversion" 538 + version = "1.0.22" 539 + source = "registry+https://github.com/rust-lang/crates.io-index" 540 + checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 541 + 542 + [[package]] 543 + name = "ryu" 544 + version = "1.0.20" 545 + source = "registry+https://github.com/rust-lang/crates.io-index" 546 + checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 547 + 548 + [[package]] 549 + name = "same-file" 550 + version = "1.0.6" 551 + source = "registry+https://github.com/rust-lang/crates.io-index" 552 + checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 553 + dependencies = [ 554 + "winapi-util", 555 + ] 556 + 557 + [[package]] 558 + name = "serde" 559 + version = "1.0.228" 560 + source = "registry+https://github.com/rust-lang/crates.io-index" 561 + checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" 562 + dependencies = [ 563 + "serde_core", 564 + "serde_derive", 565 + ] 566 + 567 + [[package]] 568 + name = "serde_core" 569 + version = "1.0.228" 570 + source = "registry+https://github.com/rust-lang/crates.io-index" 571 + checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" 572 + dependencies = [ 573 + "serde_derive", 574 + ] 575 + 576 + [[package]] 577 + name = "serde_derive" 578 + version = "1.0.228" 579 + source = "registry+https://github.com/rust-lang/crates.io-index" 580 + checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 581 + dependencies = [ 582 + "proc-macro2", 583 + "quote", 584 + "syn", 585 + ] 586 + 587 + [[package]] 588 + name = "serde_json" 589 + version = "1.0.145" 590 + source = "registry+https://github.com/rust-lang/crates.io-index" 591 + checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" 592 + dependencies = [ 593 + "itoa", 594 + "memchr", 595 + "ryu", 596 + "serde", 597 + "serde_core", 598 + ] 599 + 600 + [[package]] 601 + name = "shlex" 602 + version = "1.3.0" 603 + source = "registry+https://github.com/rust-lang/crates.io-index" 604 + checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 605 + 606 + [[package]] 607 + name = "syn" 608 + version = "2.0.111" 609 + source = "registry+https://github.com/rust-lang/crates.io-index" 610 + checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" 611 + dependencies = [ 612 + "proc-macro2", 613 + "quote", 614 + "unicode-ident", 615 + ] 616 + 617 + [[package]] 618 + name = "tinytemplate" 619 + version = "1.2.1" 620 + source = "registry+https://github.com/rust-lang/crates.io-index" 621 + checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" 622 + dependencies = [ 623 + "serde", 624 + "serde_json", 625 + ] 626 + 627 + [[package]] 628 + name = "unicode-ident" 629 + version = "1.0.22" 630 + source = "registry+https://github.com/rust-lang/crates.io-index" 631 + checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" 632 + 633 + [[package]] 634 + name = "utf8parse" 635 + version = "0.2.2" 636 + source = "registry+https://github.com/rust-lang/crates.io-index" 637 + checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 638 + 639 + [[package]] 640 + name = "walkdir" 641 + version = "2.5.0" 642 + source = "registry+https://github.com/rust-lang/crates.io-index" 643 + checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 644 + dependencies = [ 645 + "same-file", 646 + "winapi-util", 647 + ] 648 + 649 + [[package]] 650 + name = "wasm-bindgen" 651 + version = "0.2.106" 652 + source = "registry+https://github.com/rust-lang/crates.io-index" 653 + checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" 654 + dependencies = [ 655 + "cfg-if", 656 + "once_cell", 657 + "rustversion", 658 + "wasm-bindgen-macro", 659 + "wasm-bindgen-shared", 660 + ] 661 + 662 + [[package]] 663 + name = "wasm-bindgen-macro" 664 + version = "0.2.106" 665 + source = "registry+https://github.com/rust-lang/crates.io-index" 666 + checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" 667 + dependencies = [ 668 + "quote", 669 + "wasm-bindgen-macro-support", 670 + ] 671 + 672 + [[package]] 673 + name = "wasm-bindgen-macro-support" 674 + version = "0.2.106" 675 + source = "registry+https://github.com/rust-lang/crates.io-index" 676 + checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" 677 + dependencies = [ 678 + "bumpalo", 679 + "proc-macro2", 680 + "quote", 681 + "syn", 682 + "wasm-bindgen-shared", 683 + ] 684 + 685 + [[package]] 686 + name = "wasm-bindgen-shared" 687 + version = "0.2.106" 688 + source = "registry+https://github.com/rust-lang/crates.io-index" 689 + checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" 690 + dependencies = [ 691 + "unicode-ident", 692 + ] 693 + 694 + [[package]] 695 + name = "web-sys" 696 + version = "0.3.83" 697 + source = "registry+https://github.com/rust-lang/crates.io-index" 698 + checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" 699 + dependencies = [ 700 + "js-sys", 701 + "wasm-bindgen", 702 + ] 703 + 704 + [[package]] 705 + name = "winapi" 706 + version = "0.3.9" 707 + source = "registry+https://github.com/rust-lang/crates.io-index" 708 + checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 709 + dependencies = [ 710 + "winapi-i686-pc-windows-gnu", 711 + "winapi-x86_64-pc-windows-gnu", 712 + ] 713 + 714 + [[package]] 715 + name = "winapi-i686-pc-windows-gnu" 716 + version = "0.4.0" 717 + source = "registry+https://github.com/rust-lang/crates.io-index" 718 + checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 719 + 720 + [[package]] 721 + name = "winapi-util" 722 + version = "0.1.11" 723 + source = "registry+https://github.com/rust-lang/crates.io-index" 724 + checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" 725 + dependencies = [ 726 + "windows-sys", 727 + ] 728 + 729 + [[package]] 730 + name = "winapi-x86_64-pc-windows-gnu" 731 + version = "0.4.0" 732 + source = "registry+https://github.com/rust-lang/crates.io-index" 733 + checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 734 + 735 + [[package]] 736 + name = "windows-link" 737 + version = "0.2.1" 738 + source = "registry+https://github.com/rust-lang/crates.io-index" 739 + checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 740 + 741 + [[package]] 742 + name = "windows-sys" 743 + version = "0.61.2" 744 + source = "registry+https://github.com/rust-lang/crates.io-index" 745 + checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 746 + dependencies = [ 747 + "windows-link", 748 + ] 749 + 750 + [[package]] 751 + name = "zerocopy" 752 + version = "0.8.31" 753 + source = "registry+https://github.com/rust-lang/crates.io-index" 754 + checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" 755 + dependencies = [ 756 + "zerocopy-derive", 757 + ] 758 + 759 + [[package]] 760 + name = "zerocopy-derive" 761 + version = "0.8.31" 762 + source = "registry+https://github.com/rust-lang/crates.io-index" 763 + checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" 764 + dependencies = [ 765 + "proc-macro2", 766 + "quote", 767 + "syn", 768 + ]
+9
2025/Cargo.toml
··· 6 6 [dependencies] 7 7 anyhow = "1.0.100" 8 8 atoi_simd = "0.17.0" 9 + env_logger = "0.11.8" 10 + log = "0.4.29" 9 11 memchr = "2.7.6" 12 + 13 + [dev-dependencies] 14 + criterion = { version = "0.8.0", features = ["html_reports"] } 15 + 16 + [[bench]] 17 + name = "bench" 18 + harness = false
+42
2025/benches/bench.rs
··· 1 + use aoc2025::days; 2 + use criterion::{Criterion, criterion_group, criterion_main}; 3 + use std::{hint::black_box, time::Duration}; 4 + 5 + static INPUT: &str = include_str!("../inputs/day2.txt"); 6 + 7 + fn bench_parse(c: &mut Criterion) { 8 + c.bench_function("parse", |b| { 9 + b.iter(|| days::two::parse(black_box(INPUT.as_bytes()))) 10 + }); 11 + } 12 + 13 + fn bench_part_a(c: &mut Criterion) { 14 + let input = days::two::parse(INPUT.as_bytes()); 15 + c.bench_function("part_a", |b| { 16 + b.iter(|| days::two::part_a(black_box(input.clone()))) 17 + }); 18 + } 19 + 20 + fn bench_part_b(c: &mut Criterion) { 21 + let input = days::two::parse(INPUT.as_bytes()); 22 + c.bench_function("part_b", |b| { 23 + b.iter(|| days::two::part_b(black_box(input.clone()))) 24 + }); 25 + } 26 + 27 + fn bench_all(c: &mut Criterion) { 28 + c.bench_function("main", |b| { 29 + let input = days::two::parse(INPUT.as_bytes()); 30 + b.iter(|| { 31 + days::two::part_a(black_box(input.clone())); 32 + days::two::part_b(black_box(input.clone())); 33 + }) 34 + }); 35 + } 36 + 37 + criterion_group! { 38 + name = benches; 39 + config = Criterion::default().sample_size(100).measurement_time(Duration::from_secs(30)).plotting_backend(criterion::PlottingBackend::Plotters); 40 + targets = bench_parse, bench_part_a, bench_part_b, bench_all 41 + } 42 + criterion_main!(benches);
+64 -38
2025/src/days/two/mod.rs
··· 4 4 crate::run("Gift Shop", "inputs/day2.txt", parse, part_a, part_b) 5 5 } 6 6 7 - fn parse(input: &[u8]) -> Vec<u64> { 7 + pub fn parse(input: &[u8]) -> Vec<u64> { 8 8 let mut out = Vec::new(); 9 9 let mut start = 0; 10 10 11 11 while start < input.len() { 12 - let end = match memchr::memchr2(b',', b'\n', &input[start..]) { 13 - Some(index) => start + index, 14 - None => input.len(), 15 - }; 12 + let rest = &input[start..]; 13 + let end = memchr::memchr2(b',', b'\n', rest).map_or(input.len(), |i| start + i); 16 14 let range = &input[start..end]; 17 15 18 - let [min, max, ..] = range 19 - .split(|&b| b == b'-') 20 - .map(|s| parse_u64::<u64>(s).unwrap()) 21 - .collect::<Vec<_>>()[..] 22 - else { 23 - panic!("invalid input") 24 - }; 16 + let dash = memchr::memchr(b'-', range).expect("invalid input: missing '-'"); 17 + 18 + let min = parse_u64::<u64>(&range[..dash]).expect("invalid input: invalid min"); 19 + let max = parse_u64::<u64>(&range[dash + 1..]).expect("invalid input: invalid max"); 25 20 26 - for i in min.clone()..=max.clone() { 27 - out.push(i); 28 - } 29 - start += range.len() + 1; 21 + out.extend(min..=max); 22 + start = if end == input.len() { end } else { end + 1 }; 30 23 } 31 24 32 25 out 33 26 } 34 27 35 - fn part_a(input: Vec<u64>) -> usize { 36 - println!("{}", input.len()); 28 + pub fn part_a(input: Vec<u64>) -> usize { 37 29 input.iter().fold(0, |acc, x| { 38 30 acc + if is_valid_id_a(x.clone()) { 39 31 0usize ··· 43 35 }) 44 36 } 45 37 38 + fn num_digits(mut n: u64) -> u32 { 39 + if n == 0 { 40 + return 1; 41 + } 42 + let mut digits = 0; 43 + while n > 0 { 44 + digits += 1; 45 + n /= 10; 46 + } 47 + digits 48 + } 49 + 46 50 fn is_valid_id_a(id: u64) -> bool { 47 51 // invalid ID's are identifiable due to them being made up from some sequences being repeated 48 52 // eg: 11 -> [1, 1] invalid 49 53 // eg: 123123 -> [123, 123] invalid 50 54 // eg: 123456 -> [123456] valid 51 - let id_str = id.to_string(); 52 - let id_len = id_str.len(); 55 + let digits = num_digits(id); 56 + if digits % 2 == 1 { 57 + return true; 58 + } 53 59 54 - let (left, right) = id_str.split_at(id_len / 2); 60 + let half = digits / 2; 61 + let div = 10u64.pow(half); 62 + 63 + let left = id / div; 64 + let right = id % div; 55 65 left != right 56 66 } 57 67 58 - fn is_valid_id_b(id: &u64) -> bool { 68 + fn is_valid_id_b(mut id: u64) -> bool { 59 69 // invalid ID's are identifiable due to them being made up from some sequences being repeated 60 70 // eg: 11 -> [1, 1] invalid 61 71 // eg: 123123 -> [123, 123] invalid 62 72 // eg: 121212 -> [12, 12, 12] invalid 63 73 // eg: 111 -> [1, 1, 1] invalid 64 74 // eg: 123456 -> [123456] valid 65 - let id_str = id.to_string(); 66 - let id_len = id_str.len(); 67 - let mut needle = id_str.chars().next().unwrap().to_string(); 75 + let mut digits = [0u8; 10]; 76 + let mut len = 0; 68 77 69 - while needle.len() != id_str.len() { 70 - if id_len % needle.len() != 0 { 71 - needle.push(id_str.chars().nth(needle.len()).unwrap()); 72 - continue; 73 - }; 74 - let count = id_str.matches(&needle).count(); 75 - if count * needle.len() == id_len { 76 - return false; 77 - }; 78 - needle.push(id_str.chars().nth(needle.len()).unwrap()); 78 + if id == 0 { 79 + digits[0] = b'0'; 80 + len = 1; 81 + } else { 82 + while id > 0 { 83 + digits[len] = b'0' + (id % 10) as u8; 84 + len += 1; 85 + id /= 10; 86 + } 87 + digits[..len].reverse(); 88 + } 89 + 90 + if len < 2 { 91 + return true; 92 + } 93 + 94 + let mut pi = [0usize; 10]; 95 + for i in 1..len { 96 + let mut j = pi[i - 1]; 97 + while j > 0 && digits[i] != digits[j] { 98 + j = pi[j - 1]; 99 + } 100 + if digits[i] == digits[j] { 101 + j += 1; 102 + } 103 + pi[i] = j; 79 104 } 80 105 81 - true 106 + let smallest_period = len - pi[len - 1]; 107 + !(smallest_period < len && len % smallest_period == 0) 82 108 } 83 109 84 - fn part_b(input: Vec<u64>) -> usize { 110 + pub fn part_b(input: Vec<u64>) -> usize { 85 111 input.iter().fold(0, |acc, x| { 86 - acc + if is_valid_id_b(x) { 112 + acc + if is_valid_id_b(x.clone()) { 87 113 0usize 88 114 } else { 89 115 *x as usize
+18 -16
2025/src/lib.rs
··· 3 3 use std::{fmt::Display, fs, time::Instant}; 4 4 5 5 use anyhow::Result; 6 + use log::info; 6 7 7 8 pub fn run<T, P, A, B, RA, RB>( 8 9 name: &str, ··· 19 20 RA: Display, 20 21 RB: Display, 21 22 { 23 + let _ = env_logger::try_init(); 22 24 let file = &fs::read_to_string(input_path)?; 23 25 let bytes = file.as_bytes(); 24 26 let label_parse = format!("{name} Parse"); 25 27 let parse_start = Instant::now(); 26 28 let input = parse(bytes); 27 29 let parse_elapsed = parse_start.elapsed(); 28 - println!("{label_parse}"); 29 - println!("{}", "-".repeat(label_parse.len())); 30 - println!("Parse time: {:?}", parse_elapsed); 30 + info!("{label_parse}"); 31 + info!("{}", "-".repeat(label_parse.len())); 32 + info!("Parse time: {:?}", parse_elapsed); 31 33 32 - println!(); 34 + info!(""); 33 35 34 36 let label_a = format!("{name} Part A"); 35 - println!("{label_a}"); 36 - println!("{}", "-".repeat(label_a.len())); 37 + info!("{label_a}"); 38 + info!("{}", "-".repeat(label_a.len())); 37 39 let part_a_start = Instant::now(); 38 - println!("Part A answer: {}", part_a(input.clone())); 40 + info!("Part A answer: {}", part_a(input.clone())); 39 41 let part_a_elapsed = part_a_start.elapsed(); 40 - println!("Part A time: {:?}", part_a_elapsed); 42 + info!("Part A time: {:?}", part_a_elapsed); 41 43 42 - println!(); 44 + info!(""); 43 45 44 46 let label_b = format!("{name} Part B"); 45 - println!("{label_b}"); 46 - println!("{}", "-".repeat(label_b.len())); 47 + info!("{label_b}"); 48 + info!("{}", "-".repeat(label_b.len())); 47 49 let part_b_start = Instant::now(); 48 - println!("Part B answer: {}", part_b(input.clone())); 50 + info!("Part B answer: {}", part_b(input.clone())); 49 51 let part_b_elapsed = part_b_start.elapsed(); 50 - println!("Part B time: {:?}", part_b_elapsed); 52 + info!("Part B time: {:?}", part_b_elapsed); 51 53 52 - println!(); 54 + info!(""); 53 55 54 - println!("Challenge time: {:?}", part_a_elapsed + part_b_elapsed); 55 - println!( 56 + info!("Challenge time: {:?}", part_a_elapsed + part_b_elapsed); 57 + info!( 56 58 "Total time: {:?}", 57 59 part_a_elapsed + part_b_elapsed + parse_elapsed 58 60 );
-19
2025/src/main.rs
··· 1 - #![feature(test)] 2 - extern crate test; 3 - 4 1 fn main() -> anyhow::Result<()> { 5 2 aoc2025::days::two::main()?; 6 3 Ok(()) 7 4 } 8 - 9 - #[cfg(test)] 10 - mod tests { 11 - use aoc2025::days; 12 - use test::Bencher; 13 - 14 - #[bench] 15 - fn day1(b: &mut Bencher) { 16 - b.iter(|| days::one::main()) 17 - } 18 - 19 - #[bench] 20 - fn day2(b: &mut Bencher) { 21 - b.iter(|| days::two::main()) 22 - } 23 - }