Kata machine practice.
0

Configure Feed

Select the types of activity you want to include in your feed.

Initial commit

Chris Dill (Jan 18, 2026, 4:45 PM UTC) 8ae9352a

+3898
+1
.gitignore
··· 1 + node_modules/
+11
README.md
··· 1 + # kata-machine 2 + 3 + Kata machine practice. 4 + 5 + https://frontendmasters.com/courses/algorithms/ 6 + 7 + https://github.com/ThePrimeagen/kata-machine 8 + 9 + 1. `pnpm install` 10 + 11 + 2. `pnpm run test`
+20
package.json
··· 1 + { 2 + "name": "test-kata-machine", 3 + "version": "0.0.1", 4 + "scripts": { 5 + "check": "tsc --noEmit", 6 + "test": "vitest", 7 + "format": "prettier --write ./src" 8 + }, 9 + "devDependencies": { 10 + "vite": "^7.0.5", 11 + "vitest": "^3.2.4" 12 + }, 13 + "dependencies": { 14 + "prettier": "^3.6.2", 15 + "ts-node": "^10.9.2", 16 + "tsconfig-paths": "^4.2.0", 17 + "tsconfig-paths-jest": "^0.0.1", 18 + "typescript": "^5.8.3" 19 + } 20 + }
+1666
pnpm-lock.yaml
··· 1 + lockfileVersion: "9.0" 2 + 3 + settings: 4 + autoInstallPeers: true 5 + excludeLinksFromLockfile: false 6 + 7 + importers: 8 + .: 9 + dependencies: 10 + prettier: 11 + specifier: ^3.6.2 12 + version: 3.6.2 13 + ts-node: 14 + specifier: ^10.9.2 15 + version: 10.9.2(@swc/core@1.13.2)(@types/node@24.1.0)(typescript@5.8.3) 16 + tsconfig-paths: 17 + specifier: ^4.2.0 18 + version: 4.2.0 19 + tsconfig-paths-jest: 20 + specifier: ^0.0.1 21 + version: 0.0.1 22 + typescript: 23 + specifier: ^5.8.3 24 + version: 5.8.3 25 + devDependencies: 26 + vite: 27 + specifier: ^7.0.5 28 + version: 7.0.5(@types/node@24.1.0) 29 + vitest: 30 + specifier: ^3.2.4 31 + version: 3.2.4(@types/node@24.1.0) 32 + 33 + packages: 34 + "@cspotcode/source-map-support@0.8.1": 35 + resolution: 36 + { 37 + integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==, 38 + } 39 + engines: { node: ">=12" } 40 + 41 + "@esbuild/aix-ppc64@0.25.8": 42 + resolution: 43 + { 44 + integrity: sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==, 45 + } 46 + engines: { node: ">=18" } 47 + cpu: [ppc64] 48 + os: [aix] 49 + 50 + "@esbuild/android-arm64@0.25.8": 51 + resolution: 52 + { 53 + integrity: sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==, 54 + } 55 + engines: { node: ">=18" } 56 + cpu: [arm64] 57 + os: [android] 58 + 59 + "@esbuild/android-arm@0.25.8": 60 + resolution: 61 + { 62 + integrity: sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==, 63 + } 64 + engines: { node: ">=18" } 65 + cpu: [arm] 66 + os: [android] 67 + 68 + "@esbuild/android-x64@0.25.8": 69 + resolution: 70 + { 71 + integrity: sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==, 72 + } 73 + engines: { node: ">=18" } 74 + cpu: [x64] 75 + os: [android] 76 + 77 + "@esbuild/darwin-arm64@0.25.8": 78 + resolution: 79 + { 80 + integrity: sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==, 81 + } 82 + engines: { node: ">=18" } 83 + cpu: [arm64] 84 + os: [darwin] 85 + 86 + "@esbuild/darwin-x64@0.25.8": 87 + resolution: 88 + { 89 + integrity: sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==, 90 + } 91 + engines: { node: ">=18" } 92 + cpu: [x64] 93 + os: [darwin] 94 + 95 + "@esbuild/freebsd-arm64@0.25.8": 96 + resolution: 97 + { 98 + integrity: sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==, 99 + } 100 + engines: { node: ">=18" } 101 + cpu: [arm64] 102 + os: [freebsd] 103 + 104 + "@esbuild/freebsd-x64@0.25.8": 105 + resolution: 106 + { 107 + integrity: sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==, 108 + } 109 + engines: { node: ">=18" } 110 + cpu: [x64] 111 + os: [freebsd] 112 + 113 + "@esbuild/linux-arm64@0.25.8": 114 + resolution: 115 + { 116 + integrity: sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==, 117 + } 118 + engines: { node: ">=18" } 119 + cpu: [arm64] 120 + os: [linux] 121 + 122 + "@esbuild/linux-arm@0.25.8": 123 + resolution: 124 + { 125 + integrity: sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==, 126 + } 127 + engines: { node: ">=18" } 128 + cpu: [arm] 129 + os: [linux] 130 + 131 + "@esbuild/linux-ia32@0.25.8": 132 + resolution: 133 + { 134 + integrity: sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==, 135 + } 136 + engines: { node: ">=18" } 137 + cpu: [ia32] 138 + os: [linux] 139 + 140 + "@esbuild/linux-loong64@0.25.8": 141 + resolution: 142 + { 143 + integrity: sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==, 144 + } 145 + engines: { node: ">=18" } 146 + cpu: [loong64] 147 + os: [linux] 148 + 149 + "@esbuild/linux-mips64el@0.25.8": 150 + resolution: 151 + { 152 + integrity: sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==, 153 + } 154 + engines: { node: ">=18" } 155 + cpu: [mips64el] 156 + os: [linux] 157 + 158 + "@esbuild/linux-ppc64@0.25.8": 159 + resolution: 160 + { 161 + integrity: sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==, 162 + } 163 + engines: { node: ">=18" } 164 + cpu: [ppc64] 165 + os: [linux] 166 + 167 + "@esbuild/linux-riscv64@0.25.8": 168 + resolution: 169 + { 170 + integrity: sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==, 171 + } 172 + engines: { node: ">=18" } 173 + cpu: [riscv64] 174 + os: [linux] 175 + 176 + "@esbuild/linux-s390x@0.25.8": 177 + resolution: 178 + { 179 + integrity: sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==, 180 + } 181 + engines: { node: ">=18" } 182 + cpu: [s390x] 183 + os: [linux] 184 + 185 + "@esbuild/linux-x64@0.25.8": 186 + resolution: 187 + { 188 + integrity: sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==, 189 + } 190 + engines: { node: ">=18" } 191 + cpu: [x64] 192 + os: [linux] 193 + 194 + "@esbuild/netbsd-arm64@0.25.8": 195 + resolution: 196 + { 197 + integrity: sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==, 198 + } 199 + engines: { node: ">=18" } 200 + cpu: [arm64] 201 + os: [netbsd] 202 + 203 + "@esbuild/netbsd-x64@0.25.8": 204 + resolution: 205 + { 206 + integrity: sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==, 207 + } 208 + engines: { node: ">=18" } 209 + cpu: [x64] 210 + os: [netbsd] 211 + 212 + "@esbuild/openbsd-arm64@0.25.8": 213 + resolution: 214 + { 215 + integrity: sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==, 216 + } 217 + engines: { node: ">=18" } 218 + cpu: [arm64] 219 + os: [openbsd] 220 + 221 + "@esbuild/openbsd-x64@0.25.8": 222 + resolution: 223 + { 224 + integrity: sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==, 225 + } 226 + engines: { node: ">=18" } 227 + cpu: [x64] 228 + os: [openbsd] 229 + 230 + "@esbuild/openharmony-arm64@0.25.8": 231 + resolution: 232 + { 233 + integrity: sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==, 234 + } 235 + engines: { node: ">=18" } 236 + cpu: [arm64] 237 + os: [openharmony] 238 + 239 + "@esbuild/sunos-x64@0.25.8": 240 + resolution: 241 + { 242 + integrity: sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==, 243 + } 244 + engines: { node: ">=18" } 245 + cpu: [x64] 246 + os: [sunos] 247 + 248 + "@esbuild/win32-arm64@0.25.8": 249 + resolution: 250 + { 251 + integrity: sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==, 252 + } 253 + engines: { node: ">=18" } 254 + cpu: [arm64] 255 + os: [win32] 256 + 257 + "@esbuild/win32-ia32@0.25.8": 258 + resolution: 259 + { 260 + integrity: sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==, 261 + } 262 + engines: { node: ">=18" } 263 + cpu: [ia32] 264 + os: [win32] 265 + 266 + "@esbuild/win32-x64@0.25.8": 267 + resolution: 268 + { 269 + integrity: sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==, 270 + } 271 + engines: { node: ">=18" } 272 + cpu: [x64] 273 + os: [win32] 274 + 275 + "@jridgewell/resolve-uri@3.1.2": 276 + resolution: 277 + { 278 + integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, 279 + } 280 + engines: { node: ">=6.0.0" } 281 + 282 + "@jridgewell/sourcemap-codec@1.5.4": 283 + resolution: 284 + { 285 + integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==, 286 + } 287 + 288 + "@jridgewell/trace-mapping@0.3.9": 289 + resolution: 290 + { 291 + integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, 292 + } 293 + 294 + "@rollup/rollup-android-arm-eabi@4.45.1": 295 + resolution: 296 + { 297 + integrity: sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==, 298 + } 299 + cpu: [arm] 300 + os: [android] 301 + 302 + "@rollup/rollup-android-arm64@4.45.1": 303 + resolution: 304 + { 305 + integrity: sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==, 306 + } 307 + cpu: [arm64] 308 + os: [android] 309 + 310 + "@rollup/rollup-darwin-arm64@4.45.1": 311 + resolution: 312 + { 313 + integrity: sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==, 314 + } 315 + cpu: [arm64] 316 + os: [darwin] 317 + 318 + "@rollup/rollup-darwin-x64@4.45.1": 319 + resolution: 320 + { 321 + integrity: sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==, 322 + } 323 + cpu: [x64] 324 + os: [darwin] 325 + 326 + "@rollup/rollup-freebsd-arm64@4.45.1": 327 + resolution: 328 + { 329 + integrity: sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==, 330 + } 331 + cpu: [arm64] 332 + os: [freebsd] 333 + 334 + "@rollup/rollup-freebsd-x64@4.45.1": 335 + resolution: 336 + { 337 + integrity: sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==, 338 + } 339 + cpu: [x64] 340 + os: [freebsd] 341 + 342 + "@rollup/rollup-linux-arm-gnueabihf@4.45.1": 343 + resolution: 344 + { 345 + integrity: sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==, 346 + } 347 + cpu: [arm] 348 + os: [linux] 349 + 350 + "@rollup/rollup-linux-arm-musleabihf@4.45.1": 351 + resolution: 352 + { 353 + integrity: sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==, 354 + } 355 + cpu: [arm] 356 + os: [linux] 357 + 358 + "@rollup/rollup-linux-arm64-gnu@4.45.1": 359 + resolution: 360 + { 361 + integrity: sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==, 362 + } 363 + cpu: [arm64] 364 + os: [linux] 365 + 366 + "@rollup/rollup-linux-arm64-musl@4.45.1": 367 + resolution: 368 + { 369 + integrity: sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==, 370 + } 371 + cpu: [arm64] 372 + os: [linux] 373 + 374 + "@rollup/rollup-linux-loongarch64-gnu@4.45.1": 375 + resolution: 376 + { 377 + integrity: sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==, 378 + } 379 + cpu: [loong64] 380 + os: [linux] 381 + 382 + "@rollup/rollup-linux-powerpc64le-gnu@4.45.1": 383 + resolution: 384 + { 385 + integrity: sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==, 386 + } 387 + cpu: [ppc64] 388 + os: [linux] 389 + 390 + "@rollup/rollup-linux-riscv64-gnu@4.45.1": 391 + resolution: 392 + { 393 + integrity: sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==, 394 + } 395 + cpu: [riscv64] 396 + os: [linux] 397 + 398 + "@rollup/rollup-linux-riscv64-musl@4.45.1": 399 + resolution: 400 + { 401 + integrity: sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==, 402 + } 403 + cpu: [riscv64] 404 + os: [linux] 405 + 406 + "@rollup/rollup-linux-s390x-gnu@4.45.1": 407 + resolution: 408 + { 409 + integrity: sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==, 410 + } 411 + cpu: [s390x] 412 + os: [linux] 413 + 414 + "@rollup/rollup-linux-x64-gnu@4.45.1": 415 + resolution: 416 + { 417 + integrity: sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==, 418 + } 419 + cpu: [x64] 420 + os: [linux] 421 + 422 + "@rollup/rollup-linux-x64-musl@4.45.1": 423 + resolution: 424 + { 425 + integrity: sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==, 426 + } 427 + cpu: [x64] 428 + os: [linux] 429 + 430 + "@rollup/rollup-win32-arm64-msvc@4.45.1": 431 + resolution: 432 + { 433 + integrity: sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==, 434 + } 435 + cpu: [arm64] 436 + os: [win32] 437 + 438 + "@rollup/rollup-win32-ia32-msvc@4.45.1": 439 + resolution: 440 + { 441 + integrity: sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==, 442 + } 443 + cpu: [ia32] 444 + os: [win32] 445 + 446 + "@rollup/rollup-win32-x64-msvc@4.45.1": 447 + resolution: 448 + { 449 + integrity: sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==, 450 + } 451 + cpu: [x64] 452 + os: [win32] 453 + 454 + "@swc/core-darwin-arm64@1.13.2": 455 + resolution: 456 + { 457 + integrity: sha512-44p7ivuLSGFJ15Vly4ivLJjg3ARo4879LtEBAabcHhSZygpmkP8eyjyWxrH3OxkY1eRZSIJe8yRZPFw4kPXFPw==, 458 + } 459 + engines: { node: ">=10" } 460 + cpu: [arm64] 461 + os: [darwin] 462 + 463 + "@swc/core-darwin-x64@1.13.2": 464 + resolution: 465 + { 466 + integrity: sha512-Lb9EZi7X2XDAVmuUlBm2UvVAgSCbD3qKqDCxSI4jEOddzVOpNCnyZ/xEampdngUIyDDhhJLYU9duC+Mcsv5Y+A==, 467 + } 468 + engines: { node: ">=10" } 469 + cpu: [x64] 470 + os: [darwin] 471 + 472 + "@swc/core-linux-arm-gnueabihf@1.13.2": 473 + resolution: 474 + { 475 + integrity: sha512-9TDe/92ee1x57x+0OqL1huG4BeljVx0nWW4QOOxp8CCK67Rpc/HHl2wciJ0Kl9Dxf2NvpNtkPvqj9+BUmM9WVA==, 476 + } 477 + engines: { node: ">=10" } 478 + cpu: [arm] 479 + os: [linux] 480 + 481 + "@swc/core-linux-arm64-gnu@1.13.2": 482 + resolution: 483 + { 484 + integrity: sha512-KJUSl56DBk7AWMAIEcU83zl5mg3vlQYhLELhjwRFkGFMvghQvdqQ3zFOYa4TexKA7noBZa3C8fb24rI5sw9Exg==, 485 + } 486 + engines: { node: ">=10" } 487 + cpu: [arm64] 488 + os: [linux] 489 + 490 + "@swc/core-linux-arm64-musl@1.13.2": 491 + resolution: 492 + { 493 + integrity: sha512-teU27iG1oyWpNh9CzcGQ48ClDRt/RCem7mYO7ehd2FY102UeTws2+OzLESS1TS1tEZipq/5xwx3FzbVgiolCiQ==, 494 + } 495 + engines: { node: ">=10" } 496 + cpu: [arm64] 497 + os: [linux] 498 + 499 + "@swc/core-linux-x64-gnu@1.13.2": 500 + resolution: 501 + { 502 + integrity: sha512-dRPsyPyqpLD0HMRCRpYALIh4kdOir8pPg4AhNQZLehKowigRd30RcLXGNVZcc31Ua8CiPI4QSgjOIxK+EQe4LQ==, 503 + } 504 + engines: { node: ">=10" } 505 + cpu: [x64] 506 + os: [linux] 507 + 508 + "@swc/core-linux-x64-musl@1.13.2": 509 + resolution: 510 + { 511 + integrity: sha512-CCxETW+KkYEQDqz1SYC15YIWYheqFC+PJVOW76Maa/8yu8Biw+HTAcblKf2isrlUtK8RvrQN94v3UXkC2NzCEw==, 512 + } 513 + engines: { node: ">=10" } 514 + cpu: [x64] 515 + os: [linux] 516 + 517 + "@swc/core-win32-arm64-msvc@1.13.2": 518 + resolution: 519 + { 520 + integrity: sha512-Wv/QTA6PjyRLlmKcN6AmSI4jwSMRl0VTLGs57PHTqYRwwfwd7y4s2fIPJVBNbAlXd795dOEP6d/bGSQSyhOX3A==, 521 + } 522 + engines: { node: ">=10" } 523 + cpu: [arm64] 524 + os: [win32] 525 + 526 + "@swc/core-win32-ia32-msvc@1.13.2": 527 + resolution: 528 + { 529 + integrity: sha512-PuCdtNynEkUNbUXX/wsyUC+t4mamIU5y00lT5vJcAvco3/r16Iaxl5UCzhXYaWZSNVZMzPp9qN8NlSL8M5pPxw==, 530 + } 531 + engines: { node: ">=10" } 532 + cpu: [ia32] 533 + os: [win32] 534 + 535 + "@swc/core-win32-x64-msvc@1.13.2": 536 + resolution: 537 + { 538 + integrity: sha512-qlmMkFZJus8cYuBURx1a3YAG2G7IW44i+FEYV5/32ylKkzGNAr9tDJSA53XNnNXkAB5EXSPsOz7bn5C3JlEtdQ==, 539 + } 540 + engines: { node: ">=10" } 541 + cpu: [x64] 542 + os: [win32] 543 + 544 + "@swc/core@1.13.2": 545 + resolution: 546 + { 547 + integrity: sha512-YWqn+0IKXDhqVLKoac4v2tV6hJqB/wOh8/Br8zjqeqBkKa77Qb0Kw2i7LOFzjFNZbZaPH6AlMGlBwNrxaauaAg==, 548 + } 549 + engines: { node: ">=10" } 550 + peerDependencies: 551 + "@swc/helpers": ">=0.5.17" 552 + peerDependenciesMeta: 553 + "@swc/helpers": 554 + optional: true 555 + 556 + "@swc/counter@0.1.3": 557 + resolution: 558 + { 559 + integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==, 560 + } 561 + 562 + "@swc/types@0.1.23": 563 + resolution: 564 + { 565 + integrity: sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==, 566 + } 567 + 568 + "@tsconfig/node10@1.0.11": 569 + resolution: 570 + { 571 + integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==, 572 + } 573 + 574 + "@tsconfig/node12@1.0.11": 575 + resolution: 576 + { 577 + integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==, 578 + } 579 + 580 + "@tsconfig/node14@1.0.3": 581 + resolution: 582 + { 583 + integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==, 584 + } 585 + 586 + "@tsconfig/node16@1.0.4": 587 + resolution: 588 + { 589 + integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==, 590 + } 591 + 592 + "@types/chai@5.2.2": 593 + resolution: 594 + { 595 + integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==, 596 + } 597 + 598 + "@types/deep-eql@4.0.2": 599 + resolution: 600 + { 601 + integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==, 602 + } 603 + 604 + "@types/estree@1.0.8": 605 + resolution: 606 + { 607 + integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==, 608 + } 609 + 610 + "@types/node@24.1.0": 611 + resolution: 612 + { 613 + integrity: sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==, 614 + } 615 + 616 + "@vitest/expect@3.2.4": 617 + resolution: 618 + { 619 + integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==, 620 + } 621 + 622 + "@vitest/mocker@3.2.4": 623 + resolution: 624 + { 625 + integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==, 626 + } 627 + peerDependencies: 628 + msw: ^2.4.9 629 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 630 + peerDependenciesMeta: 631 + msw: 632 + optional: true 633 + vite: 634 + optional: true 635 + 636 + "@vitest/pretty-format@3.2.4": 637 + resolution: 638 + { 639 + integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==, 640 + } 641 + 642 + "@vitest/runner@3.2.4": 643 + resolution: 644 + { 645 + integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==, 646 + } 647 + 648 + "@vitest/snapshot@3.2.4": 649 + resolution: 650 + { 651 + integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==, 652 + } 653 + 654 + "@vitest/spy@3.2.4": 655 + resolution: 656 + { 657 + integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==, 658 + } 659 + 660 + "@vitest/utils@3.2.4": 661 + resolution: 662 + { 663 + integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==, 664 + } 665 + 666 + acorn-walk@8.3.4: 667 + resolution: 668 + { 669 + integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==, 670 + } 671 + engines: { node: ">=0.4.0" } 672 + 673 + acorn@8.15.0: 674 + resolution: 675 + { 676 + integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==, 677 + } 678 + engines: { node: ">=0.4.0" } 679 + hasBin: true 680 + 681 + arg@4.1.3: 682 + resolution: 683 + { 684 + integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==, 685 + } 686 + 687 + assertion-error@2.0.1: 688 + resolution: 689 + { 690 + integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==, 691 + } 692 + engines: { node: ">=12" } 693 + 694 + cac@6.7.14: 695 + resolution: 696 + { 697 + integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==, 698 + } 699 + engines: { node: ">=8" } 700 + 701 + chai@5.2.1: 702 + resolution: 703 + { 704 + integrity: sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==, 705 + } 706 + engines: { node: ">=18" } 707 + 708 + check-error@2.1.1: 709 + resolution: 710 + { 711 + integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==, 712 + } 713 + engines: { node: ">= 16" } 714 + 715 + create-require@1.1.1: 716 + resolution: 717 + { 718 + integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==, 719 + } 720 + 721 + debug@4.4.1: 722 + resolution: 723 + { 724 + integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==, 725 + } 726 + engines: { node: ">=6.0" } 727 + peerDependencies: 728 + supports-color: "*" 729 + peerDependenciesMeta: 730 + supports-color: 731 + optional: true 732 + 733 + deep-eql@5.0.2: 734 + resolution: 735 + { 736 + integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==, 737 + } 738 + engines: { node: ">=6" } 739 + 740 + diff@4.0.2: 741 + resolution: 742 + { 743 + integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==, 744 + } 745 + engines: { node: ">=0.3.1" } 746 + 747 + es-module-lexer@1.7.0: 748 + resolution: 749 + { 750 + integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==, 751 + } 752 + 753 + esbuild@0.25.8: 754 + resolution: 755 + { 756 + integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==, 757 + } 758 + engines: { node: ">=18" } 759 + hasBin: true 760 + 761 + estree-walker@3.0.3: 762 + resolution: 763 + { 764 + integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==, 765 + } 766 + 767 + expect-type@1.2.2: 768 + resolution: 769 + { 770 + integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==, 771 + } 772 + engines: { node: ">=12.0.0" } 773 + 774 + fdir@6.4.6: 775 + resolution: 776 + { 777 + integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==, 778 + } 779 + peerDependencies: 780 + picomatch: ^3 || ^4 781 + peerDependenciesMeta: 782 + picomatch: 783 + optional: true 784 + 785 + fsevents@2.3.3: 786 + resolution: 787 + { 788 + integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, 789 + } 790 + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } 791 + os: [darwin] 792 + 793 + js-tokens@9.0.1: 794 + resolution: 795 + { 796 + integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==, 797 + } 798 + 799 + json5@2.2.3: 800 + resolution: 801 + { 802 + integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, 803 + } 804 + engines: { node: ">=6" } 805 + hasBin: true 806 + 807 + loupe@3.1.4: 808 + resolution: 809 + { 810 + integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==, 811 + } 812 + 813 + magic-string@0.30.17: 814 + resolution: 815 + { 816 + integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==, 817 + } 818 + 819 + make-error@1.3.6: 820 + resolution: 821 + { 822 + integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==, 823 + } 824 + 825 + minimist@1.2.8: 826 + resolution: 827 + { 828 + integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, 829 + } 830 + 831 + ms@2.1.3: 832 + resolution: 833 + { 834 + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, 835 + } 836 + 837 + nanoid@3.3.11: 838 + resolution: 839 + { 840 + integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==, 841 + } 842 + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } 843 + hasBin: true 844 + 845 + pathe@2.0.3: 846 + resolution: 847 + { 848 + integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, 849 + } 850 + 851 + pathval@2.0.1: 852 + resolution: 853 + { 854 + integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==, 855 + } 856 + engines: { node: ">= 14.16" } 857 + 858 + picocolors@1.1.1: 859 + resolution: 860 + { 861 + integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, 862 + } 863 + 864 + picomatch@4.0.3: 865 + resolution: 866 + { 867 + integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==, 868 + } 869 + engines: { node: ">=12" } 870 + 871 + postcss@8.5.6: 872 + resolution: 873 + { 874 + integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==, 875 + } 876 + engines: { node: ^10 || ^12 || >=14 } 877 + 878 + prettier@3.6.2: 879 + resolution: 880 + { 881 + integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==, 882 + } 883 + engines: { node: ">=14" } 884 + hasBin: true 885 + 886 + rollup@4.45.1: 887 + resolution: 888 + { 889 + integrity: sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==, 890 + } 891 + engines: { node: ">=18.0.0", npm: ">=8.0.0" } 892 + hasBin: true 893 + 894 + siginfo@2.0.0: 895 + resolution: 896 + { 897 + integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==, 898 + } 899 + 900 + source-map-js@1.2.1: 901 + resolution: 902 + { 903 + integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, 904 + } 905 + engines: { node: ">=0.10.0" } 906 + 907 + stackback@0.0.2: 908 + resolution: 909 + { 910 + integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==, 911 + } 912 + 913 + std-env@3.9.0: 914 + resolution: 915 + { 916 + integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==, 917 + } 918 + 919 + strip-bom@3.0.0: 920 + resolution: 921 + { 922 + integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, 923 + } 924 + engines: { node: ">=4" } 925 + 926 + strip-literal@3.0.0: 927 + resolution: 928 + { 929 + integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==, 930 + } 931 + 932 + tinybench@2.9.0: 933 + resolution: 934 + { 935 + integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==, 936 + } 937 + 938 + tinyexec@0.3.2: 939 + resolution: 940 + { 941 + integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==, 942 + } 943 + 944 + tinyglobby@0.2.14: 945 + resolution: 946 + { 947 + integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==, 948 + } 949 + engines: { node: ">=12.0.0" } 950 + 951 + tinypool@1.1.1: 952 + resolution: 953 + { 954 + integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==, 955 + } 956 + engines: { node: ^18.0.0 || >=20.0.0 } 957 + 958 + tinyrainbow@2.0.0: 959 + resolution: 960 + { 961 + integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==, 962 + } 963 + engines: { node: ">=14.0.0" } 964 + 965 + tinyspy@4.0.3: 966 + resolution: 967 + { 968 + integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==, 969 + } 970 + engines: { node: ">=14.0.0" } 971 + 972 + ts-node@10.9.2: 973 + resolution: 974 + { 975 + integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==, 976 + } 977 + hasBin: true 978 + peerDependencies: 979 + "@swc/core": ">=1.2.50" 980 + "@swc/wasm": ">=1.2.50" 981 + "@types/node": "*" 982 + typescript: ">=2.7" 983 + peerDependenciesMeta: 984 + "@swc/core": 985 + optional: true 986 + "@swc/wasm": 987 + optional: true 988 + 989 + tsconfig-paths-jest@0.0.1: 990 + resolution: 991 + { 992 + integrity: sha512-YKhUKqbteklNppC2NqL7dv1cWF8eEobgHVD5kjF1y9Q4ocqpBiaDlYslQ9eMhtbqIPRrA68RIEXqknEjlxdwxw==, 993 + } 994 + 995 + tsconfig-paths@4.2.0: 996 + resolution: 997 + { 998 + integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==, 999 + } 1000 + engines: { node: ">=6" } 1001 + 1002 + typescript@5.8.3: 1003 + resolution: 1004 + { 1005 + integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==, 1006 + } 1007 + engines: { node: ">=14.17" } 1008 + hasBin: true 1009 + 1010 + undici-types@7.8.0: 1011 + resolution: 1012 + { 1013 + integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==, 1014 + } 1015 + 1016 + v8-compile-cache-lib@3.0.1: 1017 + resolution: 1018 + { 1019 + integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==, 1020 + } 1021 + 1022 + vite-node@3.2.4: 1023 + resolution: 1024 + { 1025 + integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==, 1026 + } 1027 + engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } 1028 + hasBin: true 1029 + 1030 + vite@7.0.5: 1031 + resolution: 1032 + { 1033 + integrity: sha512-1mncVwJxy2C9ThLwz0+2GKZyEXuC3MyWtAAlNftlZZXZDP3AJt5FmwcMit/IGGaNZ8ZOB2BNO/HFUB+CpN0NQw==, 1034 + } 1035 + engines: { node: ^20.19.0 || >=22.12.0 } 1036 + hasBin: true 1037 + peerDependencies: 1038 + "@types/node": ^20.19.0 || >=22.12.0 1039 + jiti: ">=1.21.0" 1040 + less: ^4.0.0 1041 + lightningcss: ^1.21.0 1042 + sass: ^1.70.0 1043 + sass-embedded: ^1.70.0 1044 + stylus: ">=0.54.8" 1045 + sugarss: ^5.0.0 1046 + terser: ^5.16.0 1047 + tsx: ^4.8.1 1048 + yaml: ^2.4.2 1049 + peerDependenciesMeta: 1050 + "@types/node": 1051 + optional: true 1052 + jiti: 1053 + optional: true 1054 + less: 1055 + optional: true 1056 + lightningcss: 1057 + optional: true 1058 + sass: 1059 + optional: true 1060 + sass-embedded: 1061 + optional: true 1062 + stylus: 1063 + optional: true 1064 + sugarss: 1065 + optional: true 1066 + terser: 1067 + optional: true 1068 + tsx: 1069 + optional: true 1070 + yaml: 1071 + optional: true 1072 + 1073 + vitest@3.2.4: 1074 + resolution: 1075 + { 1076 + integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==, 1077 + } 1078 + engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } 1079 + hasBin: true 1080 + peerDependencies: 1081 + "@edge-runtime/vm": "*" 1082 + "@types/debug": ^4.1.12 1083 + "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 1084 + "@vitest/browser": 3.2.4 1085 + "@vitest/ui": 3.2.4 1086 + happy-dom: "*" 1087 + jsdom: "*" 1088 + peerDependenciesMeta: 1089 + "@edge-runtime/vm": 1090 + optional: true 1091 + "@types/debug": 1092 + optional: true 1093 + "@types/node": 1094 + optional: true 1095 + "@vitest/browser": 1096 + optional: true 1097 + "@vitest/ui": 1098 + optional: true 1099 + happy-dom: 1100 + optional: true 1101 + jsdom: 1102 + optional: true 1103 + 1104 + why-is-node-running@2.3.0: 1105 + resolution: 1106 + { 1107 + integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==, 1108 + } 1109 + engines: { node: ">=8" } 1110 + hasBin: true 1111 + 1112 + yn@3.1.1: 1113 + resolution: 1114 + { 1115 + integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==, 1116 + } 1117 + engines: { node: ">=6" } 1118 + 1119 + snapshots: 1120 + "@cspotcode/source-map-support@0.8.1": 1121 + dependencies: 1122 + "@jridgewell/trace-mapping": 0.3.9 1123 + 1124 + "@esbuild/aix-ppc64@0.25.8": 1125 + optional: true 1126 + 1127 + "@esbuild/android-arm64@0.25.8": 1128 + optional: true 1129 + 1130 + "@esbuild/android-arm@0.25.8": 1131 + optional: true 1132 + 1133 + "@esbuild/android-x64@0.25.8": 1134 + optional: true 1135 + 1136 + "@esbuild/darwin-arm64@0.25.8": 1137 + optional: true 1138 + 1139 + "@esbuild/darwin-x64@0.25.8": 1140 + optional: true 1141 + 1142 + "@esbuild/freebsd-arm64@0.25.8": 1143 + optional: true 1144 + 1145 + "@esbuild/freebsd-x64@0.25.8": 1146 + optional: true 1147 + 1148 + "@esbuild/linux-arm64@0.25.8": 1149 + optional: true 1150 + 1151 + "@esbuild/linux-arm@0.25.8": 1152 + optional: true 1153 + 1154 + "@esbuild/linux-ia32@0.25.8": 1155 + optional: true 1156 + 1157 + "@esbuild/linux-loong64@0.25.8": 1158 + optional: true 1159 + 1160 + "@esbuild/linux-mips64el@0.25.8": 1161 + optional: true 1162 + 1163 + "@esbuild/linux-ppc64@0.25.8": 1164 + optional: true 1165 + 1166 + "@esbuild/linux-riscv64@0.25.8": 1167 + optional: true 1168 + 1169 + "@esbuild/linux-s390x@0.25.8": 1170 + optional: true 1171 + 1172 + "@esbuild/linux-x64@0.25.8": 1173 + optional: true 1174 + 1175 + "@esbuild/netbsd-arm64@0.25.8": 1176 + optional: true 1177 + 1178 + "@esbuild/netbsd-x64@0.25.8": 1179 + optional: true 1180 + 1181 + "@esbuild/openbsd-arm64@0.25.8": 1182 + optional: true 1183 + 1184 + "@esbuild/openbsd-x64@0.25.8": 1185 + optional: true 1186 + 1187 + "@esbuild/openharmony-arm64@0.25.8": 1188 + optional: true 1189 + 1190 + "@esbuild/sunos-x64@0.25.8": 1191 + optional: true 1192 + 1193 + "@esbuild/win32-arm64@0.25.8": 1194 + optional: true 1195 + 1196 + "@esbuild/win32-ia32@0.25.8": 1197 + optional: true 1198 + 1199 + "@esbuild/win32-x64@0.25.8": 1200 + optional: true 1201 + 1202 + "@jridgewell/resolve-uri@3.1.2": {} 1203 + 1204 + "@jridgewell/sourcemap-codec@1.5.4": {} 1205 + 1206 + "@jridgewell/trace-mapping@0.3.9": 1207 + dependencies: 1208 + "@jridgewell/resolve-uri": 3.1.2 1209 + "@jridgewell/sourcemap-codec": 1.5.4 1210 + 1211 + "@rollup/rollup-android-arm-eabi@4.45.1": 1212 + optional: true 1213 + 1214 + "@rollup/rollup-android-arm64@4.45.1": 1215 + optional: true 1216 + 1217 + "@rollup/rollup-darwin-arm64@4.45.1": 1218 + optional: true 1219 + 1220 + "@rollup/rollup-darwin-x64@4.45.1": 1221 + optional: true 1222 + 1223 + "@rollup/rollup-freebsd-arm64@4.45.1": 1224 + optional: true 1225 + 1226 + "@rollup/rollup-freebsd-x64@4.45.1": 1227 + optional: true 1228 + 1229 + "@rollup/rollup-linux-arm-gnueabihf@4.45.1": 1230 + optional: true 1231 + 1232 + "@rollup/rollup-linux-arm-musleabihf@4.45.1": 1233 + optional: true 1234 + 1235 + "@rollup/rollup-linux-arm64-gnu@4.45.1": 1236 + optional: true 1237 + 1238 + "@rollup/rollup-linux-arm64-musl@4.45.1": 1239 + optional: true 1240 + 1241 + "@rollup/rollup-linux-loongarch64-gnu@4.45.1": 1242 + optional: true 1243 + 1244 + "@rollup/rollup-linux-powerpc64le-gnu@4.45.1": 1245 + optional: true 1246 + 1247 + "@rollup/rollup-linux-riscv64-gnu@4.45.1": 1248 + optional: true 1249 + 1250 + "@rollup/rollup-linux-riscv64-musl@4.45.1": 1251 + optional: true 1252 + 1253 + "@rollup/rollup-linux-s390x-gnu@4.45.1": 1254 + optional: true 1255 + 1256 + "@rollup/rollup-linux-x64-gnu@4.45.1": 1257 + optional: true 1258 + 1259 + "@rollup/rollup-linux-x64-musl@4.45.1": 1260 + optional: true 1261 + 1262 + "@rollup/rollup-win32-arm64-msvc@4.45.1": 1263 + optional: true 1264 + 1265 + "@rollup/rollup-win32-ia32-msvc@4.45.1": 1266 + optional: true 1267 + 1268 + "@rollup/rollup-win32-x64-msvc@4.45.1": 1269 + optional: true 1270 + 1271 + "@swc/core-darwin-arm64@1.13.2": 1272 + optional: true 1273 + 1274 + "@swc/core-darwin-x64@1.13.2": 1275 + optional: true 1276 + 1277 + "@swc/core-linux-arm-gnueabihf@1.13.2": 1278 + optional: true 1279 + 1280 + "@swc/core-linux-arm64-gnu@1.13.2": 1281 + optional: true 1282 + 1283 + "@swc/core-linux-arm64-musl@1.13.2": 1284 + optional: true 1285 + 1286 + "@swc/core-linux-x64-gnu@1.13.2": 1287 + optional: true 1288 + 1289 + "@swc/core-linux-x64-musl@1.13.2": 1290 + optional: true 1291 + 1292 + "@swc/core-win32-arm64-msvc@1.13.2": 1293 + optional: true 1294 + 1295 + "@swc/core-win32-ia32-msvc@1.13.2": 1296 + optional: true 1297 + 1298 + "@swc/core-win32-x64-msvc@1.13.2": 1299 + optional: true 1300 + 1301 + "@swc/core@1.13.2": 1302 + dependencies: 1303 + "@swc/counter": 0.1.3 1304 + "@swc/types": 0.1.23 1305 + optionalDependencies: 1306 + "@swc/core-darwin-arm64": 1.13.2 1307 + "@swc/core-darwin-x64": 1.13.2 1308 + "@swc/core-linux-arm-gnueabihf": 1.13.2 1309 + "@swc/core-linux-arm64-gnu": 1.13.2 1310 + "@swc/core-linux-arm64-musl": 1.13.2 1311 + "@swc/core-linux-x64-gnu": 1.13.2 1312 + "@swc/core-linux-x64-musl": 1.13.2 1313 + "@swc/core-win32-arm64-msvc": 1.13.2 1314 + "@swc/core-win32-ia32-msvc": 1.13.2 1315 + "@swc/core-win32-x64-msvc": 1.13.2 1316 + optional: true 1317 + 1318 + "@swc/counter@0.1.3": 1319 + optional: true 1320 + 1321 + "@swc/types@0.1.23": 1322 + dependencies: 1323 + "@swc/counter": 0.1.3 1324 + optional: true 1325 + 1326 + "@tsconfig/node10@1.0.11": {} 1327 + 1328 + "@tsconfig/node12@1.0.11": {} 1329 + 1330 + "@tsconfig/node14@1.0.3": {} 1331 + 1332 + "@tsconfig/node16@1.0.4": {} 1333 + 1334 + "@types/chai@5.2.2": 1335 + dependencies: 1336 + "@types/deep-eql": 4.0.2 1337 + 1338 + "@types/deep-eql@4.0.2": {} 1339 + 1340 + "@types/estree@1.0.8": {} 1341 + 1342 + "@types/node@24.1.0": 1343 + dependencies: 1344 + undici-types: 7.8.0 1345 + 1346 + "@vitest/expect@3.2.4": 1347 + dependencies: 1348 + "@types/chai": 5.2.2 1349 + "@vitest/spy": 3.2.4 1350 + "@vitest/utils": 3.2.4 1351 + chai: 5.2.1 1352 + tinyrainbow: 2.0.0 1353 + 1354 + "@vitest/mocker@3.2.4(vite@7.0.5(@types/node@24.1.0))": 1355 + dependencies: 1356 + "@vitest/spy": 3.2.4 1357 + estree-walker: 3.0.3 1358 + magic-string: 0.30.17 1359 + optionalDependencies: 1360 + vite: 7.0.5(@types/node@24.1.0) 1361 + 1362 + "@vitest/pretty-format@3.2.4": 1363 + dependencies: 1364 + tinyrainbow: 2.0.0 1365 + 1366 + "@vitest/runner@3.2.4": 1367 + dependencies: 1368 + "@vitest/utils": 3.2.4 1369 + pathe: 2.0.3 1370 + strip-literal: 3.0.0 1371 + 1372 + "@vitest/snapshot@3.2.4": 1373 + dependencies: 1374 + "@vitest/pretty-format": 3.2.4 1375 + magic-string: 0.30.17 1376 + pathe: 2.0.3 1377 + 1378 + "@vitest/spy@3.2.4": 1379 + dependencies: 1380 + tinyspy: 4.0.3 1381 + 1382 + "@vitest/utils@3.2.4": 1383 + dependencies: 1384 + "@vitest/pretty-format": 3.2.4 1385 + loupe: 3.1.4 1386 + tinyrainbow: 2.0.0 1387 + 1388 + acorn-walk@8.3.4: 1389 + dependencies: 1390 + acorn: 8.15.0 1391 + 1392 + acorn@8.15.0: {} 1393 + 1394 + arg@4.1.3: {} 1395 + 1396 + assertion-error@2.0.1: {} 1397 + 1398 + cac@6.7.14: {} 1399 + 1400 + chai@5.2.1: 1401 + dependencies: 1402 + assertion-error: 2.0.1 1403 + check-error: 2.1.1 1404 + deep-eql: 5.0.2 1405 + loupe: 3.1.4 1406 + pathval: 2.0.1 1407 + 1408 + check-error@2.1.1: {} 1409 + 1410 + create-require@1.1.1: {} 1411 + 1412 + debug@4.4.1: 1413 + dependencies: 1414 + ms: 2.1.3 1415 + 1416 + deep-eql@5.0.2: {} 1417 + 1418 + diff@4.0.2: {} 1419 + 1420 + es-module-lexer@1.7.0: {} 1421 + 1422 + esbuild@0.25.8: 1423 + optionalDependencies: 1424 + "@esbuild/aix-ppc64": 0.25.8 1425 + "@esbuild/android-arm": 0.25.8 1426 + "@esbuild/android-arm64": 0.25.8 1427 + "@esbuild/android-x64": 0.25.8 1428 + "@esbuild/darwin-arm64": 0.25.8 1429 + "@esbuild/darwin-x64": 0.25.8 1430 + "@esbuild/freebsd-arm64": 0.25.8 1431 + "@esbuild/freebsd-x64": 0.25.8 1432 + "@esbuild/linux-arm": 0.25.8 1433 + "@esbuild/linux-arm64": 0.25.8 1434 + "@esbuild/linux-ia32": 0.25.8 1435 + "@esbuild/linux-loong64": 0.25.8 1436 + "@esbuild/linux-mips64el": 0.25.8 1437 + "@esbuild/linux-ppc64": 0.25.8 1438 + "@esbuild/linux-riscv64": 0.25.8 1439 + "@esbuild/linux-s390x": 0.25.8 1440 + "@esbuild/linux-x64": 0.25.8 1441 + "@esbuild/netbsd-arm64": 0.25.8 1442 + "@esbuild/netbsd-x64": 0.25.8 1443 + "@esbuild/openbsd-arm64": 0.25.8 1444 + "@esbuild/openbsd-x64": 0.25.8 1445 + "@esbuild/openharmony-arm64": 0.25.8 1446 + "@esbuild/sunos-x64": 0.25.8 1447 + "@esbuild/win32-arm64": 0.25.8 1448 + "@esbuild/win32-ia32": 0.25.8 1449 + "@esbuild/win32-x64": 0.25.8 1450 + 1451 + estree-walker@3.0.3: 1452 + dependencies: 1453 + "@types/estree": 1.0.8 1454 + 1455 + expect-type@1.2.2: {} 1456 + 1457 + fdir@6.4.6(picomatch@4.0.3): 1458 + optionalDependencies: 1459 + picomatch: 4.0.3 1460 + 1461 + fsevents@2.3.3: 1462 + optional: true 1463 + 1464 + js-tokens@9.0.1: {} 1465 + 1466 + json5@2.2.3: {} 1467 + 1468 + loupe@3.1.4: {} 1469 + 1470 + magic-string@0.30.17: 1471 + dependencies: 1472 + "@jridgewell/sourcemap-codec": 1.5.4 1473 + 1474 + make-error@1.3.6: {} 1475 + 1476 + minimist@1.2.8: {} 1477 + 1478 + ms@2.1.3: {} 1479 + 1480 + nanoid@3.3.11: {} 1481 + 1482 + pathe@2.0.3: {} 1483 + 1484 + pathval@2.0.1: {} 1485 + 1486 + picocolors@1.1.1: {} 1487 + 1488 + picomatch@4.0.3: {} 1489 + 1490 + postcss@8.5.6: 1491 + dependencies: 1492 + nanoid: 3.3.11 1493 + picocolors: 1.1.1 1494 + source-map-js: 1.2.1 1495 + 1496 + prettier@3.6.2: {} 1497 + 1498 + rollup@4.45.1: 1499 + dependencies: 1500 + "@types/estree": 1.0.8 1501 + optionalDependencies: 1502 + "@rollup/rollup-android-arm-eabi": 4.45.1 1503 + "@rollup/rollup-android-arm64": 4.45.1 1504 + "@rollup/rollup-darwin-arm64": 4.45.1 1505 + "@rollup/rollup-darwin-x64": 4.45.1 1506 + "@rollup/rollup-freebsd-arm64": 4.45.1 1507 + "@rollup/rollup-freebsd-x64": 4.45.1 1508 + "@rollup/rollup-linux-arm-gnueabihf": 4.45.1 1509 + "@rollup/rollup-linux-arm-musleabihf": 4.45.1 1510 + "@rollup/rollup-linux-arm64-gnu": 4.45.1 1511 + "@rollup/rollup-linux-arm64-musl": 4.45.1 1512 + "@rollup/rollup-linux-loongarch64-gnu": 4.45.1 1513 + "@rollup/rollup-linux-powerpc64le-gnu": 4.45.1 1514 + "@rollup/rollup-linux-riscv64-gnu": 4.45.1 1515 + "@rollup/rollup-linux-riscv64-musl": 4.45.1 1516 + "@rollup/rollup-linux-s390x-gnu": 4.45.1 1517 + "@rollup/rollup-linux-x64-gnu": 4.45.1 1518 + "@rollup/rollup-linux-x64-musl": 4.45.1 1519 + "@rollup/rollup-win32-arm64-msvc": 4.45.1 1520 + "@rollup/rollup-win32-ia32-msvc": 4.45.1 1521 + "@rollup/rollup-win32-x64-msvc": 4.45.1 1522 + fsevents: 2.3.3 1523 + 1524 + siginfo@2.0.0: {} 1525 + 1526 + source-map-js@1.2.1: {} 1527 + 1528 + stackback@0.0.2: {} 1529 + 1530 + std-env@3.9.0: {} 1531 + 1532 + strip-bom@3.0.0: {} 1533 + 1534 + strip-literal@3.0.0: 1535 + dependencies: 1536 + js-tokens: 9.0.1 1537 + 1538 + tinybench@2.9.0: {} 1539 + 1540 + tinyexec@0.3.2: {} 1541 + 1542 + tinyglobby@0.2.14: 1543 + dependencies: 1544 + fdir: 6.4.6(picomatch@4.0.3) 1545 + picomatch: 4.0.3 1546 + 1547 + tinypool@1.1.1: {} 1548 + 1549 + tinyrainbow@2.0.0: {} 1550 + 1551 + tinyspy@4.0.3: {} 1552 + 1553 + ts-node@10.9.2(@swc/core@1.13.2)(@types/node@24.1.0)(typescript@5.8.3): 1554 + dependencies: 1555 + "@cspotcode/source-map-support": 0.8.1 1556 + "@tsconfig/node10": 1.0.11 1557 + "@tsconfig/node12": 1.0.11 1558 + "@tsconfig/node14": 1.0.3 1559 + "@tsconfig/node16": 1.0.4 1560 + "@types/node": 24.1.0 1561 + acorn: 8.15.0 1562 + acorn-walk: 8.3.4 1563 + arg: 4.1.3 1564 + create-require: 1.1.1 1565 + diff: 4.0.2 1566 + make-error: 1.3.6 1567 + typescript: 5.8.3 1568 + v8-compile-cache-lib: 3.0.1 1569 + yn: 3.1.1 1570 + optionalDependencies: 1571 + "@swc/core": 1.13.2 1572 + 1573 + tsconfig-paths-jest@0.0.1: {} 1574 + 1575 + tsconfig-paths@4.2.0: 1576 + dependencies: 1577 + json5: 2.2.3 1578 + minimist: 1.2.8 1579 + strip-bom: 3.0.0 1580 + 1581 + typescript@5.8.3: {} 1582 + 1583 + undici-types@7.8.0: {} 1584 + 1585 + v8-compile-cache-lib@3.0.1: {} 1586 + 1587 + vite-node@3.2.4(@types/node@24.1.0): 1588 + dependencies: 1589 + cac: 6.7.14 1590 + debug: 4.4.1 1591 + es-module-lexer: 1.7.0 1592 + pathe: 2.0.3 1593 + vite: 7.0.5(@types/node@24.1.0) 1594 + transitivePeerDependencies: 1595 + - "@types/node" 1596 + - jiti 1597 + - less 1598 + - lightningcss 1599 + - sass 1600 + - sass-embedded 1601 + - stylus 1602 + - sugarss 1603 + - supports-color 1604 + - terser 1605 + - tsx 1606 + - yaml 1607 + 1608 + vite@7.0.5(@types/node@24.1.0): 1609 + dependencies: 1610 + esbuild: 0.25.8 1611 + fdir: 6.4.6(picomatch@4.0.3) 1612 + picomatch: 4.0.3 1613 + postcss: 8.5.6 1614 + rollup: 4.45.1 1615 + tinyglobby: 0.2.14 1616 + optionalDependencies: 1617 + "@types/node": 24.1.0 1618 + fsevents: 2.3.3 1619 + 1620 + vitest@3.2.4(@types/node@24.1.0): 1621 + dependencies: 1622 + "@types/chai": 5.2.2 1623 + "@vitest/expect": 3.2.4 1624 + "@vitest/mocker": 3.2.4(vite@7.0.5(@types/node@24.1.0)) 1625 + "@vitest/pretty-format": 3.2.4 1626 + "@vitest/runner": 3.2.4 1627 + "@vitest/snapshot": 3.2.4 1628 + "@vitest/spy": 3.2.4 1629 + "@vitest/utils": 3.2.4 1630 + chai: 5.2.1 1631 + debug: 4.4.1 1632 + expect-type: 1.2.2 1633 + magic-string: 0.30.17 1634 + pathe: 2.0.3 1635 + picomatch: 4.0.3 1636 + std-env: 3.9.0 1637 + tinybench: 2.9.0 1638 + tinyexec: 0.3.2 1639 + tinyglobby: 0.2.14 1640 + tinypool: 1.1.1 1641 + tinyrainbow: 2.0.0 1642 + vite: 7.0.5(@types/node@24.1.0) 1643 + vite-node: 3.2.4(@types/node@24.1.0) 1644 + why-is-node-running: 2.3.0 1645 + optionalDependencies: 1646 + "@types/node": 24.1.0 1647 + transitivePeerDependencies: 1648 + - jiti 1649 + - less 1650 + - lightningcss 1651 + - msw 1652 + - sass 1653 + - sass-embedded 1654 + - stylus 1655 + - sugarss 1656 + - supports-color 1657 + - terser 1658 + - tsx 1659 + - yaml 1660 + 1661 + why-is-node-running@2.3.0: 1662 + dependencies: 1663 + siginfo: 2.0.0 1664 + stackback: 0.0.2 1665 + 1666 + yn@3.1.1: {}
+8
prettier.config.ts
··· 1 + export default { 2 + tabWidth: 4, 3 + printWidth: 80, 4 + proseWrap: "never", 5 + trailingComma: "all", 6 + singleQuote: false, 7 + semi: true, 8 + };
+101
src/array-test.ts
··· 1 + const a: number[] = []; 2 + 3 + function time(fn: () => void): number { 4 + const now = Date.now(); 5 + fn(); 6 + return Date.now() - now; 7 + } 8 + 9 + function unshift(number: number) { 10 + for (let i = 0; i < number; ++i) { 11 + a.unshift(Math.random()); 12 + } 13 + } 14 + 15 + function shift(number: number) { 16 + for (let i = 0; i < number; ++i) { 17 + a.shift(); 18 + } 19 + } 20 + 21 + function push(number: number) { 22 + for (let i = 0; i < number; ++i) { 23 + a.push(Math.random()); 24 + } 25 + } 26 + 27 + function pop(number: number) { 28 + for (let i = 0; i < number; ++i) { 29 + a.pop(); 30 + } 31 + } 32 + 33 + function get(idx: number) { 34 + return function () { 35 + return a[idx]; 36 + }; 37 + } 38 + 39 + function push_arr(count: number) { 40 + return function () { 41 + push(count); 42 + }; 43 + } 44 + 45 + function pop_arr(count: number) { 46 + return function () { 47 + pop(count); 48 + }; 49 + } 50 + 51 + function unshift_arr(count: number) { 52 + return function () { 53 + unshift(count); 54 + }; 55 + } 56 + 57 + function shift_arr(count: number) { 58 + return function () { 59 + shift(count); 60 + }; 61 + } 62 + 63 + const tests = [10, 100, 1000, 10000, 100000, 1_000_000, 10_000_000]; 64 + console.log("Testing get"); 65 + tests.forEach((t) => { 66 + a.length = 0; 67 + push(t); 68 + console.log(t, time(get(t - 1))); 69 + }); 70 + 71 + console.log("push"); 72 + tests.forEach((t) => { 73 + a.length = 0; 74 + push(t); 75 + 76 + console.log(t, time(push_arr(1000))); 77 + }); 78 + 79 + console.log("pop"); 80 + tests.forEach((t) => { 81 + a.length = 0; 82 + push(t); 83 + 84 + console.log(t, time(pop_arr(1000))); 85 + }); 86 + 87 + console.log("unshift"); 88 + tests.forEach((t) => { 89 + a.length = 0; 90 + push(t); 91 + 92 + console.log(t, time(unshift_arr(1000))); 93 + }); 94 + 95 + console.log("shift"); 96 + tests.forEach((t) => { 97 + a.length = 0; 98 + push(t); 99 + 100 + console.log(t, time(shift_arr(1000))); 101 + });
+7
src/day1/ArrayList.test.ts
··· 1 + import ArrayList from "@code/ArrayList"; 2 + import { test_list } from "./ListTest"; 3 + 4 + test("array-list", function () { 5 + const list = new ArrayList<number>(3); 6 + test_list(list); 7 + });
+93
src/day1/ArrayList.ts
··· 1 + export default class ArrayList<T> { 2 + public length: number; 3 + private array: Array<T>; 4 + private capacity: number; 5 + 6 + constructor(capacity: number = 5) { 7 + this.capacity = capacity; 8 + this.array = []; 9 + this.array.length = this.capacity; 10 + this.length = 0; 11 + } 12 + 13 + private grow() { 14 + const old = this.array; 15 + this.capacity *= 2; 16 + this.array = []; 17 + this.array.length = this.capacity; 18 + 19 + let i = 0; 20 + for (; i < this.length; ++i) { 21 + this.array[i] = old[i]; 22 + } 23 + } 24 + 25 + // ShiftRight manages the size of the array and shifts everything 26 + // from array[idx] one to the right. Creating free space at array[idx]. 27 + private shiftRight(idx: number) { 28 + if (this.length == this.capacity) { 29 + this.grow(); 30 + } 31 + 32 + let i = this.length; 33 + for (; i > idx; --i) { 34 + this.array[i] = this.array[i - 1]; 35 + } 36 + this.length++; 37 + } 38 + 39 + // ShiftLeft manages the size of the array and shifts everything to the 40 + // right of array[idx] one to the left. Overwriting array[idx]. 41 + private ShiftLeft(idx: number) { 42 + this.length--; 43 + let i = idx; 44 + for (; i < this.length; ++i) { 45 + this.array[i] = this.array[i + 1]; 46 + } 47 + } 48 + 49 + prepend(item: T): void { 50 + this.shiftRight(0); 51 + this.array[0] = item; 52 + } 53 + 54 + insertAt(item: T, idx: number): void { 55 + this.shiftRight(idx); 56 + this.array[idx] = item; 57 + } 58 + 59 + append(item: T): void { 60 + if (this.length == this.capacity) { 61 + this.grow(); 62 + } 63 + 64 + this.array[this.length] = item; 65 + this.length++; 66 + } 67 + 68 + remove(item: T): T | undefined { 69 + let i = 0; 70 + for (; i < this.length; ++i) { 71 + if (this.array[i] == item) { 72 + break; 73 + } 74 + } 75 + 76 + // item was not found 77 + if (i == this.length) { 78 + return undefined; 79 + } 80 + 81 + return this.removeAt(i); 82 + } 83 + 84 + get(idx: number): T | undefined { 85 + return idx >= this.length ? undefined : this.array[idx]; 86 + } 87 + 88 + removeAt(idx: number): T | undefined { 89 + const item = this.get(idx); 90 + this.ShiftLeft(idx); 91 + return item; 92 + } 93 + }
+8
src/day1/BFSGraphList.test.ts
··· 1 + import bfs from "@code/BFSGraphList"; 2 + import { list2 } from "./graph"; 3 + 4 + test("bfs - graph", function () { 5 + expect(bfs(list2, 0, 6)).toEqual([0, 1, 4, 5, 6]); 6 + 7 + expect(bfs(list2, 6, 0)).toEqual(null); 8 + });
+45
src/day1/BFSGraphList.ts
··· 1 + export default function bfs( 2 + graph: WeightedAdjacencyList, 3 + source: number, 4 + needle: number, 5 + ): number[] | null { 6 + const seen = new Array(graph.length).fill(false); 7 + const prev = new Array(graph.length).fill(-1); 8 + 9 + const queue: number[] = [source]; 10 + seen[source] = true; 11 + 12 + while (queue.length > 0) { 13 + const curr = queue.shift() as number; 14 + 15 + if (curr === needle) { 16 + break; 17 + } 18 + 19 + for (const edge of graph[curr]) { 20 + const neighbor = edge.to; 21 + 22 + if (seen[neighbor]) { 23 + continue; 24 + } 25 + 26 + seen[neighbor] = true; 27 + prev[neighbor] = curr; 28 + queue.push(neighbor); 29 + } 30 + } 31 + 32 + if (!seen[needle]) { 33 + return null; 34 + } 35 + 36 + const path: number[] = []; 37 + let curr = needle; 38 + 39 + while (curr !== -1) { 40 + path.push(curr); 41 + curr = prev[curr]; 42 + } 43 + 44 + return path.reverse(); 45 + }
+8
src/day1/BFSGraphMatrix.test.ts
··· 1 + import bfs from "@code/BFSGraphMatrix"; 2 + import { matrix2 } from "./graph"; 3 + 4 + test("bfs - graph matrix", function () { 5 + expect(bfs(matrix2, 0, 6)).toEqual([0, 1, 4, 5, 6]); 6 + 7 + expect(bfs(matrix2, 6, 0)).toEqual(null); 8 + });
+43
src/day1/BFSGraphMatrix.ts
··· 1 + export default function bfs( 2 + graph: number[][], 3 + source: number, 4 + needle: number, 5 + ): number[] | null { 6 + const seen = new Array(graph.length).fill(false); 7 + const prev = new Array(graph.length).fill(-1); 8 + const q: number[] = [source]; 9 + seen[source] = true; 10 + 11 + do { 12 + const curr = q.shift() as number; 13 + 14 + if (curr === needle) { 15 + break; 16 + } 17 + 18 + const adjs = graph[curr]; 19 + for (let i = 0; i < graph.length; i++) { 20 + if (adjs[i] === 0 || seen[i]) { 21 + continue; 22 + } 23 + 24 + seen[i] = true; 25 + prev[i] = curr; 26 + q.push(i); 27 + } 28 + } while (q.length); 29 + 30 + if (prev[needle] === -1) { 31 + return null; 32 + } 33 + 34 + let curr = needle; 35 + const out: number[] = []; 36 + 37 + while (prev[curr] !== -1) { 38 + out.push(curr); 39 + curr = prev[curr]; 40 + } 41 + 42 + return [source].concat(out.reverse()); 43 + }
+8
src/day1/BTBFS.test.ts
··· 1 + import bfs from "@code/BTBFS"; 2 + import { tree } from "./tree"; 3 + 4 + test("bt bfs", function () { 5 + expect(bfs(tree, 45)).toEqual(true); 6 + expect(bfs(tree, 7)).toEqual(true); 7 + expect(bfs(tree, 69)).toEqual(false); 8 + });
+20
src/day1/BTBFS.ts
··· 1 + export default function bfs(head: BinaryNode<number>, needle: number): boolean { 2 + const q: (BinaryNode<number> | null)[] = [head]; 3 + 4 + while (q.length) { 5 + const curr = q.shift() as BinaryNode<number> | undefined | null; 6 + if (!curr) { 7 + continue; 8 + } 9 + 10 + // search 11 + if (curr.value === needle) { 12 + return true; 13 + } 14 + 15 + q.push(curr.left); 16 + q.push(curr.right); 17 + } 18 + 19 + return false; 20 + }
+6
src/day1/BTInOrder.test.ts
··· 1 + import bt_in_order from "@code/BTInOrder"; 2 + import { tree } from "./tree"; 3 + 4 + test("In order", function () { 5 + expect(bt_in_order(tree)).toEqual([5, 7, 10, 15, 20, 29, 30, 45, 50, 100]); 6 + });
+17
src/day1/BTInOrder.ts
··· 1 + function walk(curr: BinaryNode<number> | null, path: number[]): number[] { 2 + if (!curr) { 3 + return path; 4 + } 5 + 6 + // recurse 7 + walk(curr.left, path); 8 + path.push(curr.value); 9 + walk(curr.right, path); 10 + 11 + // post 12 + return path; 13 + } 14 + 15 + export default function in_order_search(head: BinaryNode<number>): number[] { 16 + return walk(head, []); 17 + }
+8
src/day1/BTPostOrder.test.ts
··· 1 + import bt_post_order from "@code/BTPostOrder"; 2 + import { tree } from "./tree"; 3 + 4 + test("post order", function () { 5 + expect(bt_post_order(tree)).toEqual([ 6 + 7, 5, 15, 10, 29, 45, 30, 100, 50, 20, 7 + ]); 8 + });
+17
src/day1/BTPostOrder.ts
··· 1 + function walk(curr: BinaryNode<number> | null, path: number[]): number[] { 2 + if (!curr) { 3 + return path; 4 + } 5 + 6 + // recurse 7 + walk(curr.left, path); 8 + walk(curr.right, path); 9 + 10 + // post 11 + path.push(curr.value); 12 + return path; 13 + } 14 + 15 + export default function post_order_search(head: BinaryNode<number>): number[] { 16 + return walk(head, []); 17 + }
+6
src/day1/BTPreOrder.test.ts
··· 1 + import bt_pre_order from "@code/BTPreOrder"; 2 + import { tree } from "./tree"; 3 + 4 + test("Pre order", function () { 5 + expect(bt_pre_order(tree)).toEqual([20, 10, 5, 7, 15, 50, 30, 29, 45, 100]); 6 + });
+19
src/day1/BTPreOrder.ts
··· 1 + function walk(curr: BinaryNode<number> | null, path: number[]): number[] { 2 + if (!curr) { 3 + return path; 4 + } 5 + 6 + // pre 7 + path.push(curr.value); 8 + 9 + // recurse 10 + walk(curr.left, path); 11 + walk(curr.right, path); 12 + 13 + // post 14 + return path; 15 + } 16 + 17 + export default function pre_order_search(head: BinaryNode<number>): number[] { 18 + return walk(head, []); 19 + }
+11
src/day1/BinarySearchList.test.ts
··· 1 + import binary_fn from "@code/BinarySearchList"; 2 + 3 + test("binary search array", function () { 4 + const foo = [1, 3, 4, 69, 71, 81, 90, 99, 420, 1337, 69420]; 5 + expect(binary_fn(foo, 69)).toEqual(true); 6 + expect(binary_fn(foo, 1336)).toEqual(false); 7 + expect(binary_fn(foo, 69420)).toEqual(true); 8 + expect(binary_fn(foo, 69421)).toEqual(false); 9 + expect(binary_fn(foo, 1)).toEqual(true); 10 + expect(binary_fn(foo, 0)).toEqual(false); 11 + });
+19
src/day1/BinarySearchList.ts
··· 1 + export default function bs_list(haystack: number[], needle: number): boolean { 2 + let lo = 0; 3 + let hi = haystack.length; 4 + 5 + while (lo < hi) { 6 + const m = Math.floor(lo + (hi - lo) / 2); 7 + const v = haystack[m]; 8 + 9 + if (v === needle) { 10 + return true; 11 + } else if (v > needle) { 12 + hi = m; 13 + } else { 14 + lo = m + 1; 15 + } 16 + } 17 + 18 + return false; 19 + }
+9
src/day1/BubbleSort.test.ts
··· 1 + import bubble_sort from "@code/BubbleSort"; 2 + 3 + test("bubble-sort", function () { 4 + const arr = [9, 3, 7, 4, 69, 420, 42]; 5 + 6 + debugger; 7 + bubble_sort(arr); 8 + expect(arr).toEqual([3, 4, 7, 9, 42, 69, 420]); 9 + });
+11
src/day1/BubbleSort.ts
··· 1 + export default function bubble_sort(arr: number[]): void { 2 + for (let i = 0; i < arr.length; i++) { 3 + for (let j = 0; j < arr.length - 1 - i; j++) { 4 + if (arr[j] > arr[j + 1]) { 5 + const tmp = arr[j]; 6 + arr[j] = arr[j + 1]; 7 + arr[j + 1] = tmp; 8 + } 9 + } 10 + } 11 + }
+7
src/day1/CompareBinaryTrees.test.ts
··· 1 + import compare from "@code/CompareBinaryTrees"; 2 + import { tree, tree2 } from "./tree"; 3 + 4 + test("Compare Binary Trees", function () { 5 + expect(compare(tree, tree)).toEqual(true); 6 + expect(compare(tree, tree2)).toEqual(false); 7 + });
+21
src/day1/CompareBinaryTrees.ts
··· 1 + export default function compare( 2 + a: BinaryNode<number> | null, 3 + b: BinaryNode<number> | null, 4 + ): boolean { 5 + // structual check 6 + if (a === null && b === null) { 7 + return true; 8 + } 9 + 10 + // structual check 11 + if (a === null || b === null) { 12 + return false; 13 + } 14 + 15 + // value check 16 + if (a?.value !== b?.value) { 17 + return false; 18 + } 19 + 20 + return compare(a.left, b.left) && compare(a.right, b.right); 21 + }
+8
src/day1/DFSGraphList.test.ts
··· 1 + import dfs from "@code/DFSGraphList"; 2 + import { list2 } from "./graph"; 3 + 4 + test("dfs - graph", function () { 5 + expect(dfs(list2, 0, 6)).toEqual([0, 1, 4, 5, 6]); 6 + 7 + expect(dfs(list2, 6, 0)).toEqual(null); 8 + });
+50
src/day1/DFSGraphList.ts
··· 1 + function walk( 2 + graph: WeightedAdjacencyList, 3 + curr: number, 4 + needle: number, 5 + seen: boolean[], 6 + path: number[], 7 + ): boolean { 8 + if (seen[curr]) { 9 + return false; 10 + } 11 + 12 + seen[curr] = true; 13 + 14 + // pre 15 + path.push(curr); 16 + if (curr === needle) { 17 + return true; 18 + } 19 + 20 + // recurse 21 + const list = graph[curr]; 22 + for (let i = 0; i < list.length; i++) { 23 + const edge = list[i]; 24 + 25 + if (walk(graph, edge.to, needle, seen, path)) { 26 + return true; 27 + } 28 + } 29 + 30 + // post 31 + path.pop(); 32 + 33 + return false; 34 + } 35 + 36 + export default function dfs( 37 + graph: WeightedAdjacencyList, 38 + source: number, 39 + needle: number, 40 + ): number[] | null { 41 + const seen: boolean[] = new Array(graph.length).fill(false); 42 + const path: number[] = []; 43 + walk(graph, source, needle, seen, path); 44 + 45 + if (path.length === 0) { 46 + return null; 47 + } 48 + 49 + return path; 50 + }
+8
src/day1/DFSOnBST.test.ts
··· 1 + import dfs from "@code/DFSOnBST"; 2 + import { tree } from "./tree"; 3 + 4 + test("DFS on BST", function () { 5 + expect(dfs(tree, 45)).toEqual(true); 6 + expect(dfs(tree, 7)).toEqual(true); 7 + expect(dfs(tree, 69)).toEqual(false); 8 + });
+19
src/day1/DFSOnBST.ts
··· 1 + function search(curr: BinaryNode<number> | null, needle: number): boolean { 2 + if (!curr) { 3 + return false; 4 + } 5 + 6 + if (curr.value === needle) { 7 + return true; 8 + } 9 + 10 + if (curr.value < needle) { 11 + return search(curr.right, needle); 12 + } 13 + 14 + return search(curr.left, needle); 15 + } 16 + 17 + export default function dfs(head: BinaryNode<number>, needle: number): boolean { 18 + return search(head, needle); 19 + }
+9
src/day1/DijkstraList.test.ts
··· 1 + import dijkstra_list from "@code/DijkstraList"; 2 + import { list1 } from "./graph"; 3 + 4 + test("dijkstra via adj list", function () { 5 + /// waht? 6 + // what.. 7 + // what... 8 + expect(dijkstra_list(0, 6, list1)).toEqual([0, 1, 4, 5, 6]); 9 + });
+61
src/day1/DijkstraList.ts
··· 1 + function hasUnvisited(seen: boolean[], dists: number[]): boolean { 2 + return seen.some((s, i) => !s && dists[i] < Infinity); 3 + } 4 + 5 + function getLowestUnvisited(seen: boolean[], dists: number[]): number { 6 + let idx = -1; 7 + let lowestDistance = Infinity; 8 + 9 + for (let i = 0; i < seen.length; i++) { 10 + if (seen[i]) { 11 + continue; 12 + } 13 + 14 + if (lowestDistance > dists[i]) { 15 + lowestDistance = dists[i]; 16 + idx = i; 17 + } 18 + } 19 + 20 + return idx; 21 + } 22 + 23 + export default function dijkstra_list( 24 + source: number, 25 + sink: number, 26 + arr: WeightedAdjacencyList, 27 + ): number[] { 28 + const seen = new Array(arr.length).fill(false); 29 + const prev = new Array(arr.length).fill(-1); 30 + const dists = new Array(arr.length).fill(Infinity); 31 + dists[source] = 0; 32 + 33 + while (hasUnvisited(seen, dists)) { 34 + const curr = getLowestUnvisited(seen, dists); 35 + seen[curr] = true; 36 + 37 + const adjs = arr[curr]; 38 + for (let i = 0; i < adjs.length; i++) { 39 + const edge = adjs[i]; 40 + if (seen[edge.to]) { 41 + continue; 42 + } 43 + 44 + const dist = dists[curr] + edge.weight; 45 + if (dist < dists[edge.to]) { 46 + dists[edge.to] = dist; 47 + prev[edge.to] = curr; 48 + } 49 + } 50 + } 51 + 52 + let curr = sink; 53 + const out: number[] = []; 54 + 55 + while (prev[curr] !== -1) { 56 + out.push(curr); 57 + curr = prev[curr]; 58 + } 59 + 60 + return [source].concat(out.reverse()); 61 + }
+7
src/day1/DoublyLinkedList.test.ts
··· 1 + import LinkedList from "@code/DoublyLinkedList"; 2 + import { test_list } from "./ListTest"; 3 + 4 + test("DoublyLinkedList", function () { 5 + const list = new LinkedList<number>(); 6 + test_list(list); 7 + });
+136
src/day1/DoublyLinkedList.ts
··· 1 + class Node<T> { 2 + public value: T; 3 + public prev?: Node<T>; 4 + public next?: Node<T>; 5 + } 6 + 7 + export default class DoublyLinkedList<T> { 8 + public length: number; 9 + public head?: Node<T>; 10 + public tail?: Node<T>; 11 + 12 + constructor() { 13 + this.length = 0; 14 + this.head = undefined; 15 + } 16 + 17 + prepend(item: T): void { 18 + const node = { value: item } as Node<T>; 19 + this.length++; 20 + 21 + if (!this.head) { 22 + this.head = node; 23 + this.tail = node; 24 + return; 25 + } 26 + 27 + node.next = this.head; 28 + this.head.prev = node; 29 + this.head = node; 30 + } 31 + 32 + insertAt(item: T, idx: number): void { 33 + if (idx > this.length) { 34 + throw new Error("oh no"); 35 + } else if (idx === this.length) { 36 + this.append(item); 37 + return; 38 + } else if (idx === 0) { 39 + this.prepend(item); 40 + } 41 + 42 + this.length++; 43 + const curr = this.getAt(idx) as Node<T>; 44 + const node = { value: item } as Node<T>; 45 + 46 + node.next = curr; 47 + node.prev = curr.prev; 48 + curr.prev = node; 49 + 50 + if (node.prev) { 51 + node.prev.next = node; 52 + } 53 + } 54 + 55 + append(item: T): void { 56 + const node = { value: item } as Node<T>; 57 + this.length++; 58 + 59 + if (!this.tail) { 60 + this.head = node; 61 + this.tail = node; 62 + return; 63 + } 64 + 65 + node.prev = this.tail; 66 + this.tail.next = node; 67 + this.tail = node; 68 + } 69 + 70 + remove(item: T): T | undefined { 71 + let curr = this.head; 72 + for (let i = 0; curr && i < this.length; i++) { 73 + if (curr.value === item) { 74 + break; 75 + } 76 + curr = curr.next; 77 + } 78 + 79 + if (!curr) { 80 + return undefined; 81 + } 82 + 83 + return this.removeNode(curr); 84 + } 85 + 86 + get(idx: number): T | undefined { 87 + return this.getAt(idx)?.value; 88 + } 89 + 90 + removeAt(idx: number): T | undefined { 91 + const node = this.getAt(idx); 92 + 93 + if (!node) { 94 + return undefined; 95 + } 96 + return this.removeNode(node); 97 + } 98 + 99 + private removeNode(node: Node<T>): T | undefined { 100 + this.length--; 101 + 102 + if (this.length === 0) { 103 + const out = this.head?.value; 104 + this.head = undefined; 105 + this.tail = undefined; 106 + return out; 107 + } 108 + 109 + if (node.prev) { 110 + node.prev.next = node.next; 111 + } 112 + if (node.next) { 113 + node.next.prev = node.prev; 114 + } 115 + 116 + if (node === this.head) { 117 + this.head = node.next; 118 + } 119 + if (node === this.tail) { 120 + this.tail = node.prev; 121 + } 122 + 123 + node.prev = undefined; 124 + node.next = undefined; 125 + 126 + return node.value; 127 + } 128 + 129 + private getAt(idx: number): Node<T> | undefined { 130 + let curr = this.head; 131 + for (let i = 0; curr && i < idx; i++) { 132 + curr = curr.next; 133 + } 134 + return curr; 135 + } 136 + }
+9
src/day1/InsertionSort.test.ts
··· 1 + import insertion_sort from "@code/InsertionSort"; 2 + 3 + test("insertion-sort", function () { 4 + const arr = [9, 3, 7, 4, 69, 420, 42]; 5 + debugger; 6 + // where is my debugger 7 + insertion_sort(arr); 8 + expect(arr).toEqual([3, 4, 7, 9, 42, 69, 420]); 9 + });
+13
src/day1/InsertionSort.ts
··· 1 + export default function insertion_sort(arr: number[]): void { 2 + for (let i = 1; i < arr.length; i++) { 3 + const key = arr[i]; 4 + let j = i - 1; 5 + 6 + while (j >= 0 && arr[j] > key) { 7 + arr[j + 1] = arr[j]; 8 + j--; 9 + } 10 + 11 + arr[j + 1] = key; 12 + } 13 + }
+27
src/day1/LRU.test.ts
··· 1 + import LRU from "@code/LRU"; 2 + 3 + test("LRU", function () { 4 + const lru = new LRU<string, number>(3) as ILRU<string, number>; 5 + 6 + expect(lru.get("foo")).toEqual(undefined); 7 + lru.update("foo", 69); 8 + expect(lru.get("foo")).toEqual(69); 9 + 10 + lru.update("bar", 420); 11 + expect(lru.get("bar")).toEqual(420); 12 + 13 + lru.update("baz", 1337); 14 + expect(lru.get("baz")).toEqual(1337); 15 + 16 + lru.update("ball", 69420); 17 + expect(lru.get("ball")).toEqual(69420); 18 + expect(lru.get("foo")).toEqual(undefined); 19 + expect(lru.get("bar")).toEqual(420); 20 + lru.update("foo", 69); 21 + expect(lru.get("bar")).toEqual(420); 22 + expect(lru.get("foo")).toEqual(69); 23 + 24 + // shouldn't of been deleted, but since bar was get'd, bar was added to the 25 + // front of the list, so baz became the end 26 + expect(lru.get("baz")).toEqual(undefined); 27 + });
+105
src/day1/LRU.ts
··· 1 + type Node<T> = { 2 + value: T; 3 + prev?: Node<T>; 4 + next?: Node<T>; 5 + }; 6 + 7 + function createNode<V>(value: V): Node<V> { 8 + return { value }; 9 + } 10 + 11 + export default class LRU<K, V> { 12 + private length: number; 13 + private capacity: number; 14 + private head?: Node<V>; 15 + private tail?: Node<V>; 16 + private lookup: Map<K, Node<V>>; 17 + private reverseLookup: Map<Node<V>, K>; 18 + 19 + constructor(capacity: number) { 20 + this.length = 0; 21 + this.capacity = capacity; 22 + this.head = this.tail = undefined; 23 + this.lookup = new Map<K, Node<V>>(); 24 + this.reverseLookup = new Map<Node<V>, K>(); 25 + } 26 + 27 + update(key: K, value: V): void { 28 + // check the cache for existence 29 + let node = this.lookup.get(key); 30 + if (!node) { 31 + node = createNode(value); 32 + this.length++; 33 + this.prepend(node); 34 + this.trimCache(); 35 + 36 + this.lookup.set(key, node); 37 + this.reverseLookup.set(node, key); 38 + } else { 39 + this.detach(node); 40 + this.prepend(node); 41 + node.value = value; 42 + } 43 + } 44 + 45 + get(key: K): V | undefined { 46 + // check the cache for existence 47 + const node = this.lookup.get(key); 48 + if (!node) { 49 + return undefined; 50 + } 51 + 52 + // update the value we found and move it to the front 53 + this.detach(node); 54 + this.prepend(node); 55 + 56 + // return out the value found 57 + return node.value; 58 + } 59 + 60 + private detach(node: Node<V>): void { 61 + if (node.prev) { 62 + node.prev.next = node.next; 63 + } 64 + 65 + if (node.next) { 66 + node.next.prev = node.prev; 67 + } 68 + 69 + if (this.head === node) { 70 + this.head = this.head.next; 71 + } 72 + 73 + if (this.tail === node) { 74 + this.tail = this.tail.prev; 75 + } 76 + 77 + node.next = undefined; 78 + node.prev = undefined; 79 + } 80 + 81 + private prepend(node: Node<V>): void { 82 + if (!this.head) { 83 + this.head = this.tail = node; 84 + return; 85 + } 86 + 87 + node.next = this.head; 88 + this.head.prev = node; 89 + this.head = node; 90 + } 91 + 92 + private trimCache(): void { 93 + if (this.length <= this.capacity) { 94 + return; 95 + } 96 + 97 + const tail = this.tail as Node<V>; 98 + this.detach(this.tail as Node<V>); 99 + 100 + const key = this.reverseLookup.get(tail) as K; 101 + this.lookup.delete(key); 102 + this.reverseLookup.delete(tail); 103 + this.length--; 104 + } 105 + }
+11
src/day1/LinearSearchList.test.ts
··· 1 + import linear_fn from "@code/LinearSearchList"; 2 + 3 + test("linear search array", function () { 4 + const foo = [1, 3, 4, 69, 71, 81, 90, 99, 420, 1337, 69420]; 5 + expect(linear_fn(foo, 69)).toEqual(true); 6 + expect(linear_fn(foo, 1336)).toEqual(false); 7 + expect(linear_fn(foo, 69420)).toEqual(true); 8 + expect(linear_fn(foo, 69421)).toEqual(false); 9 + expect(linear_fn(foo, 1)).toEqual(true); 10 + expect(linear_fn(foo, 0)).toEqual(false); 11 + });
+12
src/day1/LinearSearchList.ts
··· 1 + export default function linear_search( 2 + haystack: number[], 3 + needle: number, 4 + ): boolean { 5 + for (let i = 0; i < haystack.length; i++) { 6 + if (haystack[i] === needle) { 7 + return true; 8 + } 9 + } 10 + 11 + return false; 12 + }
+26
src/day1/ListTest.ts
··· 1 + export function test_list(list: List<number>): void { 2 + list.append(5); 3 + list.append(7); 4 + list.append(9); 5 + 6 + expect(list.get(2)).toEqual(9); 7 + expect(list.removeAt(1)).toEqual(7); 8 + expect(list.length).toEqual(2); 9 + 10 + list.append(11); 11 + expect(list.removeAt(1)).toEqual(9); 12 + expect(list.remove(9)).toEqual(undefined); 13 + expect(list.removeAt(0)).toEqual(5); 14 + expect(list.removeAt(0)).toEqual(11); 15 + expect(list.length).toEqual(0); 16 + 17 + list.prepend(5); 18 + list.prepend(7); 19 + list.prepend(9); 20 + 21 + expect(list.get(2)).toEqual(5); 22 + expect(list.get(0)).toEqual(9); 23 + expect(list.remove(9)).toEqual(9); 24 + expect(list.length).toEqual(2); 25 + expect(list.get(0)).toEqual(7); 26 + }
+23
src/day1/Map.test.ts
··· 1 + import MyMap from "@code/Map"; 2 + 3 + test("Map", function () { 4 + const map = new MyMap<string, number>(); 5 + map.set("foo", 55); 6 + expect(map.size()).toEqual(1); 7 + map.set("fool", 75); 8 + expect(map.size()).toEqual(2); 9 + map.set("foolish", 105); 10 + expect(map.size()).toEqual(3); 11 + map.set("bar", 69); 12 + expect(map.size()).toEqual(4); 13 + 14 + expect(map.get("bar")).toEqual(69); 15 + expect(map.get("blaz")).toEqual(undefined); 16 + 17 + map.delete("barblabr"); 18 + expect(map.size()).toEqual(4); 19 + 20 + map.delete("bar"); 21 + expect(map.size()).toEqual(3); 22 + expect(map.get("bar")).toEqual(undefined); 23 + });
+34
src/day1/Map.ts
··· 1 + export default class Map<T extends string | number, V> { 2 + private store: { [key: string]: V }; 3 + private count: number; 4 + 5 + constructor() { 6 + this.store = {}; 7 + this.count = 0; 8 + } 9 + 10 + get(key: T): V | undefined { 11 + return this.store.hasOwnProperty(key) ? this.store[key] : undefined; 12 + } 13 + 14 + set(key: T, value: V): void { 15 + if (!this.store.hasOwnProperty(key)) { 16 + this.count++; 17 + } 18 + this.store[key] = value; 19 + } 20 + 21 + delete(key: T): V | undefined { 22 + if (this.store.hasOwnProperty(key)) { 23 + const value = this.store[key]; 24 + delete this.store[key]; 25 + this.count--; 26 + return value; 27 + } 28 + return undefined; 29 + } 30 + 31 + size(): number { 32 + return this.count; 33 + } 34 + }
+44
src/day1/MazeSolver.test.ts
··· 1 + import maze_solver from "@code/MazeSolver"; 2 + 3 + test("maze solver", function () { 4 + const maze = [ 5 + "xxxxxxxxxx x", 6 + "x x x", 7 + "x x x", 8 + "x xxxxxxxx x", 9 + "x x", 10 + "x xxxxxxxxxx", 11 + ]; 12 + 13 + const mazeResult = [ 14 + { x: 10, y: 0 }, 15 + { x: 10, y: 1 }, 16 + { x: 10, y: 2 }, 17 + { x: 10, y: 3 }, 18 + { x: 10, y: 4 }, 19 + { x: 9, y: 4 }, 20 + { x: 8, y: 4 }, 21 + { x: 7, y: 4 }, 22 + { x: 6, y: 4 }, 23 + { x: 5, y: 4 }, 24 + { x: 4, y: 4 }, 25 + { x: 3, y: 4 }, 26 + { x: 2, y: 4 }, 27 + { x: 1, y: 4 }, 28 + { x: 1, y: 5 }, 29 + ]; 30 + 31 + // there is only one path through 32 + const result = maze_solver(maze, "x", { x: 10, y: 0 }, { x: 1, y: 5 }); 33 + expect(drawPath(maze, result)).toEqual(drawPath(maze, mazeResult)); 34 + }); 35 + 36 + function drawPath(data: string[], path: Point[]) { 37 + const data2 = data.map((row) => row.split("")); 38 + path.forEach((p) => { 39 + if (data2[p.y] && data2[p.y][p.x]) { 40 + data2[p.y][p.x] = "*"; 41 + } 42 + }); 43 + return data2.map((d) => d.join("")); 44 + }
+57
src/day1/MazeSolver.ts
··· 1 + export default function solve( 2 + maze: string[], 3 + wall: string, 4 + start: Point, 5 + end: Point, 6 + ): Point[] { 7 + const numRows = maze.length; 8 + const numCols = maze[0].length; 9 + const visited = new Set<string>(); 10 + const queue: { point: Point; path: Point[] }[] = []; 11 + 12 + function isValid(x: number, y: number): boolean { 13 + return ( 14 + x >= 0 && 15 + x < numCols && 16 + y >= 0 && 17 + y < numRows && 18 + maze[y][x] !== wall 19 + ); 20 + } 21 + 22 + const key = (p: Point) => `${p.x},${p.y}`; 23 + 24 + queue.push({ point: start, path: [start] }); 25 + visited.add(key(start)); 26 + 27 + const directions = [ 28 + // up 29 + { x: 0, y: -1 }, 30 + // right 31 + { x: 1, y: 0 }, 32 + // down 33 + { x: 0, y: 1 }, 34 + // left 35 + { x: -1, y: 0 }, 36 + ]; 37 + 38 + while (queue.length > 0) { 39 + const { point, path } = queue.shift()!; 40 + if (point.x === end.x && point.y === end.y) { 41 + return path; 42 + } 43 + 44 + for (const dir of directions) { 45 + const next = { x: point.x + dir.x, y: point.y + dir.y }; 46 + const nextKey = key(next); 47 + 48 + if (isValid(next.x, next.y) && !visited.has(nextKey)) { 49 + visited.add(nextKey); 50 + queue.push({ point: next, path: [...path, next] }); 51 + } 52 + } 53 + } 54 + 55 + // No path found 56 + return []; 57 + }
+7
src/day1/MergeSort.test.ts
··· 1 + import merge_sort from "@code/MergeSort"; 2 + 3 + test("merge-sort", function () { 4 + const arr = [9, 3, 7, 4, 69, 420, 42]; 5 + merge_sort(arr); 6 + expect(arr).toEqual([3, 4, 7, 9, 42, 69, 420]); 7 + });
+36
src/day1/MergeSort.ts
··· 1 + function mergeSortHelper(arr: number[], start: number, end: number): void { 2 + if (start >= end) { 3 + return; 4 + } 5 + 6 + const mid = Math.floor((start + end) / 2); 7 + 8 + mergeSortHelper(arr, start, mid); 9 + mergeSortHelper(arr, mid + 1, end); 10 + 11 + merge(arr, start, mid, end); 12 + } 13 + 14 + function merge(arr: number[], start: number, mid: number, end: number): void { 15 + const left = arr.slice(start, mid + 1); 16 + const right = arr.slice(mid + 1, end + 1); 17 + 18 + let i = 0; 19 + let j = 0; 20 + let k = start; 21 + 22 + while (i < left.length && j < right.length) { 23 + arr[k++] = left[i] <= right[j] ? left[i++] : right[j++]; 24 + } 25 + 26 + while (i < left.length) { 27 + arr[k++] = left[i++]; 28 + } 29 + while (j < right.length) { 30 + arr[k++] = right[j++]; 31 + } 32 + } 33 + 34 + export default function merge_sort(arr: number[]): void { 35 + mergeSortHelper(arr, 0, arr.length - 1); 36 + }
+28
src/day1/MinHeap.test.ts
··· 1 + import MinHeap from "@code/MinHeap"; 2 + 3 + test("min heap", function () { 4 + const heap = new MinHeap(); 5 + 6 + expect(heap.length).toEqual(0); 7 + 8 + heap.insert(5); 9 + heap.insert(3); 10 + heap.insert(69); 11 + heap.insert(420); 12 + heap.insert(4); 13 + heap.insert(1); 14 + heap.insert(8); 15 + heap.insert(7); 16 + 17 + expect(heap.length).toEqual(8); 18 + expect(heap.delete()).toEqual(1); 19 + expect(heap.delete()).toEqual(3); 20 + expect(heap.delete()).toEqual(4); 21 + expect(heap.delete()).toEqual(5); 22 + expect(heap.length).toEqual(4); 23 + expect(heap.delete()).toEqual(7); 24 + expect(heap.delete()).toEqual(8); 25 + expect(heap.delete()).toEqual(69); 26 + expect(heap.delete()).toEqual(420); 27 + expect(heap.length).toEqual(0); 28 + });
+89
src/day1/MinHeap.ts
··· 1 + export default class MinHeap { 2 + public length: number; 3 + private data: number[]; 4 + 5 + constructor() { 6 + this.data = []; 7 + this.length = 0; 8 + } 9 + 10 + insert(value: number): void { 11 + this.data[this.length] = value; 12 + this.heapifyUp(this.length); 13 + this.length++; 14 + } 15 + 16 + delete(): number { 17 + if (this.length === 0) { 18 + return -1; 19 + } 20 + 21 + const out = this.data[0]; 22 + this.length--; 23 + 24 + if (this.length === 0) { 25 + this.data = []; 26 + return out; 27 + } 28 + 29 + this.data[0] = this.data[this.length]; 30 + this.heapifyDown(0); 31 + 32 + return out; 33 + } 34 + 35 + private heapifyDown(idx: number): void { 36 + const lIdx = this.leftChild(idx); 37 + const rIdx = this.rightChild(idx); 38 + 39 + if (idx >= this.length || lIdx >= this.length) { 40 + return; 41 + } 42 + 43 + const lV = this.data[lIdx]; 44 + const rV = this.data[rIdx]; 45 + const v = this.data[idx]; 46 + 47 + if (lV > rV && v > rV) { 48 + this.data[idx] = rV; 49 + this.data[rIdx] = v; 50 + this.heapifyDown(rIdx); 51 + } else if (rV > lV && v > lV) { 52 + this.data[idx] = lV; 53 + this.data[lIdx] = v; 54 + this.heapifyDown(lIdx); 55 + } else if (lV == rV && v > rV) { 56 + this.data[idx] = rV; 57 + this.data[rIdx] = v; 58 + this.heapifyDown(rIdx); 59 + } 60 + } 61 + 62 + private heapifyUp(idx: number): void { 63 + if (idx === 0) { 64 + return; 65 + } 66 + 67 + const p = this.parent(idx); 68 + const parentV = this.data[p]; 69 + const v = this.data[idx]; 70 + 71 + if (parentV > v) { 72 + this.data[idx] = parentV; 73 + this.data[p] = v; 74 + this.heapifyUp(p); 75 + } 76 + } 77 + 78 + private parent(idx: number): number { 79 + return Math.floor((idx - 1) / 2); 80 + } 81 + 82 + private leftChild(idx: number): number { 83 + return idx * 2 + 1; 84 + } 85 + 86 + private rightChild(idx: number): number { 87 + return idx * 2 + 2; 88 + } 89 + }
+58
src/day1/PrimsAlgorithm.ts
··· 1 + export default function prims( 2 + list: WeightedAdjacencyList, 3 + ): WeightedAdjacencyList | null { 4 + const n = list.length; 5 + if (n === 0) { 6 + return null; 7 + } 8 + 9 + const inMST = new Array(n).fill(false); 10 + const mst: WeightedAdjacencyList = Array.from({ length: n }, () => []); 11 + 12 + const minEdge: { to: number; from: number; weight: number }[] = new Array( 13 + n, 14 + ).fill(null as any); 15 + minEdge[0] = { to: 0, from: -1, weight: 0 }; 16 + 17 + for (let i = 0; i < n; i++) { 18 + let u = -1; 19 + 20 + for (let v = 0; v < n; v++) { 21 + if ( 22 + !inMST[v] && 23 + (u === -1 || 24 + (minEdge[v] && minEdge[v].weight < minEdge[u].weight)) 25 + ) { 26 + u = v; 27 + } 28 + } 29 + 30 + if (u === -1 || minEdge[u] === null) { 31 + return null; 32 + } 33 + 34 + inMST[u] = true; 35 + 36 + const edge = minEdge[u]; 37 + if (edge.from !== -1) { 38 + mst[edge.from].push({ to: u, weight: edge.weight }); 39 + mst[u].push({ to: edge.from, weight: edge.weight }); 40 + } 41 + 42 + for (const neighbor of list[u]) { 43 + if ( 44 + !inMST[neighbor.to] && 45 + (!minEdge[neighbor.to] || 46 + neighbor.weight < minEdge[neighbor.to].weight) 47 + ) { 48 + minEdge[neighbor.to] = { 49 + to: neighbor.to, 50 + from: u, 51 + weight: neighbor.weight, 52 + }; 53 + } 54 + } 55 + } 56 + 57 + return mst; 58 + }
+30
src/day1/PrimsList.test.ts
··· 1 + import prims from "@code/PrimsAlgorithm"; 2 + import { list1 } from "./graph"; 3 + 4 + test("PrimsAlgorithm", function () { 5 + // there is only one right answer for this graph 6 + expect(prims(list1)).toEqual([ 7 + [ 8 + { to: 2, weight: 1 }, 9 + { to: 1, weight: 3 }, 10 + ], 11 + [ 12 + { to: 0, weight: 3 }, 13 + { to: 4, weight: 1 }, 14 + ], 15 + [{ to: 0, weight: 1 }], 16 + [{ to: 6, weight: 1 }], 17 + [ 18 + { to: 1, weight: 1 }, 19 + { to: 5, weight: 2 }, 20 + ], 21 + [ 22 + { to: 4, weight: 2 }, 23 + { to: 6, weight: 1 }, 24 + ], 25 + [ 26 + { to: 5, weight: 1 }, 27 + { to: 3, weight: 1 }, 28 + ], 29 + ]); 30 + });
+31
src/day1/Queue.test.ts
··· 1 + import Queue from "@code/Queue"; 2 + 3 + test("queue", function () { 4 + const list = new Queue<number>(); 5 + 6 + list.enqueue(5); 7 + list.enqueue(7); 8 + list.enqueue(9); 9 + 10 + expect(list.deque()).toEqual(5); 11 + expect(list.length).toEqual(2); 12 + 13 + // this must be wrong..? 14 + debugger; 15 + 16 + // i hate using debuggers 17 + list.enqueue(11); 18 + debugger; 19 + expect(list.deque()).toEqual(7); 20 + expect(list.deque()).toEqual(9); 21 + expect(list.peek()).toEqual(11); 22 + expect(list.deque()).toEqual(11); 23 + expect(list.deque()).toEqual(undefined); 24 + expect(list.length).toEqual(0); 25 + 26 + // just wanted to make sure that I could not blow up myself when i remove 27 + // everything 28 + list.enqueue(69); 29 + expect(list.peek()).toEqual(69); 30 + expect(list.length).toEqual(1); 31 + });
+50
src/day1/Queue.ts
··· 1 + type Node<T> = { 2 + value: T; 3 + next?: Node<T>; 4 + }; 5 + 6 + export default class Queue<T> { 7 + public length: number; 8 + private head?: Node<T>; 9 + private tail?: Node<T>; 10 + 11 + constructor() { 12 + this.head = undefined; 13 + this.tail = undefined; 14 + this.length = 0; 15 + } 16 + 17 + enqueue(item: T): void { 18 + const node = { value: item } as Node<T>; 19 + this.length++; 20 + if (!this.tail) { 21 + this.head = node; 22 + this.tail = node; 23 + return; 24 + } 25 + 26 + this.tail.next = node; 27 + this.tail = node; 28 + } 29 + 30 + deque(): T | undefined { 31 + if (!this.head) { 32 + return undefined; 33 + } 34 + 35 + this.length--; 36 + const head = this.head; 37 + this.head = this.head.next; 38 + head.next = undefined; 39 + 40 + if (this.length === 0) { 41 + this.tail = undefined; 42 + } 43 + 44 + return head.value; 45 + } 46 + 47 + peek(): T | undefined { 48 + return this.head?.value; 49 + } 50 + }
+9
src/day1/QuickSort.test.ts
··· 1 + import quick_sort from "@code/QuickSort"; 2 + 3 + test("quick-sort", function () { 4 + const arr = [9, 3, 7, 4, 69, 420, 42]; 5 + 6 + debugger; 7 + quick_sort(arr); 8 + expect(arr).toEqual([3, 4, 7, 9, 42, 69, 420]); 9 + });
+34
src/day1/QuickSort.ts
··· 1 + function qs(arr: number[], lo: number, hi: number): void { 2 + if (lo >= hi) { 3 + return; 4 + } 5 + 6 + const pivotIdx = partition(arr, lo, hi); 7 + 8 + qs(arr, lo, pivotIdx - 1); 9 + qs(arr, pivotIdx + 1, hi); 10 + } 11 + 12 + function partition(arr: number[], lo: number, hi: number): number { 13 + const pivot = arr[hi]; 14 + let idx = lo - 1; 15 + 16 + for (let i = lo; i < hi; i++) { 17 + if (arr[i] <= pivot) { 18 + idx++; 19 + const tmp = arr[i]; 20 + arr[i] = arr[idx]; 21 + arr[idx] = tmp; 22 + } 23 + } 24 + 25 + idx++; 26 + arr[hi] = arr[idx]; 27 + arr[idx] = pivot; 28 + 29 + return idx; 30 + } 31 + 32 + export default function quick_sort(arr: number[]): void { 33 + qs(arr, 0, arr.length - 1); 34 + }
+22
src/day1/RingBuffer.test.ts
··· 1 + import RingBuffer from "@code/RingBuffer"; 2 + 3 + test("RingBuffer", function () { 4 + const buffer = new RingBuffer<number>(); 5 + 6 + buffer.push(5); 7 + expect(buffer.pop()).toEqual(5); 8 + expect(buffer.pop()).toEqual(undefined); 9 + 10 + buffer.push(42); 11 + buffer.push(9); 12 + expect(buffer.pop()).toEqual(42); 13 + expect(buffer.pop()).toEqual(9); 14 + expect(buffer.pop()).toEqual(undefined); 15 + 16 + buffer.push(42); 17 + buffer.push(9); 18 + buffer.push(12); 19 + expect(buffer.get(2)).toEqual(12); 20 + expect(buffer.get(1)).toEqual(9); 21 + expect(buffer.get(0)).toEqual(42); 22 + });
+59
src/day1/RingBuffer.ts
··· 1 + export default class RingBuffer<T> { 2 + private items: T[] = []; 3 + private start: number = 0; 4 + private end: number = 0; 5 + private count: number = 0; 6 + 7 + constructor(initialCapacity: number = 4) { 8 + this.items = new Array<T>(initialCapacity); 9 + } 10 + 11 + public get length(): number { 12 + return this.count; 13 + } 14 + 15 + push(item: T): void { 16 + if (this.count === this.items.length) { 17 + this.resize(); 18 + } 19 + 20 + this.items[this.end] = item; 21 + this.end = (this.end + 1) % this.items.length; 22 + this.count++; 23 + } 24 + 25 + pop(): T | undefined { 26 + if (this.count === 0) { 27 + return undefined; 28 + } 29 + 30 + const item = this.items[this.start]; 31 + this.items[this.start] = undefined as any; 32 + this.start = (this.start + 1) % this.items.length; 33 + this.count--; 34 + 35 + return item; 36 + } 37 + 38 + get(idx: number): T | undefined { 39 + if (idx < 0 || idx >= this.count) { 40 + return undefined; 41 + } 42 + 43 + const realIndex = (this.start + idx) % this.items.length; 44 + return this.items[realIndex]; 45 + } 46 + 47 + private resize(): void { 48 + const newCapacity = this.items.length * 2 || 4; 49 + const newItems = new Array<T>(newCapacity); 50 + 51 + for (let i = 0; i < this.count; i++) { 52 + newItems[i] = this.get(i)!; 53 + } 54 + 55 + this.items = newItems; 56 + this.start = 0; 57 + this.end = this.count; 58 + } 59 + }
+7
src/day1/SinglyLinkedList.test.ts
··· 1 + import SinglyLinkedList from "@code/SinglyLinkedList"; 2 + import { test_list } from "./ListTest"; 3 + 4 + test("linked-list", function () { 5 + const list = new SinglyLinkedList<number>(); 6 + test_list(list); 7 + });
+138
src/day1/SinglyLinkedList.ts
··· 1 + class Node<T> { 2 + public value: T; 3 + public next?: Node<T>; 4 + 5 + constructor(t: T) { 6 + this.value = t; 7 + } 8 + } 9 + 10 + export default class SinglyLinkedList<T> { 11 + public length: number; 12 + public head?: Node<T>; 13 + public tail?: Node<T>; 14 + 15 + constructor() { 16 + this.length = 0; 17 + this.head = undefined; 18 + } 19 + 20 + prepend(item: T): void { 21 + let node = new Node<T>(item); 22 + if (this.head != null) { 23 + node.next = this.head; 24 + } 25 + this.head = node; 26 + this.length++; 27 + } 28 + 29 + insertAt(item: T, idx: number): void { 30 + let current_node = this.head; 31 + let i = 0; 32 + 33 + while (current_node?.next != null && i < idx) { 34 + current_node = current_node.next; 35 + i += 1; 36 + } 37 + 38 + if (current_node?.next != null) { 39 + let node = new Node<T>(item); 40 + node.next = current_node.next; 41 + current_node.next = node; 42 + this.length++; 43 + } 44 + } 45 + 46 + append(item: T): void { 47 + if (this.length == 0) { 48 + let node = new Node<T>(item); 49 + this.head = node; 50 + this.length++; 51 + return; 52 + } 53 + 54 + let current_node = this.head; 55 + 56 + while (current_node?.next != null) { 57 + current_node = current_node.next; 58 + } 59 + 60 + if (current_node != null) { 61 + let node = new Node<T>(item); 62 + current_node.next = node; 63 + this.length++; 64 + } 65 + } 66 + 67 + remove(item: T): T | undefined { 68 + let current_node = this.head; 69 + let prev_node = this.head; 70 + let node_to_remove = null; 71 + 72 + while (current_node != null) { 73 + if (current_node.value === item) { 74 + node_to_remove = current_node; 75 + break; 76 + } 77 + prev_node = current_node; 78 + current_node = current_node.next; 79 + } 80 + 81 + if (node_to_remove == this.head) { 82 + this.head = node_to_remove.next; 83 + this.length--; 84 + } else if (prev_node?.next != null) { 85 + prev_node.next = node_to_remove?.next; 86 + this.length--; 87 + } 88 + 89 + return current_node?.value; 90 + } 91 + 92 + get(idx: number): T | undefined { 93 + let current_node = this.head; 94 + let i = 0; 95 + 96 + while (current_node != null && i < idx) { 97 + current_node = current_node.next; 98 + i += 1; 99 + } 100 + 101 + return current_node?.value; 102 + } 103 + 104 + removeAt(idx: number): T | undefined { 105 + let current_node = this.head; 106 + 107 + if (idx == 0 && current_node != null) { 108 + this.head = current_node.next; 109 + this.length--; 110 + return current_node.value; 111 + } 112 + 113 + let i = 0; 114 + while (current_node?.next != null && i < idx - 1) { 115 + current_node = current_node.next; 116 + i += 1; 117 + } 118 + 119 + if (current_node?.next != null) { 120 + let node_to_remove = current_node.next; 121 + current_node.next = node_to_remove.next; 122 + this.length--; 123 + return node_to_remove.value; 124 + } 125 + 126 + return undefined; 127 + } 128 + 129 + debug() { 130 + let current_node = this.head; 131 + let result = ""; 132 + while (current_node != null) { 133 + result += ` ${current_node.value},`; 134 + current_node = current_node.next; 135 + } 136 + console.log(result); 137 + } 138 + }
+25
src/day1/Stack.test.ts
··· 1 + import Stack from "@code/Stack"; 2 + 3 + test("stack", function () { 4 + const list = new Stack<number>(); 5 + 6 + list.push(5); 7 + list.push(7); 8 + list.push(9); 9 + 10 + expect(list.pop()).toEqual(9); 11 + expect(list.length).toEqual(2); 12 + 13 + list.push(11); 14 + expect(list.pop()).toEqual(11); 15 + expect(list.pop()).toEqual(7); 16 + expect(list.peek()).toEqual(5); 17 + expect(list.pop()).toEqual(5); 18 + expect(list.pop()).toEqual(undefined); 19 + 20 + // just wanted to make sure that I could not blow up myself when i remove 21 + // everything 22 + list.push(69); 23 + expect(list.peek()).toEqual(69); 24 + expect(list.length).toEqual(1); 25 + });
+43
src/day1/Stack.ts
··· 1 + type Node<T> = { 2 + value: T; 3 + prev?: Node<T>; 4 + }; 5 + 6 + export default class Stack<T> { 7 + public length: number; 8 + private head?: Node<T>; 9 + 10 + constructor() { 11 + this.head = undefined; 12 + this.length = 0; 13 + } 14 + 15 + push(item: T): void { 16 + const node = { value: item } as Node<T>; 17 + this.length++; 18 + if (!this.head) { 19 + this.head = node; 20 + return; 21 + } 22 + 23 + node.prev = this.head; 24 + this.head = node; 25 + } 26 + 27 + pop(): T | undefined { 28 + this.length = Math.max(0, this.length - 1); 29 + if (this.length === 0) { 30 + const head = this.head; 31 + this.head = undefined; 32 + return head?.value; 33 + } 34 + 35 + const head = this.head as Node<T>; 36 + this.head = head.prev; 37 + return head?.value; 38 + } 39 + 40 + peek(): T | undefined { 41 + return this.head?.value; 42 + } 43 + }
+15
src/day1/Trie.test.ts
··· 1 + import Trie from "@code/Trie"; 2 + 3 + test("Trie", function () { 4 + const trie = new Trie(); 5 + trie.insert("foo"); 6 + trie.insert("fool"); 7 + trie.insert("foolish"); 8 + trie.insert("bar"); 9 + 10 + expect(trie.find("fo").sort()).toEqual(["foo", "fool", "foolish"]); 11 + 12 + trie.delete("fool"); 13 + 14 + expect(trie.find("fo").sort()).toEqual(["foo", "foolish"]); 15 + });
+86
src/day1/Trie.ts
··· 1 + type TrieNode = { 2 + children: TrieNode[]; 3 + isValue: boolean; 4 + value?: string; 5 + }; 6 + 7 + // Creates a new TrieNode with defaults 8 + function createTrieNode() { 9 + return { 10 + children: [], 11 + isValue: false, 12 + }; 13 + } 14 + 15 + // Char code for 'a'. 16 + const start = "a".charCodeAt(0); 17 + 18 + // Returns the distance from 'a' which can be used to index into an array. 19 + function getIdx(item: string, idx: number): number { 20 + return item.toLowerCase().charCodeAt(idx) - start; 21 + } 22 + 23 + export default class Trie { 24 + private head: TrieNode; 25 + 26 + constructor() { 27 + this.head = createTrieNode(); 28 + } 29 + 30 + insert(item: string): void { 31 + let current: TrieNode = this.head; 32 + for (let i = 0; i < item.length; ++i) { 33 + const letter = getIdx(item, i); 34 + if (!current.children[letter]) { 35 + current.children[letter] = createTrieNode(); 36 + } 37 + current = current.children[letter]; 38 + } 39 + 40 + current.isValue = true; 41 + current.value = item; 42 + } 43 + 44 + delete(item: string): void { 45 + let current: TrieNode = this.head; 46 + for (let i = 0; current && i < item.length; ++i) { 47 + current = current.children[getIdx(item, i)]; 48 + } 49 + 50 + if (!current) { 51 + return; 52 + } 53 + 54 + current.value = undefined; 55 + current.isValue = false; 56 + } 57 + 58 + find(partial: string): string[] { 59 + let current = this.head; 60 + for (let i = 0; i < partial.length; ++i) { 61 + current = current.children[getIdx(partial, i)]; 62 + } 63 + 64 + return this.findRecursively(current, []); 65 + } 66 + 67 + // Finds all the possible words to complete node. 68 + private findRecursively( 69 + node: TrieNode | undefined, 70 + out: string[], 71 + ): string[] { 72 + if (!node) { 73 + return out; 74 + } 75 + 76 + if (node.isValue) { 77 + out.push(node.value as string); 78 + } 79 + 80 + for (let i = 0; i < node.children.length; ++i) { 81 + this.findRecursively(node.children[i], out); 82 + } 83 + 84 + return out; 85 + } 86 + }
+13
src/day1/TwoCrystalBalls.test.ts
··· 1 + import two_crystal_balls from "@code/TwoCrystalBalls"; 2 + 3 + test("two crystal balls", function () { 4 + let idx = Math.floor(Math.random() * 10000); 5 + const data = new Array(10000).fill(false); 6 + 7 + for (let i = idx; i < 10000; ++i) { 8 + data[i] = true; 9 + } 10 + 11 + expect(two_crystal_balls(data)).toEqual(idx); 12 + expect(two_crystal_balls(new Array(821).fill(false))).toEqual(-1); 13 + });
+20
src/day1/TwoCrystalBalls.ts
··· 1 + export default function two_crystal_balls(breaks: boolean[]): number { 2 + const jmpAmount = Math.floor(Math.sqrt(breaks.length)); 3 + 4 + let i = jmpAmount; 5 + for (; i < breaks.length; i += jmpAmount) { 6 + if (breaks[i]) { 7 + break; 8 + } 9 + } 10 + 11 + i -= jmpAmount; 12 + 13 + for (let j = 0; j < jmpAmount && i < breaks.length; j++, i++) { 14 + if (breaks[i]) { 15 + return i; 16 + } 17 + } 18 + 19 + return -1; 20 + }
+80
src/day1/graph.ts
··· 1 + export const list1: WeightedAdjacencyList = []; 2 + 3 + // (1) --- (4) ---- (5) 4 + // / | | /| 5 + // (0) | ------|------- | 6 + // \ |/ | | 7 + // (2) --- (3) ---- (6) 8 + list1[0] = [ 9 + { to: 1, weight: 3 }, 10 + { to: 2, weight: 1 }, 11 + ]; 12 + list1[1] = [ 13 + { to: 0, weight: 3 }, 14 + { to: 2, weight: 4 }, 15 + { to: 4, weight: 1 }, 16 + ]; 17 + list1[2] = [ 18 + { to: 1, weight: 4 }, 19 + { to: 3, weight: 7 }, 20 + { to: 0, weight: 1 }, 21 + ]; 22 + list1[3] = [ 23 + { to: 2, weight: 7 }, 24 + { to: 4, weight: 5 }, 25 + { to: 6, weight: 1 }, 26 + ]; 27 + list1[4] = [ 28 + { to: 1, weight: 1 }, 29 + { to: 3, weight: 5 }, 30 + { to: 5, weight: 2 }, 31 + ]; 32 + list1[5] = [ 33 + { to: 6, weight: 1 }, 34 + { to: 4, weight: 2 }, 35 + { to: 2, weight: 18 }, 36 + ]; 37 + list1[6] = [ 38 + { to: 3, weight: 1 }, 39 + { to: 5, weight: 1 }, 40 + ]; 41 + 42 + export const list2: WeightedAdjacencyList = []; 43 + 44 + // >(1)<--->(4) ---->(5) 45 + // / | /| 46 + // (0) ------|------- | 47 + // \ v v v 48 + // >(2) --> (3) <----(6) 49 + list2[0] = [ 50 + { to: 1, weight: 3 }, 51 + { to: 2, weight: 1 }, 52 + ]; 53 + list2[1] = [{ to: 4, weight: 1 }]; 54 + list2[2] = [{ to: 3, weight: 7 }]; 55 + list2[3] = []; 56 + list2[4] = [ 57 + { to: 1, weight: 1 }, 58 + { to: 3, weight: 5 }, 59 + { to: 5, weight: 2 }, 60 + ]; 61 + list2[5] = [ 62 + { to: 2, weight: 18 }, 63 + { to: 6, weight: 1 }, 64 + ]; 65 + list2[6] = [{ to: 3, weight: 1 }]; 66 + 67 + // >(1)<--->(4) ---->(5) 68 + // / | /| 69 + // (0) ------|------- | 70 + // \ v v v 71 + // >(2) --> (3) <----(6) 72 + export const matrix2: WeightedAdjacencyMatrix = [ 73 + [0, 3, 1, 0, 0, 0, 0], // 0 74 + [0, 0, 0, 0, 1, 0, 0], 75 + [0, 0, 7, 0, 0, 0, 0], 76 + [0, 0, 0, 0, 0, 0, 0], 77 + [0, 1, 0, 5, 0, 2, 0], 78 + [0, 0, 18, 0, 0, 0, 1], 79 + [0, 0, 0, 1, 0, 0, 1], 80 + ];
+87
src/day1/tree.ts
··· 1 + export const tree: BinaryNode<number> = { 2 + value: 20, 3 + right: { 4 + value: 50, 5 + right: { 6 + value: 100, 7 + right: null, 8 + left: null, 9 + }, 10 + left: { 11 + value: 30, 12 + right: { 13 + value: 45, 14 + right: null, 15 + left: null, 16 + }, 17 + left: { 18 + value: 29, 19 + right: null, 20 + left: null, 21 + }, 22 + }, 23 + }, 24 + left: { 25 + value: 10, 26 + right: { 27 + value: 15, 28 + right: null, 29 + left: null, 30 + }, 31 + left: { 32 + value: 5, 33 + right: { 34 + value: 7, 35 + right: null, 36 + left: null, 37 + }, 38 + left: null, 39 + }, 40 + }, 41 + }; 42 + 43 + export const tree2: BinaryNode<number> = { 44 + value: 20, 45 + right: { 46 + value: 50, 47 + right: null, 48 + left: { 49 + value: 30, 50 + right: { 51 + value: 45, 52 + right: { 53 + value: 49, 54 + left: null, 55 + right: null, 56 + }, 57 + left: null, 58 + }, 59 + left: { 60 + value: 29, 61 + right: null, 62 + left: { 63 + value: 21, 64 + right: null, 65 + left: null, 66 + }, 67 + }, 68 + }, 69 + }, 70 + left: { 71 + value: 10, 72 + right: { 73 + value: 15, 74 + right: null, 75 + left: null, 76 + }, 77 + left: { 78 + value: 5, 79 + right: { 80 + value: 7, 81 + right: null, 82 + left: null, 83 + }, 84 + left: null, 85 + }, 86 + }, 87 + };
+46
src/global.d.ts
··· 1 + declare type Point = { 2 + x: number; 3 + y: number; 4 + }; 5 + 6 + declare type ListNode<T> = { 7 + value: T; 8 + next?: ListNode<T>; 9 + prev?: ListNode<T>; 10 + }; 11 + 12 + declare interface List<T> { 13 + get length(): number; 14 + removeAt(index: number): T | undefined; 15 + remove(item: T): T | undefined; 16 + get(index: number): T | undefined; 17 + prepend(item: T): void; 18 + append(item: T): void; 19 + insertAt(item: T, idx: number): void; 20 + } 21 + 22 + declare type CompleteGraphEdge = { from: number; to: number; weight: number }; 23 + declare type GraphEdge = { to: number; weight: number }; 24 + declare type WeightedAdjacencyList = GraphEdge[][]; 25 + // A number means weight 26 + declare type WeightedAdjacencyMatrix = number[][]; 27 + 28 + declare type AdjacencyList = number[][]; 29 + // A 1 means connected 30 + declare type AdjacencyMatrix = number[][]; 31 + 32 + declare type BinaryNode<T> = { 33 + value: T; 34 + left: BinaryNode<T> | null; 35 + right: BinaryNode<T> | null; 36 + }; 37 + 38 + declare type GeneralNode<T> = { 39 + value: T; 40 + children: GeneralNode<T>[]; 41 + }; 42 + 43 + declare interface ILRU<K, V> { 44 + update(key: K, value: V): void; 45 + get(key: K): V | undefined; 46 + }
+21
tsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + "outDir": "dist", 4 + "allowJs": true, 5 + "noImplicitAny": true, 6 + "strictNullChecks": true, 7 + "resolveJsonModule": true, 8 + "noImplicitReturns": true, 9 + "esModuleInterop": true, 10 + "target": "ESNext", 11 + "module": "ESNext", 12 + "moduleResolution": "bundler", 13 + "baseUrl": "src", 14 + "paths": { 15 + "@code/*": ["day1/*"] 16 + }, 17 + "types": ["vitest/globals"] 18 + }, 19 + "include": ["./src/**/*"], 20 + "exclude": ["node_modules"] 21 + }
+15
vitest.config.ts
··· 1 + import { defineConfig } from "vitest/config"; 2 + import path from "path"; 3 + 4 + export default defineConfig({ 5 + resolve: { 6 + alias: { 7 + "@code": path.resolve(__dirname, "src/day1"), 8 + }, 9 + }, 10 + test: { 11 + globals: true, 12 + environment: "node", 13 + include: ["src/**/*.test.{ts,js}"], 14 + }, 15 + });