From baa87fb2fbd96f492d0962b8125532e0b17fd03a Mon Sep 17 00:00:00 2001 From: Chris Dill Date: Tue, 16 Dec 2025 20:39:11 +0000 Subject: [PATCH] Initial commit --- .gitignore | 1 + README.md | 11 + package.json | 19 + pnpm-lock.yaml | 1666 +++++++++++++++++++++++++++ prettier.config.ts | 8 + src/array-test.ts | 101 ++ src/day1/ArrayList.test.ts | 7 + src/day1/ArrayList.ts | 93 ++ src/day1/BFSGraphList.test.ts | 8 + src/day1/BFSGraphList.ts | 45 + src/day1/BFSGraphMatrix.test.ts | 8 + src/day1/BFSGraphMatrix.ts | 43 + src/day1/BTBFS.test.ts | 8 + src/day1/BTBFS.ts | 20 + src/day1/BTInOrder.test.ts | 6 + src/day1/BTInOrder.ts | 17 + src/day1/BTPostOrder.test.ts | 8 + src/day1/BTPostOrder.ts | 17 + src/day1/BTPreOrder.test.ts | 6 + src/day1/BTPreOrder.ts | 19 + src/day1/BinarySearchList.test.ts | 11 + src/day1/BinarySearchList.ts | 19 + src/day1/BubbleSort.test.ts | 9 + src/day1/BubbleSort.ts | 11 + src/day1/CompareBinaryTrees.test.ts | 7 + src/day1/CompareBinaryTrees.ts | 21 + src/day1/DFSGraphList.test.ts | 8 + src/day1/DFSGraphList.ts | 50 + src/day1/DFSOnBST.test.ts | 8 + src/day1/DFSOnBST.ts | 19 + src/day1/DijkstraList.test.ts | 9 + src/day1/DijkstraList.ts | 61 + src/day1/DoublyLinkedList.test.ts | 7 + src/day1/DoublyLinkedList.ts | 136 +++ src/day1/InsertionSort.test.ts | 9 + src/day1/InsertionSort.ts | 13 + src/day1/LRU.test.ts | 27 + src/day1/LRU.ts | 99 ++ src/day1/LinearSearchList.test.ts | 11 + src/day1/LinearSearchList.ts | 12 + src/day1/ListTest.ts | 26 + src/day1/Map.test.ts | 23 + src/day1/Map.ts | 34 + src/day1/MazeSolver.test.ts | 44 + src/day1/MazeSolver.ts | 57 + src/day1/MergeSort.test.ts | 7 + src/day1/MergeSort.ts | 36 + src/day1/MinHeap.test.ts | 28 + src/day1/MinHeap.ts | 89 ++ src/day1/PrimsAlgorithm.ts | 58 + src/day1/PrimsList.test.ts | 30 + src/day1/Queue.test.ts | 31 + src/day1/Queue.ts | 50 + src/day1/QuickSort.test.ts | 9 + src/day1/QuickSort.ts | 34 + src/day1/RingBuffer.test.ts | 22 + src/day1/RingBuffer.ts | 59 + src/day1/SinglyLinkedList.test.ts | 7 + src/day1/SinglyLinkedList.ts | 138 +++ src/day1/Stack.test.ts | 25 + src/day1/Stack.ts | 43 + src/day1/Trie.test.ts | 15 + src/day1/Trie.ts | 86 ++ src/day1/TwoCrystalBalls.test.ts | 13 + src/day1/TwoCrystalBalls.ts | 20 + src/day1/graph.ts | 80 ++ src/day1/tree.ts | 87 ++ src/global.d.ts | 52 + tsconfig.json | 19 + vitest.config.ts | 15 + 70 files changed, 3895 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 prettier.config.ts create mode 100644 src/array-test.ts create mode 100644 src/day1/ArrayList.test.ts create mode 100644 src/day1/ArrayList.ts create mode 100644 src/day1/BFSGraphList.test.ts create mode 100644 src/day1/BFSGraphList.ts create mode 100644 src/day1/BFSGraphMatrix.test.ts create mode 100644 src/day1/BFSGraphMatrix.ts create mode 100644 src/day1/BTBFS.test.ts create mode 100644 src/day1/BTBFS.ts create mode 100644 src/day1/BTInOrder.test.ts create mode 100644 src/day1/BTInOrder.ts create mode 100644 src/day1/BTPostOrder.test.ts create mode 100644 src/day1/BTPostOrder.ts create mode 100644 src/day1/BTPreOrder.test.ts create mode 100644 src/day1/BTPreOrder.ts create mode 100644 src/day1/BinarySearchList.test.ts create mode 100644 src/day1/BinarySearchList.ts create mode 100644 src/day1/BubbleSort.test.ts create mode 100644 src/day1/BubbleSort.ts create mode 100644 src/day1/CompareBinaryTrees.test.ts create mode 100644 src/day1/CompareBinaryTrees.ts create mode 100644 src/day1/DFSGraphList.test.ts create mode 100644 src/day1/DFSGraphList.ts create mode 100644 src/day1/DFSOnBST.test.ts create mode 100644 src/day1/DFSOnBST.ts create mode 100644 src/day1/DijkstraList.test.ts create mode 100644 src/day1/DijkstraList.ts create mode 100644 src/day1/DoublyLinkedList.test.ts create mode 100644 src/day1/DoublyLinkedList.ts create mode 100644 src/day1/InsertionSort.test.ts create mode 100644 src/day1/InsertionSort.ts create mode 100644 src/day1/LRU.test.ts create mode 100644 src/day1/LRU.ts create mode 100644 src/day1/LinearSearchList.test.ts create mode 100644 src/day1/LinearSearchList.ts create mode 100644 src/day1/ListTest.ts create mode 100644 src/day1/Map.test.ts create mode 100644 src/day1/Map.ts create mode 100644 src/day1/MazeSolver.test.ts create mode 100644 src/day1/MazeSolver.ts create mode 100644 src/day1/MergeSort.test.ts create mode 100644 src/day1/MergeSort.ts create mode 100644 src/day1/MinHeap.test.ts create mode 100644 src/day1/MinHeap.ts create mode 100644 src/day1/PrimsAlgorithm.ts create mode 100644 src/day1/PrimsList.test.ts create mode 100644 src/day1/Queue.test.ts create mode 100644 src/day1/Queue.ts create mode 100644 src/day1/QuickSort.test.ts create mode 100644 src/day1/QuickSort.ts create mode 100644 src/day1/RingBuffer.test.ts create mode 100644 src/day1/RingBuffer.ts create mode 100644 src/day1/SinglyLinkedList.test.ts create mode 100644 src/day1/SinglyLinkedList.ts create mode 100644 src/day1/Stack.test.ts create mode 100644 src/day1/Stack.ts create mode 100644 src/day1/Trie.test.ts create mode 100644 src/day1/Trie.ts create mode 100644 src/day1/TwoCrystalBalls.test.ts create mode 100644 src/day1/TwoCrystalBalls.ts create mode 100644 src/day1/graph.ts create mode 100644 src/day1/tree.ts create mode 100644 src/global.d.ts create mode 100644 tsconfig.json create mode 100644 vitest.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..7b1c572 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# test-kata-machine + +Kata machine practice. + +https://frontendmasters.com/courses/algorithms/ + +https://github.com/ThePrimeagen/kata-machine + +1. `pnpm install` + +2. `pnpm test` diff --git a/package.json b/package.json new file mode 100644 index 0000000..f4149a8 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "test-kata-machine", + "version": "0.0.1", + "scripts": { + "test": "vitest", + "format": "prettier --write ./src" + }, + "devDependencies": { + "vite": "^7.0.5", + "vitest": "^3.2.4" + }, + "dependencies": { + "prettier": "^3.6.2", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "tsconfig-paths-jest": "^0.0.1", + "typescript": "^5.8.3" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..aecf47e --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1666 @@ +lockfileVersion: "9.0" + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + .: + dependencies: + prettier: + specifier: ^3.6.2 + version: 3.6.2 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@swc/core@1.13.2)(@types/node@24.1.0)(typescript@5.8.3) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + tsconfig-paths-jest: + specifier: ^0.0.1 + version: 0.0.1 + typescript: + specifier: ^5.8.3 + version: 5.8.3 + devDependencies: + vite: + specifier: ^7.0.5 + version: 7.0.5(@types/node@24.1.0) + vitest: + specifier: ^3.2.4 + version: 3.2.4(@types/node@24.1.0) + +packages: + "@cspotcode/source-map-support@0.8.1": + resolution: + { + integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==, + } + engines: { node: ">=12" } + + "@esbuild/aix-ppc64@0.25.8": + resolution: + { + integrity: sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==, + } + engines: { node: ">=18" } + cpu: [ppc64] + os: [aix] + + "@esbuild/android-arm64@0.25.8": + resolution: + { + integrity: sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [android] + + "@esbuild/android-arm@0.25.8": + resolution: + { + integrity: sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==, + } + engines: { node: ">=18" } + cpu: [arm] + os: [android] + + "@esbuild/android-x64@0.25.8": + resolution: + { + integrity: sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [android] + + "@esbuild/darwin-arm64@0.25.8": + resolution: + { + integrity: sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [darwin] + + "@esbuild/darwin-x64@0.25.8": + resolution: + { + integrity: sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [darwin] + + "@esbuild/freebsd-arm64@0.25.8": + resolution: + { + integrity: sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [freebsd] + + "@esbuild/freebsd-x64@0.25.8": + resolution: + { + integrity: sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [freebsd] + + "@esbuild/linux-arm64@0.25.8": + resolution: + { + integrity: sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [linux] + + "@esbuild/linux-arm@0.25.8": + resolution: + { + integrity: sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==, + } + engines: { node: ">=18" } + cpu: [arm] + os: [linux] + + "@esbuild/linux-ia32@0.25.8": + resolution: + { + integrity: sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==, + } + engines: { node: ">=18" } + cpu: [ia32] + os: [linux] + + "@esbuild/linux-loong64@0.25.8": + resolution: + { + integrity: sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==, + } + engines: { node: ">=18" } + cpu: [loong64] + os: [linux] + + "@esbuild/linux-mips64el@0.25.8": + resolution: + { + integrity: sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==, + } + engines: { node: ">=18" } + cpu: [mips64el] + os: [linux] + + "@esbuild/linux-ppc64@0.25.8": + resolution: + { + integrity: sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==, + } + engines: { node: ">=18" } + cpu: [ppc64] + os: [linux] + + "@esbuild/linux-riscv64@0.25.8": + resolution: + { + integrity: sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==, + } + engines: { node: ">=18" } + cpu: [riscv64] + os: [linux] + + "@esbuild/linux-s390x@0.25.8": + resolution: + { + integrity: sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==, + } + engines: { node: ">=18" } + cpu: [s390x] + os: [linux] + + "@esbuild/linux-x64@0.25.8": + resolution: + { + integrity: sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [linux] + + "@esbuild/netbsd-arm64@0.25.8": + resolution: + { + integrity: sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [netbsd] + + "@esbuild/netbsd-x64@0.25.8": + resolution: + { + integrity: sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [netbsd] + + "@esbuild/openbsd-arm64@0.25.8": + resolution: + { + integrity: sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [openbsd] + + "@esbuild/openbsd-x64@0.25.8": + resolution: + { + integrity: sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [openbsd] + + "@esbuild/openharmony-arm64@0.25.8": + resolution: + { + integrity: sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [openharmony] + + "@esbuild/sunos-x64@0.25.8": + resolution: + { + integrity: sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [sunos] + + "@esbuild/win32-arm64@0.25.8": + resolution: + { + integrity: sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [win32] + + "@esbuild/win32-ia32@0.25.8": + resolution: + { + integrity: sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==, + } + engines: { node: ">=18" } + cpu: [ia32] + os: [win32] + + "@esbuild/win32-x64@0.25.8": + resolution: + { + integrity: sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [win32] + + "@jridgewell/resolve-uri@3.1.2": + resolution: + { + integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, + } + engines: { node: ">=6.0.0" } + + "@jridgewell/sourcemap-codec@1.5.4": + resolution: + { + integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==, + } + + "@jridgewell/trace-mapping@0.3.9": + resolution: + { + integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, + } + + "@rollup/rollup-android-arm-eabi@4.45.1": + resolution: + { + integrity: sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==, + } + cpu: [arm] + os: [android] + + "@rollup/rollup-android-arm64@4.45.1": + resolution: + { + integrity: sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==, + } + cpu: [arm64] + os: [android] + + "@rollup/rollup-darwin-arm64@4.45.1": + resolution: + { + integrity: sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==, + } + cpu: [arm64] + os: [darwin] + + "@rollup/rollup-darwin-x64@4.45.1": + resolution: + { + integrity: sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==, + } + cpu: [x64] + os: [darwin] + + "@rollup/rollup-freebsd-arm64@4.45.1": + resolution: + { + integrity: sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==, + } + cpu: [arm64] + os: [freebsd] + + "@rollup/rollup-freebsd-x64@4.45.1": + resolution: + { + integrity: sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==, + } + cpu: [x64] + os: [freebsd] + + "@rollup/rollup-linux-arm-gnueabihf@4.45.1": + resolution: + { + integrity: sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==, + } + cpu: [arm] + os: [linux] + + "@rollup/rollup-linux-arm-musleabihf@4.45.1": + resolution: + { + integrity: sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==, + } + cpu: [arm] + os: [linux] + + "@rollup/rollup-linux-arm64-gnu@4.45.1": + resolution: + { + integrity: sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==, + } + cpu: [arm64] + os: [linux] + + "@rollup/rollup-linux-arm64-musl@4.45.1": + resolution: + { + integrity: sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==, + } + cpu: [arm64] + os: [linux] + + "@rollup/rollup-linux-loongarch64-gnu@4.45.1": + resolution: + { + integrity: sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==, + } + cpu: [loong64] + os: [linux] + + "@rollup/rollup-linux-powerpc64le-gnu@4.45.1": + resolution: + { + integrity: sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==, + } + cpu: [ppc64] + os: [linux] + + "@rollup/rollup-linux-riscv64-gnu@4.45.1": + resolution: + { + integrity: sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==, + } + cpu: [riscv64] + os: [linux] + + "@rollup/rollup-linux-riscv64-musl@4.45.1": + resolution: + { + integrity: sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==, + } + cpu: [riscv64] + os: [linux] + + "@rollup/rollup-linux-s390x-gnu@4.45.1": + resolution: + { + integrity: sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==, + } + cpu: [s390x] + os: [linux] + + "@rollup/rollup-linux-x64-gnu@4.45.1": + resolution: + { + integrity: sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==, + } + cpu: [x64] + os: [linux] + + "@rollup/rollup-linux-x64-musl@4.45.1": + resolution: + { + integrity: sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==, + } + cpu: [x64] + os: [linux] + + "@rollup/rollup-win32-arm64-msvc@4.45.1": + resolution: + { + integrity: sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==, + } + cpu: [arm64] + os: [win32] + + "@rollup/rollup-win32-ia32-msvc@4.45.1": + resolution: + { + integrity: sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==, + } + cpu: [ia32] + os: [win32] + + "@rollup/rollup-win32-x64-msvc@4.45.1": + resolution: + { + integrity: sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==, + } + cpu: [x64] + os: [win32] + + "@swc/core-darwin-arm64@1.13.2": + resolution: + { + integrity: sha512-44p7ivuLSGFJ15Vly4ivLJjg3ARo4879LtEBAabcHhSZygpmkP8eyjyWxrH3OxkY1eRZSIJe8yRZPFw4kPXFPw==, + } + engines: { node: ">=10" } + cpu: [arm64] + os: [darwin] + + "@swc/core-darwin-x64@1.13.2": + resolution: + { + integrity: sha512-Lb9EZi7X2XDAVmuUlBm2UvVAgSCbD3qKqDCxSI4jEOddzVOpNCnyZ/xEampdngUIyDDhhJLYU9duC+Mcsv5Y+A==, + } + engines: { node: ">=10" } + cpu: [x64] + os: [darwin] + + "@swc/core-linux-arm-gnueabihf@1.13.2": + resolution: + { + integrity: sha512-9TDe/92ee1x57x+0OqL1huG4BeljVx0nWW4QOOxp8CCK67Rpc/HHl2wciJ0Kl9Dxf2NvpNtkPvqj9+BUmM9WVA==, + } + engines: { node: ">=10" } + cpu: [arm] + os: [linux] + + "@swc/core-linux-arm64-gnu@1.13.2": + resolution: + { + integrity: sha512-KJUSl56DBk7AWMAIEcU83zl5mg3vlQYhLELhjwRFkGFMvghQvdqQ3zFOYa4TexKA7noBZa3C8fb24rI5sw9Exg==, + } + engines: { node: ">=10" } + cpu: [arm64] + os: [linux] + + "@swc/core-linux-arm64-musl@1.13.2": + resolution: + { + integrity: sha512-teU27iG1oyWpNh9CzcGQ48ClDRt/RCem7mYO7ehd2FY102UeTws2+OzLESS1TS1tEZipq/5xwx3FzbVgiolCiQ==, + } + engines: { node: ">=10" } + cpu: [arm64] + os: [linux] + + "@swc/core-linux-x64-gnu@1.13.2": + resolution: + { + integrity: sha512-dRPsyPyqpLD0HMRCRpYALIh4kdOir8pPg4AhNQZLehKowigRd30RcLXGNVZcc31Ua8CiPI4QSgjOIxK+EQe4LQ==, + } + engines: { node: ">=10" } + cpu: [x64] + os: [linux] + + "@swc/core-linux-x64-musl@1.13.2": + resolution: + { + integrity: sha512-CCxETW+KkYEQDqz1SYC15YIWYheqFC+PJVOW76Maa/8yu8Biw+HTAcblKf2isrlUtK8RvrQN94v3UXkC2NzCEw==, + } + engines: { node: ">=10" } + cpu: [x64] + os: [linux] + + "@swc/core-win32-arm64-msvc@1.13.2": + resolution: + { + integrity: sha512-Wv/QTA6PjyRLlmKcN6AmSI4jwSMRl0VTLGs57PHTqYRwwfwd7y4s2fIPJVBNbAlXd795dOEP6d/bGSQSyhOX3A==, + } + engines: { node: ">=10" } + cpu: [arm64] + os: [win32] + + "@swc/core-win32-ia32-msvc@1.13.2": + resolution: + { + integrity: sha512-PuCdtNynEkUNbUXX/wsyUC+t4mamIU5y00lT5vJcAvco3/r16Iaxl5UCzhXYaWZSNVZMzPp9qN8NlSL8M5pPxw==, + } + engines: { node: ">=10" } + cpu: [ia32] + os: [win32] + + "@swc/core-win32-x64-msvc@1.13.2": + resolution: + { + integrity: sha512-qlmMkFZJus8cYuBURx1a3YAG2G7IW44i+FEYV5/32ylKkzGNAr9tDJSA53XNnNXkAB5EXSPsOz7bn5C3JlEtdQ==, + } + engines: { node: ">=10" } + cpu: [x64] + os: [win32] + + "@swc/core@1.13.2": + resolution: + { + integrity: sha512-YWqn+0IKXDhqVLKoac4v2tV6hJqB/wOh8/Br8zjqeqBkKa77Qb0Kw2i7LOFzjFNZbZaPH6AlMGlBwNrxaauaAg==, + } + engines: { node: ">=10" } + peerDependencies: + "@swc/helpers": ">=0.5.17" + peerDependenciesMeta: + "@swc/helpers": + optional: true + + "@swc/counter@0.1.3": + resolution: + { + integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==, + } + + "@swc/types@0.1.23": + resolution: + { + integrity: sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==, + } + + "@tsconfig/node10@1.0.11": + resolution: + { + integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==, + } + + "@tsconfig/node12@1.0.11": + resolution: + { + integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==, + } + + "@tsconfig/node14@1.0.3": + resolution: + { + integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==, + } + + "@tsconfig/node16@1.0.4": + resolution: + { + integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==, + } + + "@types/chai@5.2.2": + resolution: + { + integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==, + } + + "@types/deep-eql@4.0.2": + resolution: + { + integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==, + } + + "@types/estree@1.0.8": + resolution: + { + integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==, + } + + "@types/node@24.1.0": + resolution: + { + integrity: sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==, + } + + "@vitest/expect@3.2.4": + resolution: + { + integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==, + } + + "@vitest/mocker@3.2.4": + resolution: + { + integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==, + } + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + "@vitest/pretty-format@3.2.4": + resolution: + { + integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==, + } + + "@vitest/runner@3.2.4": + resolution: + { + integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==, + } + + "@vitest/snapshot@3.2.4": + resolution: + { + integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==, + } + + "@vitest/spy@3.2.4": + resolution: + { + integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==, + } + + "@vitest/utils@3.2.4": + resolution: + { + integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==, + } + + acorn-walk@8.3.4: + resolution: + { + integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==, + } + engines: { node: ">=0.4.0" } + + acorn@8.15.0: + resolution: + { + integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==, + } + engines: { node: ">=0.4.0" } + hasBin: true + + arg@4.1.3: + resolution: + { + integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==, + } + + assertion-error@2.0.1: + resolution: + { + integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==, + } + engines: { node: ">=12" } + + cac@6.7.14: + resolution: + { + integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==, + } + engines: { node: ">=8" } + + chai@5.2.1: + resolution: + { + integrity: sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==, + } + engines: { node: ">=18" } + + check-error@2.1.1: + resolution: + { + integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==, + } + engines: { node: ">= 16" } + + create-require@1.1.1: + resolution: + { + integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==, + } + + debug@4.4.1: + resolution: + { + integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==, + } + engines: { node: ">=6.0" } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + + deep-eql@5.0.2: + resolution: + { + integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==, + } + engines: { node: ">=6" } + + diff@4.0.2: + resolution: + { + integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==, + } + engines: { node: ">=0.3.1" } + + es-module-lexer@1.7.0: + resolution: + { + integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==, + } + + esbuild@0.25.8: + resolution: + { + integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==, + } + engines: { node: ">=18" } + hasBin: true + + estree-walker@3.0.3: + resolution: + { + integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==, + } + + expect-type@1.2.2: + resolution: + { + integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==, + } + engines: { node: ">=12.0.0" } + + fdir@6.4.6: + resolution: + { + integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==, + } + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fsevents@2.3.3: + resolution: + { + integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, + } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + os: [darwin] + + js-tokens@9.0.1: + resolution: + { + integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==, + } + + json5@2.2.3: + resolution: + { + integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, + } + engines: { node: ">=6" } + hasBin: true + + loupe@3.1.4: + resolution: + { + integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==, + } + + magic-string@0.30.17: + resolution: + { + integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==, + } + + make-error@1.3.6: + resolution: + { + integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==, + } + + minimist@1.2.8: + resolution: + { + integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, + } + + ms@2.1.3: + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, + } + + nanoid@3.3.11: + resolution: + { + integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==, + } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + hasBin: true + + pathe@2.0.3: + resolution: + { + integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, + } + + pathval@2.0.1: + resolution: + { + integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==, + } + engines: { node: ">= 14.16" } + + picocolors@1.1.1: + resolution: + { + integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, + } + + picomatch@4.0.3: + resolution: + { + integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==, + } + engines: { node: ">=12" } + + postcss@8.5.6: + resolution: + { + integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==, + } + engines: { node: ^10 || ^12 || >=14 } + + prettier@3.6.2: + resolution: + { + integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==, + } + engines: { node: ">=14" } + hasBin: true + + rollup@4.45.1: + resolution: + { + integrity: sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==, + } + engines: { node: ">=18.0.0", npm: ">=8.0.0" } + hasBin: true + + siginfo@2.0.0: + resolution: + { + integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==, + } + + source-map-js@1.2.1: + resolution: + { + integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, + } + engines: { node: ">=0.10.0" } + + stackback@0.0.2: + resolution: + { + integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==, + } + + std-env@3.9.0: + resolution: + { + integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==, + } + + strip-bom@3.0.0: + resolution: + { + integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, + } + engines: { node: ">=4" } + + strip-literal@3.0.0: + resolution: + { + integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==, + } + + tinybench@2.9.0: + resolution: + { + integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==, + } + + tinyexec@0.3.2: + resolution: + { + integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==, + } + + tinyglobby@0.2.14: + resolution: + { + integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==, + } + engines: { node: ">=12.0.0" } + + tinypool@1.1.1: + resolution: + { + integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==, + } + engines: { node: ^18.0.0 || >=20.0.0 } + + tinyrainbow@2.0.0: + resolution: + { + integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==, + } + engines: { node: ">=14.0.0" } + + tinyspy@4.0.3: + resolution: + { + integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==, + } + engines: { node: ">=14.0.0" } + + ts-node@10.9.2: + resolution: + { + integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==, + } + hasBin: true + peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true + + tsconfig-paths-jest@0.0.1: + resolution: + { + integrity: sha512-YKhUKqbteklNppC2NqL7dv1cWF8eEobgHVD5kjF1y9Q4ocqpBiaDlYslQ9eMhtbqIPRrA68RIEXqknEjlxdwxw==, + } + + tsconfig-paths@4.2.0: + resolution: + { + integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==, + } + engines: { node: ">=6" } + + typescript@5.8.3: + resolution: + { + integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==, + } + engines: { node: ">=14.17" } + hasBin: true + + undici-types@7.8.0: + resolution: + { + integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==, + } + + v8-compile-cache-lib@3.0.1: + resolution: + { + integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==, + } + + vite-node@3.2.4: + resolution: + { + integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==, + } + engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } + hasBin: true + + vite@7.0.5: + resolution: + { + integrity: sha512-1mncVwJxy2C9ThLwz0+2GKZyEXuC3MyWtAAlNftlZZXZDP3AJt5FmwcMit/IGGaNZ8ZOB2BNO/HFUB+CpN0NQw==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + hasBin: true + peerDependencies: + "@types/node": ^20.19.0 || >=22.12.0 + jiti: ">=1.21.0" + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: ">=0.54.8" + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + "@types/node": + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@3.2.4: + resolution: + { + integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==, + } + engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } + hasBin: true + peerDependencies: + "@edge-runtime/vm": "*" + "@types/debug": ^4.1.12 + "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 + "@vitest/browser": 3.2.4 + "@vitest/ui": 3.2.4 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/debug": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + why-is-node-running@2.3.0: + resolution: + { + integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==, + } + engines: { node: ">=8" } + hasBin: true + + yn@3.1.1: + resolution: + { + integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==, + } + engines: { node: ">=6" } + +snapshots: + "@cspotcode/source-map-support@0.8.1": + dependencies: + "@jridgewell/trace-mapping": 0.3.9 + + "@esbuild/aix-ppc64@0.25.8": + optional: true + + "@esbuild/android-arm64@0.25.8": + optional: true + + "@esbuild/android-arm@0.25.8": + optional: true + + "@esbuild/android-x64@0.25.8": + optional: true + + "@esbuild/darwin-arm64@0.25.8": + optional: true + + "@esbuild/darwin-x64@0.25.8": + optional: true + + "@esbuild/freebsd-arm64@0.25.8": + optional: true + + "@esbuild/freebsd-x64@0.25.8": + optional: true + + "@esbuild/linux-arm64@0.25.8": + optional: true + + "@esbuild/linux-arm@0.25.8": + optional: true + + "@esbuild/linux-ia32@0.25.8": + optional: true + + "@esbuild/linux-loong64@0.25.8": + optional: true + + "@esbuild/linux-mips64el@0.25.8": + optional: true + + "@esbuild/linux-ppc64@0.25.8": + optional: true + + "@esbuild/linux-riscv64@0.25.8": + optional: true + + "@esbuild/linux-s390x@0.25.8": + optional: true + + "@esbuild/linux-x64@0.25.8": + optional: true + + "@esbuild/netbsd-arm64@0.25.8": + optional: true + + "@esbuild/netbsd-x64@0.25.8": + optional: true + + "@esbuild/openbsd-arm64@0.25.8": + optional: true + + "@esbuild/openbsd-x64@0.25.8": + optional: true + + "@esbuild/openharmony-arm64@0.25.8": + optional: true + + "@esbuild/sunos-x64@0.25.8": + optional: true + + "@esbuild/win32-arm64@0.25.8": + optional: true + + "@esbuild/win32-ia32@0.25.8": + optional: true + + "@esbuild/win32-x64@0.25.8": + optional: true + + "@jridgewell/resolve-uri@3.1.2": {} + + "@jridgewell/sourcemap-codec@1.5.4": {} + + "@jridgewell/trace-mapping@0.3.9": + dependencies: + "@jridgewell/resolve-uri": 3.1.2 + "@jridgewell/sourcemap-codec": 1.5.4 + + "@rollup/rollup-android-arm-eabi@4.45.1": + optional: true + + "@rollup/rollup-android-arm64@4.45.1": + optional: true + + "@rollup/rollup-darwin-arm64@4.45.1": + optional: true + + "@rollup/rollup-darwin-x64@4.45.1": + optional: true + + "@rollup/rollup-freebsd-arm64@4.45.1": + optional: true + + "@rollup/rollup-freebsd-x64@4.45.1": + optional: true + + "@rollup/rollup-linux-arm-gnueabihf@4.45.1": + optional: true + + "@rollup/rollup-linux-arm-musleabihf@4.45.1": + optional: true + + "@rollup/rollup-linux-arm64-gnu@4.45.1": + optional: true + + "@rollup/rollup-linux-arm64-musl@4.45.1": + optional: true + + "@rollup/rollup-linux-loongarch64-gnu@4.45.1": + optional: true + + "@rollup/rollup-linux-powerpc64le-gnu@4.45.1": + optional: true + + "@rollup/rollup-linux-riscv64-gnu@4.45.1": + optional: true + + "@rollup/rollup-linux-riscv64-musl@4.45.1": + optional: true + + "@rollup/rollup-linux-s390x-gnu@4.45.1": + optional: true + + "@rollup/rollup-linux-x64-gnu@4.45.1": + optional: true + + "@rollup/rollup-linux-x64-musl@4.45.1": + optional: true + + "@rollup/rollup-win32-arm64-msvc@4.45.1": + optional: true + + "@rollup/rollup-win32-ia32-msvc@4.45.1": + optional: true + + "@rollup/rollup-win32-x64-msvc@4.45.1": + optional: true + + "@swc/core-darwin-arm64@1.13.2": + optional: true + + "@swc/core-darwin-x64@1.13.2": + optional: true + + "@swc/core-linux-arm-gnueabihf@1.13.2": + optional: true + + "@swc/core-linux-arm64-gnu@1.13.2": + optional: true + + "@swc/core-linux-arm64-musl@1.13.2": + optional: true + + "@swc/core-linux-x64-gnu@1.13.2": + optional: true + + "@swc/core-linux-x64-musl@1.13.2": + optional: true + + "@swc/core-win32-arm64-msvc@1.13.2": + optional: true + + "@swc/core-win32-ia32-msvc@1.13.2": + optional: true + + "@swc/core-win32-x64-msvc@1.13.2": + optional: true + + "@swc/core@1.13.2": + dependencies: + "@swc/counter": 0.1.3 + "@swc/types": 0.1.23 + optionalDependencies: + "@swc/core-darwin-arm64": 1.13.2 + "@swc/core-darwin-x64": 1.13.2 + "@swc/core-linux-arm-gnueabihf": 1.13.2 + "@swc/core-linux-arm64-gnu": 1.13.2 + "@swc/core-linux-arm64-musl": 1.13.2 + "@swc/core-linux-x64-gnu": 1.13.2 + "@swc/core-linux-x64-musl": 1.13.2 + "@swc/core-win32-arm64-msvc": 1.13.2 + "@swc/core-win32-ia32-msvc": 1.13.2 + "@swc/core-win32-x64-msvc": 1.13.2 + optional: true + + "@swc/counter@0.1.3": + optional: true + + "@swc/types@0.1.23": + dependencies: + "@swc/counter": 0.1.3 + optional: true + + "@tsconfig/node10@1.0.11": {} + + "@tsconfig/node12@1.0.11": {} + + "@tsconfig/node14@1.0.3": {} + + "@tsconfig/node16@1.0.4": {} + + "@types/chai@5.2.2": + dependencies: + "@types/deep-eql": 4.0.2 + + "@types/deep-eql@4.0.2": {} + + "@types/estree@1.0.8": {} + + "@types/node@24.1.0": + dependencies: + undici-types: 7.8.0 + + "@vitest/expect@3.2.4": + dependencies: + "@types/chai": 5.2.2 + "@vitest/spy": 3.2.4 + "@vitest/utils": 3.2.4 + chai: 5.2.1 + tinyrainbow: 2.0.0 + + "@vitest/mocker@3.2.4(vite@7.0.5(@types/node@24.1.0))": + dependencies: + "@vitest/spy": 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 7.0.5(@types/node@24.1.0) + + "@vitest/pretty-format@3.2.4": + dependencies: + tinyrainbow: 2.0.0 + + "@vitest/runner@3.2.4": + dependencies: + "@vitest/utils": 3.2.4 + pathe: 2.0.3 + strip-literal: 3.0.0 + + "@vitest/snapshot@3.2.4": + dependencies: + "@vitest/pretty-format": 3.2.4 + magic-string: 0.30.17 + pathe: 2.0.3 + + "@vitest/spy@3.2.4": + dependencies: + tinyspy: 4.0.3 + + "@vitest/utils@3.2.4": + dependencies: + "@vitest/pretty-format": 3.2.4 + loupe: 3.1.4 + tinyrainbow: 2.0.0 + + acorn-walk@8.3.4: + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + arg@4.1.3: {} + + assertion-error@2.0.1: {} + + cac@6.7.14: {} + + chai@5.2.1: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.4 + pathval: 2.0.1 + + check-error@2.1.1: {} + + create-require@1.1.1: {} + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + deep-eql@5.0.2: {} + + diff@4.0.2: {} + + es-module-lexer@1.7.0: {} + + esbuild@0.25.8: + optionalDependencies: + "@esbuild/aix-ppc64": 0.25.8 + "@esbuild/android-arm": 0.25.8 + "@esbuild/android-arm64": 0.25.8 + "@esbuild/android-x64": 0.25.8 + "@esbuild/darwin-arm64": 0.25.8 + "@esbuild/darwin-x64": 0.25.8 + "@esbuild/freebsd-arm64": 0.25.8 + "@esbuild/freebsd-x64": 0.25.8 + "@esbuild/linux-arm": 0.25.8 + "@esbuild/linux-arm64": 0.25.8 + "@esbuild/linux-ia32": 0.25.8 + "@esbuild/linux-loong64": 0.25.8 + "@esbuild/linux-mips64el": 0.25.8 + "@esbuild/linux-ppc64": 0.25.8 + "@esbuild/linux-riscv64": 0.25.8 + "@esbuild/linux-s390x": 0.25.8 + "@esbuild/linux-x64": 0.25.8 + "@esbuild/netbsd-arm64": 0.25.8 + "@esbuild/netbsd-x64": 0.25.8 + "@esbuild/openbsd-arm64": 0.25.8 + "@esbuild/openbsd-x64": 0.25.8 + "@esbuild/openharmony-arm64": 0.25.8 + "@esbuild/sunos-x64": 0.25.8 + "@esbuild/win32-arm64": 0.25.8 + "@esbuild/win32-ia32": 0.25.8 + "@esbuild/win32-x64": 0.25.8 + + estree-walker@3.0.3: + dependencies: + "@types/estree": 1.0.8 + + expect-type@1.2.2: {} + + fdir@6.4.6(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fsevents@2.3.3: + optional: true + + js-tokens@9.0.1: {} + + json5@2.2.3: {} + + loupe@3.1.4: {} + + magic-string@0.30.17: + dependencies: + "@jridgewell/sourcemap-codec": 1.5.4 + + make-error@1.3.6: {} + + minimist@1.2.8: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + pathe@2.0.3: {} + + pathval@2.0.1: {} + + picocolors@1.1.1: {} + + picomatch@4.0.3: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prettier@3.6.2: {} + + rollup@4.45.1: + dependencies: + "@types/estree": 1.0.8 + optionalDependencies: + "@rollup/rollup-android-arm-eabi": 4.45.1 + "@rollup/rollup-android-arm64": 4.45.1 + "@rollup/rollup-darwin-arm64": 4.45.1 + "@rollup/rollup-darwin-x64": 4.45.1 + "@rollup/rollup-freebsd-arm64": 4.45.1 + "@rollup/rollup-freebsd-x64": 4.45.1 + "@rollup/rollup-linux-arm-gnueabihf": 4.45.1 + "@rollup/rollup-linux-arm-musleabihf": 4.45.1 + "@rollup/rollup-linux-arm64-gnu": 4.45.1 + "@rollup/rollup-linux-arm64-musl": 4.45.1 + "@rollup/rollup-linux-loongarch64-gnu": 4.45.1 + "@rollup/rollup-linux-powerpc64le-gnu": 4.45.1 + "@rollup/rollup-linux-riscv64-gnu": 4.45.1 + "@rollup/rollup-linux-riscv64-musl": 4.45.1 + "@rollup/rollup-linux-s390x-gnu": 4.45.1 + "@rollup/rollup-linux-x64-gnu": 4.45.1 + "@rollup/rollup-linux-x64-musl": 4.45.1 + "@rollup/rollup-win32-arm64-msvc": 4.45.1 + "@rollup/rollup-win32-ia32-msvc": 4.45.1 + "@rollup/rollup-win32-x64-msvc": 4.45.1 + fsevents: 2.3.3 + + siginfo@2.0.0: {} + + source-map-js@1.2.1: {} + + stackback@0.0.2: {} + + std-env@3.9.0: {} + + strip-bom@3.0.0: {} + + strip-literal@3.0.0: + dependencies: + js-tokens: 9.0.1 + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + + tinyspy@4.0.3: {} + + ts-node@10.9.2(@swc/core@1.13.2)(@types/node@24.1.0)(typescript@5.8.3): + dependencies: + "@cspotcode/source-map-support": 0.8.1 + "@tsconfig/node10": 1.0.11 + "@tsconfig/node12": 1.0.11 + "@tsconfig/node14": 1.0.3 + "@tsconfig/node16": 1.0.4 + "@types/node": 24.1.0 + acorn: 8.15.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.8.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + "@swc/core": 1.13.2 + + tsconfig-paths-jest@0.0.1: {} + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + typescript@5.8.3: {} + + undici-types@7.8.0: {} + + v8-compile-cache-lib@3.0.1: {} + + vite-node@3.2.4(@types/node@24.1.0): + dependencies: + cac: 6.7.14 + debug: 4.4.1 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 7.0.5(@types/node@24.1.0) + transitivePeerDependencies: + - "@types/node" + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@7.0.5(@types/node@24.1.0): + dependencies: + esbuild: 0.25.8 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.45.1 + tinyglobby: 0.2.14 + optionalDependencies: + "@types/node": 24.1.0 + fsevents: 2.3.3 + + vitest@3.2.4(@types/node@24.1.0): + dependencies: + "@types/chai": 5.2.2 + "@vitest/expect": 3.2.4 + "@vitest/mocker": 3.2.4(vite@7.0.5(@types/node@24.1.0)) + "@vitest/pretty-format": 3.2.4 + "@vitest/runner": 3.2.4 + "@vitest/snapshot": 3.2.4 + "@vitest/spy": 3.2.4 + "@vitest/utils": 3.2.4 + chai: 5.2.1 + debug: 4.4.1 + expect-type: 1.2.2 + magic-string: 0.30.17 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.14 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.0.5(@types/node@24.1.0) + vite-node: 3.2.4(@types/node@24.1.0) + why-is-node-running: 2.3.0 + optionalDependencies: + "@types/node": 24.1.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + yn@3.1.1: {} diff --git a/prettier.config.ts b/prettier.config.ts new file mode 100644 index 0000000..af77d01 --- /dev/null +++ b/prettier.config.ts @@ -0,0 +1,8 @@ +export default { + tabWidth: 4, + printWidth: 80, + proseWrap: "never", + trailingComma: "all", + singleQuote: false, + semi: true, +}; diff --git a/src/array-test.ts b/src/array-test.ts new file mode 100644 index 0000000..f0ea9d3 --- /dev/null +++ b/src/array-test.ts @@ -0,0 +1,101 @@ +const a: number[] = []; + +function time(fn: () => void): number { + const now = Date.now(); + fn(); + return Date.now() - now; +} + +function unshift(number: number) { + for (let i = 0; i < number; ++i) { + a.unshift(Math.random()); + } +} + +function shift(number: number) { + for (let i = 0; i < number; ++i) { + a.shift(); + } +} + +function push(number: number) { + for (let i = 0; i < number; ++i) { + a.push(Math.random()); + } +} + +function pop(number: number) { + for (let i = 0; i < number; ++i) { + a.pop(); + } +} + +function get(idx: number) { + return function () { + return a[idx]; + }; +} + +function push_arr(count: number) { + return function () { + push(count); + }; +} + +function pop_arr(count: number) { + return function () { + pop(count); + }; +} + +function unshift_arr(count: number) { + return function () { + unshift(count); + }; +} + +function shift_arr(count: number) { + return function () { + shift(count); + }; +} + +const tests = [10, 100, 1000, 10000, 100000, 1_000_000, 10_000_000]; +console.log("Testing get"); +tests.forEach((t) => { + a.length = 0; + push(t); + console.log(t, time(get(t - 1))); +}); + +console.log("push"); +tests.forEach((t) => { + a.length = 0; + push(t); + + console.log(t, time(push_arr(1000))); +}); + +console.log("pop"); +tests.forEach((t) => { + a.length = 0; + push(t); + + console.log(t, time(pop_arr(1000))); +}); + +console.log("unshift"); +tests.forEach((t) => { + a.length = 0; + push(t); + + console.log(t, time(unshift_arr(1000))); +}); + +console.log("shift"); +tests.forEach((t) => { + a.length = 0; + push(t); + + console.log(t, time(shift_arr(1000))); +}); diff --git a/src/day1/ArrayList.test.ts b/src/day1/ArrayList.test.ts new file mode 100644 index 0000000..4f1f3d6 --- /dev/null +++ b/src/day1/ArrayList.test.ts @@ -0,0 +1,7 @@ +import ArrayList from "@code/ArrayList"; +import { test_list } from "./ListTest"; + +test("array-list", function () { + const list = new ArrayList(3); + test_list(list); +}); diff --git a/src/day1/ArrayList.ts b/src/day1/ArrayList.ts new file mode 100644 index 0000000..64a49eb --- /dev/null +++ b/src/day1/ArrayList.ts @@ -0,0 +1,93 @@ +export default class ArrayList { + public length: number; + private array: Array; + private capacity: number; + + constructor(capacity: number = 5) { + this.capacity = capacity; + this.array = []; + this.array.length = this.capacity; + this.length = 0; + } + + private grow() { + const old = this.array; + this.capacity *= 2; + this.array = []; + this.array.length = this.capacity; + + let i = 0; + for (; i < this.length; ++i) { + this.array[i] = old[i]; + } + } + + // ShiftRight manages the size of the array and shifts everything + // from array[idx] one to the right. Creating free space at array[idx]. + private shiftRight(idx: number) { + if (this.length == this.capacity) { + this.grow(); + } + + let i = this.length; + for (; i > idx; --i) { + this.array[i] = this.array[i - 1]; + } + this.length++; + } + + // ShiftLeft manages the size of the array and shifts everything to the + // right of array[idx] one to the left. Overwriting array[idx]. + private ShiftLeft(idx: number) { + this.length--; + let i = idx; + for (; i < this.length; ++i) { + this.array[i] = this.array[i + 1]; + } + } + + prepend(item: T): void { + this.shiftRight(0); + this.array[0] = item; + } + + insertAt(item: T, idx: number): void { + this.shiftRight(idx); + this.array[idx] = item; + } + + append(item: T): void { + if (this.length == this.capacity) { + this.grow(); + } + + this.array[this.length] = item; + this.length++; + } + + remove(item: T): T | undefined { + let i = 0; + for (; i < this.length; ++i) { + if (this.array[i] == item) { + break; + } + } + + // item was not found + if (i == this.length) { + return undefined; + } + + return this.removeAt(i); + } + + get(idx: number): T | undefined { + return idx >= this.length ? undefined : this.array[idx]; + } + + removeAt(idx: number): T | undefined { + const item = this.get(idx); + this.ShiftLeft(idx); + return item; + } +} diff --git a/src/day1/BFSGraphList.test.ts b/src/day1/BFSGraphList.test.ts new file mode 100644 index 0000000..d69aba8 --- /dev/null +++ b/src/day1/BFSGraphList.test.ts @@ -0,0 +1,8 @@ +import bfs from "@code/BFSGraphList"; +import { list2 } from "./graph"; + +test("bfs - graph", function () { + expect(bfs(list2, 0, 6)).toEqual([0, 1, 4, 5, 6]); + + expect(bfs(list2, 6, 0)).toEqual(null); +}); diff --git a/src/day1/BFSGraphList.ts b/src/day1/BFSGraphList.ts new file mode 100644 index 0000000..3e57809 --- /dev/null +++ b/src/day1/BFSGraphList.ts @@ -0,0 +1,45 @@ +export default function bfs( + graph: WeightedAdjacencyList, + source: number, + needle: number, +): number[] | null { + const seen = new Array(graph.length).fill(false); + const prev = new Array(graph.length).fill(-1); + + const queue: number[] = [source]; + seen[source] = true; + + while (queue.length > 0) { + const curr = queue.shift() as number; + + if (curr === needle) { + break; + } + + for (const edge of graph[curr]) { + const neighbor = edge.to; + + if (seen[neighbor]) { + continue; + } + + seen[neighbor] = true; + prev[neighbor] = curr; + queue.push(neighbor); + } + } + + if (!seen[needle]) { + return null; + } + + const path: number[] = []; + let curr = needle; + + while (curr !== -1) { + path.push(curr); + curr = prev[curr]; + } + + return path.reverse(); +} diff --git a/src/day1/BFSGraphMatrix.test.ts b/src/day1/BFSGraphMatrix.test.ts new file mode 100644 index 0000000..c4976ad --- /dev/null +++ b/src/day1/BFSGraphMatrix.test.ts @@ -0,0 +1,8 @@ +import bfs from "@code/BFSGraphMatrix"; +import { matrix2 } from "./graph"; + +test("bfs - graph matrix", function () { + expect(bfs(matrix2, 0, 6)).toEqual([0, 1, 4, 5, 6]); + + expect(bfs(matrix2, 6, 0)).toEqual(null); +}); diff --git a/src/day1/BFSGraphMatrix.ts b/src/day1/BFSGraphMatrix.ts new file mode 100644 index 0000000..2593a07 --- /dev/null +++ b/src/day1/BFSGraphMatrix.ts @@ -0,0 +1,43 @@ +export default function bfs( + graph: number[][], + source: number, + needle: number, +): number[] | null { + const seen = new Array(graph.length).fill(false); + const prev = new Array(graph.length).fill(-1); + const q: number[] = [source]; + seen[source] = true; + + do { + const curr = q.shift() as number; + + if (curr === needle) { + break; + } + + const adjs = graph[curr]; + for (let i = 0; i < graph.length; i++) { + if (adjs[i] === 0 || seen[i]) { + continue; + } + + seen[i] = true; + prev[i] = curr; + q.push(i); + } + } while (q.length); + + if (prev[needle] === -1) { + return null; + } + + let curr = needle; + const out: number[] = []; + + while (prev[curr] !== -1) { + out.push(curr); + curr = prev[curr]; + } + + return [source].concat(out.reverse()); +} diff --git a/src/day1/BTBFS.test.ts b/src/day1/BTBFS.test.ts new file mode 100644 index 0000000..6d2cabd --- /dev/null +++ b/src/day1/BTBFS.test.ts @@ -0,0 +1,8 @@ +import bfs from "@code/BTBFS"; +import { tree } from "./tree"; + +test("bt bfs", function () { + expect(bfs(tree, 45)).toEqual(true); + expect(bfs(tree, 7)).toEqual(true); + expect(bfs(tree, 69)).toEqual(false); +}); diff --git a/src/day1/BTBFS.ts b/src/day1/BTBFS.ts new file mode 100644 index 0000000..6cfb250 --- /dev/null +++ b/src/day1/BTBFS.ts @@ -0,0 +1,20 @@ +export default function bfs(head: BinaryNode, needle: number): boolean { + const q: (BinaryNode | null)[] = [head]; + + while (q.length) { + const curr = q.shift() as BinaryNode | undefined | null; + if (!curr) { + continue; + } + + // search + if (curr.value === needle) { + return true; + } + + q.push(curr.left); + q.push(curr.right); + } + + return false; +} diff --git a/src/day1/BTInOrder.test.ts b/src/day1/BTInOrder.test.ts new file mode 100644 index 0000000..0796572 --- /dev/null +++ b/src/day1/BTInOrder.test.ts @@ -0,0 +1,6 @@ +import bt_in_order from "@code/BTInOrder"; +import { tree } from "./tree"; + +test("In order", function () { + expect(bt_in_order(tree)).toEqual([5, 7, 10, 15, 20, 29, 30, 45, 50, 100]); +}); diff --git a/src/day1/BTInOrder.ts b/src/day1/BTInOrder.ts new file mode 100644 index 0000000..189d4a7 --- /dev/null +++ b/src/day1/BTInOrder.ts @@ -0,0 +1,17 @@ +function walk(curr: BinaryNode | null, path: number[]): number[] { + if (!curr) { + return path; + } + + // recurse + walk(curr.left, path); + path.push(curr.value); + walk(curr.right, path); + + // post + return path; +} + +export default function in_order_search(head: BinaryNode): number[] { + return walk(head, []); +} diff --git a/src/day1/BTPostOrder.test.ts b/src/day1/BTPostOrder.test.ts new file mode 100644 index 0000000..60468e7 --- /dev/null +++ b/src/day1/BTPostOrder.test.ts @@ -0,0 +1,8 @@ +import bt_post_order from "@code/BTPostOrder"; +import { tree } from "./tree"; + +test("post order", function () { + expect(bt_post_order(tree)).toEqual([ + 7, 5, 15, 10, 29, 45, 30, 100, 50, 20, + ]); +}); diff --git a/src/day1/BTPostOrder.ts b/src/day1/BTPostOrder.ts new file mode 100644 index 0000000..55ea232 --- /dev/null +++ b/src/day1/BTPostOrder.ts @@ -0,0 +1,17 @@ +function walk(curr: BinaryNode | null, path: number[]): number[] { + if (!curr) { + return path; + } + + // recurse + walk(curr.left, path); + walk(curr.right, path); + + // post + path.push(curr.value); + return path; +} + +export default function post_order_search(head: BinaryNode): number[] { + return walk(head, []); +} diff --git a/src/day1/BTPreOrder.test.ts b/src/day1/BTPreOrder.test.ts new file mode 100644 index 0000000..2fc74e0 --- /dev/null +++ b/src/day1/BTPreOrder.test.ts @@ -0,0 +1,6 @@ +import bt_pre_order from "@code/BTPreOrder"; +import { tree } from "./tree"; + +test("Pre order", function () { + expect(bt_pre_order(tree)).toEqual([20, 10, 5, 7, 15, 50, 30, 29, 45, 100]); +}); diff --git a/src/day1/BTPreOrder.ts b/src/day1/BTPreOrder.ts new file mode 100644 index 0000000..10e6482 --- /dev/null +++ b/src/day1/BTPreOrder.ts @@ -0,0 +1,19 @@ +function walk(curr: BinaryNode | null, path: number[]): number[] { + if (!curr) { + return path; + } + + // pre + path.push(curr.value); + + // recurse + walk(curr.left, path); + walk(curr.right, path); + + // post + return path; +} + +export default function pre_order_search(head: BinaryNode): number[] { + return walk(head, []); +} diff --git a/src/day1/BinarySearchList.test.ts b/src/day1/BinarySearchList.test.ts new file mode 100644 index 0000000..447c8dc --- /dev/null +++ b/src/day1/BinarySearchList.test.ts @@ -0,0 +1,11 @@ +import binary_fn from "@code/BinarySearchList"; + +test("binary search array", function () { + const foo = [1, 3, 4, 69, 71, 81, 90, 99, 420, 1337, 69420]; + expect(binary_fn(foo, 69)).toEqual(true); + expect(binary_fn(foo, 1336)).toEqual(false); + expect(binary_fn(foo, 69420)).toEqual(true); + expect(binary_fn(foo, 69421)).toEqual(false); + expect(binary_fn(foo, 1)).toEqual(true); + expect(binary_fn(foo, 0)).toEqual(false); +}); diff --git a/src/day1/BinarySearchList.ts b/src/day1/BinarySearchList.ts new file mode 100644 index 0000000..1ee479c --- /dev/null +++ b/src/day1/BinarySearchList.ts @@ -0,0 +1,19 @@ +export default function bs_list(haystack: number[], needle: number): boolean { + let lo = 0; + let hi = haystack.length; + + while (lo < hi) { + const m = Math.floor(lo + (hi - lo) / 2); + const v = haystack[m]; + + if (v === needle) { + return true; + } else if (v > needle) { + hi = m; + } else { + lo = m + 1; + } + } + + return false; +} diff --git a/src/day1/BubbleSort.test.ts b/src/day1/BubbleSort.test.ts new file mode 100644 index 0000000..050b1e7 --- /dev/null +++ b/src/day1/BubbleSort.test.ts @@ -0,0 +1,9 @@ +import bubble_sort from "@code/BubbleSort"; + +test("bubble-sort", function () { + const arr = [9, 3, 7, 4, 69, 420, 42]; + + debugger; + bubble_sort(arr); + expect(arr).toEqual([3, 4, 7, 9, 42, 69, 420]); +}); diff --git a/src/day1/BubbleSort.ts b/src/day1/BubbleSort.ts new file mode 100644 index 0000000..591ed75 --- /dev/null +++ b/src/day1/BubbleSort.ts @@ -0,0 +1,11 @@ +export default function bubble_sort(arr: number[]): void { + for (let i = 0; i < arr.length; i++) { + for (let j = 0; j < arr.length - 1 - i; j++) { + if (arr[j] > arr[j + 1]) { + const tmp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = tmp; + } + } + } +} diff --git a/src/day1/CompareBinaryTrees.test.ts b/src/day1/CompareBinaryTrees.test.ts new file mode 100644 index 0000000..5395af6 --- /dev/null +++ b/src/day1/CompareBinaryTrees.test.ts @@ -0,0 +1,7 @@ +import compare from "@code/CompareBinaryTrees"; +import { tree, tree2 } from "./tree"; + +test("Compare Binary Trees", function () { + expect(compare(tree, tree)).toEqual(true); + expect(compare(tree, tree2)).toEqual(false); +}); diff --git a/src/day1/CompareBinaryTrees.ts b/src/day1/CompareBinaryTrees.ts new file mode 100644 index 0000000..f945127 --- /dev/null +++ b/src/day1/CompareBinaryTrees.ts @@ -0,0 +1,21 @@ +export default function compare( + a: BinaryNode | null, + b: BinaryNode | null, +): boolean { + // structual check + if (a === null && b === null) { + return true; + } + + // structual check + if (a === null || b === null) { + return false; + } + + // value check + if (a?.value !== b?.value) { + return false; + } + + return compare(a.left, b.left) && compare(a.right, b.right); +} diff --git a/src/day1/DFSGraphList.test.ts b/src/day1/DFSGraphList.test.ts new file mode 100644 index 0000000..b9c3a55 --- /dev/null +++ b/src/day1/DFSGraphList.test.ts @@ -0,0 +1,8 @@ +import dfs from "@code/DFSGraphList"; +import { list2 } from "./graph"; + +test("dfs - graph", function () { + expect(dfs(list2, 0, 6)).toEqual([0, 1, 4, 5, 6]); + + expect(dfs(list2, 6, 0)).toEqual(null); +}); diff --git a/src/day1/DFSGraphList.ts b/src/day1/DFSGraphList.ts new file mode 100644 index 0000000..0aa215b --- /dev/null +++ b/src/day1/DFSGraphList.ts @@ -0,0 +1,50 @@ +function walk( + graph: WeightedAdjacencyList, + curr: number, + needle: number, + seen: boolean[], + path: number[], +): boolean { + if (seen[curr]) { + return false; + } + + seen[curr] = true; + + // pre + path.push(curr); + if (curr === needle) { + return true; + } + + // recurse + const list = graph[curr]; + for (let i = 0; i < list.length; i++) { + const edge = list[i]; + + if (walk(graph, edge.to, needle, seen, path)) { + return true; + } + } + + // post + path.pop(); + + return false; +} + +export default function dfs( + graph: WeightedAdjacencyList, + source: number, + needle: number, +): number[] | null { + const seen: boolean[] = new Array(graph.length).fill(false); + const path: number[] = []; + walk(graph, source, needle, seen, path); + + if (path.length === 0) { + return null; + } + + return path; +} diff --git a/src/day1/DFSOnBST.test.ts b/src/day1/DFSOnBST.test.ts new file mode 100644 index 0000000..b5dd152 --- /dev/null +++ b/src/day1/DFSOnBST.test.ts @@ -0,0 +1,8 @@ +import dfs from "@code/DFSOnBST"; +import { tree } from "./tree"; + +test("DFS on BST", function () { + expect(dfs(tree, 45)).toEqual(true); + expect(dfs(tree, 7)).toEqual(true); + expect(dfs(tree, 69)).toEqual(false); +}); diff --git a/src/day1/DFSOnBST.ts b/src/day1/DFSOnBST.ts new file mode 100644 index 0000000..fe6e8ae --- /dev/null +++ b/src/day1/DFSOnBST.ts @@ -0,0 +1,19 @@ +function search(curr: BinaryNode | null, needle: number): boolean { + if (!curr) { + return false; + } + + if (curr.value === needle) { + return true; + } + + if (curr.value < needle) { + return search(curr.right, needle); + } + + return search(curr.left, needle); +} + +export default function dfs(head: BinaryNode, needle: number): boolean { + return search(head, needle); +} diff --git a/src/day1/DijkstraList.test.ts b/src/day1/DijkstraList.test.ts new file mode 100644 index 0000000..c0f2836 --- /dev/null +++ b/src/day1/DijkstraList.test.ts @@ -0,0 +1,9 @@ +import dijkstra_list from "@code/DijkstraList"; +import { list1 } from "./graph"; + +test("dijkstra via adj list", function () { + /// waht? + // what.. + // what... + expect(dijkstra_list(0, 6, list1)).toEqual([0, 1, 4, 5, 6]); +}); diff --git a/src/day1/DijkstraList.ts b/src/day1/DijkstraList.ts new file mode 100644 index 0000000..d1bb720 --- /dev/null +++ b/src/day1/DijkstraList.ts @@ -0,0 +1,61 @@ +function hasUnvisited(seen: boolean[], dists: number[]): boolean { + return seen.some((s, i) => !s && dists[i] < Infinity); +} + +function getLowestUnvisited(seen: boolean[], dists: number[]): number { + let idx = -1; + let lowestDistance = Infinity; + + for (let i = 0; i < seen.length; i++) { + if (seen[i]) { + continue; + } + + if (lowestDistance > dists[i]) { + lowestDistance = dists[i]; + idx = i; + } + } + + return idx; +} + +export default function dijkstra_list( + source: number, + sink: number, + arr: WeightedAdjacencyList, +): number[] { + const seen = new Array(arr.length).fill(false); + const prev = new Array(arr.length).fill(-1); + const dists = new Array(arr.length).fill(Infinity); + dists[source] = 0; + + while (hasUnvisited(seen, dists)) { + const curr = getLowestUnvisited(seen, dists); + seen[curr] = true; + + const adjs = arr[curr]; + for (let i = 0; i < adjs.length; i++) { + const edge = adjs[i]; + if (seen[edge.to]) { + continue; + } + + const dist = dists[curr] + edge.weight; + if (dist < dists[edge.to]) { + dists[edge.to] = dist; + prev[edge.to] = curr; + } + } + } + + let curr = sink; + const out: number[] = []; + + while (prev[curr] !== -1) { + out.push(curr); + curr = prev[curr]; + } + + return [source].concat(out.reverse()); +} diff --git a/src/day1/DoublyLinkedList.test.ts b/src/day1/DoublyLinkedList.test.ts new file mode 100644 index 0000000..e0e5cfc --- /dev/null +++ b/src/day1/DoublyLinkedList.test.ts @@ -0,0 +1,7 @@ +import LinkedList from "@code/DoublyLinkedList"; +import { test_list } from "./ListTest"; + +test("DoublyLinkedList", function () { + const list = new LinkedList(); + test_list(list); +}); diff --git a/src/day1/DoublyLinkedList.ts b/src/day1/DoublyLinkedList.ts new file mode 100644 index 0000000..1f4f335 --- /dev/null +++ b/src/day1/DoublyLinkedList.ts @@ -0,0 +1,136 @@ +class Node { + public value: T; + public prev?: Node; + public next?: Node; +} + +export default class DoublyLinkedList { + public length: number; + public head?: Node; + public tail?: Node; + + constructor() { + this.length = 0; + this.head = undefined; + } + + prepend(item: T): void { + const node = { value: item } as Node; + this.length++; + + if (!this.head) { + this.head = node; + this.tail = node; + return; + } + + node.next = this.head; + this.head.prev = node; + this.head = node; + } + + insertAt(item: T, idx: number): void { + if (idx > this.length) { + throw new Error("oh no"); + } else if (idx === this.length) { + this.append(item); + return; + } else if (idx === 0) { + this.prepend(item); + } + + this.length++; + const curr = this.getAt(idx) as Node; + const node = { value: item } as Node; + + node.next = curr; + node.prev = curr.prev; + curr.prev = node; + + if (node.prev) { + node.prev.next = node; + } + } + + append(item: T): void { + const node = { value: item } as Node; + this.length++; + + if (!this.tail) { + this.head = node; + this.tail = node; + return; + } + + node.prev = this.tail; + this.tail.next = node; + this.tail = node; + } + + remove(item: T): T | undefined { + let curr = this.head; + for (let i = 0; curr && i < this.length; i++) { + if (curr.value === item) { + break; + } + curr = curr.next; + } + + if (!curr) { + return undefined; + } + + return this.removeNode(curr); + } + + get(idx: number): T | undefined { + return this.getAt(idx)?.value; + } + + removeAt(idx: number): T | undefined { + const node = this.getAt(idx); + + if (!node) { + return undefined; + } + return this.removeNode(node); + } + + private removeNode(node: Node): T | undefined { + this.length--; + + if (this.length === 0) { + const out = this.head?.value; + this.head = undefined; + this.tail = undefined; + return out; + } + + if (node.prev) { + node.prev.next = node.next; + } + if (node.next) { + node.next.prev = node.prev; + } + + if (node === this.head) { + this.head = node.next; + } + if (node === this.tail) { + this.tail = node.prev; + } + + node.prev = undefined; + node.next = undefined; + + return node.value; + } + + private getAt(idx: number): Node | undefined { + let curr = this.head; + for (let i = 0; curr && i < idx; i++) { + curr = curr.next; + } + return curr; + } +} diff --git a/src/day1/InsertionSort.test.ts b/src/day1/InsertionSort.test.ts new file mode 100644 index 0000000..76273ce --- /dev/null +++ b/src/day1/InsertionSort.test.ts @@ -0,0 +1,9 @@ +import insertion_sort from "@code/InsertionSort"; + +test("insertion-sort", function () { + const arr = [9, 3, 7, 4, 69, 420, 42]; + debugger; + // where is my debugger + insertion_sort(arr); + expect(arr).toEqual([3, 4, 7, 9, 42, 69, 420]); +}); diff --git a/src/day1/InsertionSort.ts b/src/day1/InsertionSort.ts new file mode 100644 index 0000000..46e4fdb --- /dev/null +++ b/src/day1/InsertionSort.ts @@ -0,0 +1,13 @@ +export default function insertion_sort(arr: number[]): void { + for (let i = 1; i < arr.length; i++) { + const key = arr[i]; + let j = i - 1; + + while (j >= 0 && arr[j] > key) { + arr[j + 1] = arr[j]; + j--; + } + + arr[j + 1] = key; + } +} diff --git a/src/day1/LRU.test.ts b/src/day1/LRU.test.ts new file mode 100644 index 0000000..ebb601c --- /dev/null +++ b/src/day1/LRU.test.ts @@ -0,0 +1,27 @@ +import LRU from "@code/LRU"; + +test("LRU", function () { + const lru = new LRU(3) as ILRU; + + expect(lru.get("foo")).toEqual(undefined); + lru.update("foo", 69); + expect(lru.get("foo")).toEqual(69); + + lru.update("bar", 420); + expect(lru.get("bar")).toEqual(420); + + lru.update("baz", 1337); + expect(lru.get("baz")).toEqual(1337); + + lru.update("ball", 69420); + expect(lru.get("ball")).toEqual(69420); + expect(lru.get("foo")).toEqual(undefined); + expect(lru.get("bar")).toEqual(420); + lru.update("foo", 69); + expect(lru.get("bar")).toEqual(420); + expect(lru.get("foo")).toEqual(69); + + // shouldn't of been deleted, but since bar was get'd, bar was added to the + // front of the list, so baz became the end + expect(lru.get("baz")).toEqual(undefined); +}); diff --git a/src/day1/LRU.ts b/src/day1/LRU.ts new file mode 100644 index 0000000..ab09525 --- /dev/null +++ b/src/day1/LRU.ts @@ -0,0 +1,99 @@ +function createNode(value: V): Node { + return { value }; +} + +export default class LRU { + private length: number; + private capacity: number; + private head?: Node; + private tail?: Node; + private lookup: Map>; + private reverseLookup: Map, K>; + + constructor(capacity: number) { + this.length = 0; + this.capacity = capacity; + this.head = this.tail = undefined; + this.lookup = new Map>(); + this.reverseLookup = new Map, K>(); + } + + update(key: K, value: V): void { + // check the cache for existence + let node = this.lookup.get(key); + if (!node) { + node = createNode(value); + this.length++; + this.prepend(node); + this.trimCache(); + + this.lookup.set(key, node); + this.reverseLookup.set(node, key); + } else { + this.detach(node); + this.prepend(node); + node.value = value; + } + } + + get(key: K): V | undefined { + // check the cache for existence + const node = this.lookup.get(key); + if (!node) { + return undefined; + } + + // update the value we found and move it to the front + this.detach(node); + this.prepend(node); + + // return out the value found + return node.value; + } + + private detach(node: Node): void { + if (node.prev) { + node.prev.next = node.next; + } + + if (node.next) { + node.next.prev = node.prev; + } + + if (this.head === node) { + this.head = this.head.next; + } + + if (this.tail === node) { + this.tail = this.tail.prev; + } + + node.next = undefined; + node.prev = undefined; + } + + private prepend(node: Node): void { + if (!this.head) { + this.head = this.tail = node; + return; + } + + node.next = this.head; + this.head.prev = node; + this.head = node; + } + + private trimCache(): void { + if (this.length <= this.capacity) { + return; + } + + const tail = this.tail as Node; + this.detach(this.tail as Node); + + const key = this.reverseLookup.get(tail) as K; + this.lookup.delete(key); + this.reverseLookup.delete(tail); + this.length--; + } +} diff --git a/src/day1/LinearSearchList.test.ts b/src/day1/LinearSearchList.test.ts new file mode 100644 index 0000000..35a7292 --- /dev/null +++ b/src/day1/LinearSearchList.test.ts @@ -0,0 +1,11 @@ +import linear_fn from "@code/LinearSearchList"; + +test("linear search array", function () { + const foo = [1, 3, 4, 69, 71, 81, 90, 99, 420, 1337, 69420]; + expect(linear_fn(foo, 69)).toEqual(true); + expect(linear_fn(foo, 1336)).toEqual(false); + expect(linear_fn(foo, 69420)).toEqual(true); + expect(linear_fn(foo, 69421)).toEqual(false); + expect(linear_fn(foo, 1)).toEqual(true); + expect(linear_fn(foo, 0)).toEqual(false); +}); diff --git a/src/day1/LinearSearchList.ts b/src/day1/LinearSearchList.ts new file mode 100644 index 0000000..1252d89 --- /dev/null +++ b/src/day1/LinearSearchList.ts @@ -0,0 +1,12 @@ +export default function linear_search( + haystack: number[], + needle: number, +): boolean { + for (let i = 0; i < haystack.length; i++) { + if (haystack[i] === needle) { + return true; + } + } + + return false; +} diff --git a/src/day1/ListTest.ts b/src/day1/ListTest.ts new file mode 100644 index 0000000..91ac951 --- /dev/null +++ b/src/day1/ListTest.ts @@ -0,0 +1,26 @@ +export function test_list(list: List): void { + list.append(5); + list.append(7); + list.append(9); + + expect(list.get(2)).toEqual(9); + expect(list.removeAt(1)).toEqual(7); + expect(list.length).toEqual(2); + + list.append(11); + expect(list.removeAt(1)).toEqual(9); + expect(list.remove(9)).toEqual(undefined); + expect(list.removeAt(0)).toEqual(5); + expect(list.removeAt(0)).toEqual(11); + expect(list.length).toEqual(0); + + list.prepend(5); + list.prepend(7); + list.prepend(9); + + expect(list.get(2)).toEqual(5); + expect(list.get(0)).toEqual(9); + expect(list.remove(9)).toEqual(9); + expect(list.length).toEqual(2); + expect(list.get(0)).toEqual(7); +} diff --git a/src/day1/Map.test.ts b/src/day1/Map.test.ts new file mode 100644 index 0000000..f914304 --- /dev/null +++ b/src/day1/Map.test.ts @@ -0,0 +1,23 @@ +import MyMap from "@code/Map"; + +test("Map", function () { + const map = new MyMap(); + map.set("foo", 55); + expect(map.size()).toEqual(1); + map.set("fool", 75); + expect(map.size()).toEqual(2); + map.set("foolish", 105); + expect(map.size()).toEqual(3); + map.set("bar", 69); + expect(map.size()).toEqual(4); + + expect(map.get("bar")).toEqual(69); + expect(map.get("blaz")).toEqual(undefined); + + map.delete("barblabr"); + expect(map.size()).toEqual(4); + + map.delete("bar"); + expect(map.size()).toEqual(3); + expect(map.get("bar")).toEqual(undefined); +}); diff --git a/src/day1/Map.ts b/src/day1/Map.ts new file mode 100644 index 0000000..31256df --- /dev/null +++ b/src/day1/Map.ts @@ -0,0 +1,34 @@ +export default class Map { + private store: { [key: string]: V }; + private count: number; + + constructor() { + this.store = {}; + this.count = 0; + } + + get(key: T): V | undefined { + return this.store.hasOwnProperty(key) ? this.store[key] : undefined; + } + + set(key: T, value: V): void { + if (!this.store.hasOwnProperty(key)) { + this.count++; + } + this.store[key] = value; + } + + delete(key: T): V | undefined { + if (this.store.hasOwnProperty(key)) { + const value = this.store[key]; + delete this.store[key]; + this.count--; + return value; + } + return undefined; + } + + size(): number { + return this.count; + } +} diff --git a/src/day1/MazeSolver.test.ts b/src/day1/MazeSolver.test.ts new file mode 100644 index 0000000..ccc7a32 --- /dev/null +++ b/src/day1/MazeSolver.test.ts @@ -0,0 +1,44 @@ +import maze_solver from "@code/MazeSolver"; + +test("maze solver", function () { + const maze = [ + "xxxxxxxxxx x", + "x x x", + "x x x", + "x xxxxxxxx x", + "x x", + "x xxxxxxxxxx", + ]; + + const mazeResult = [ + { x: 10, y: 0 }, + { x: 10, y: 1 }, + { x: 10, y: 2 }, + { x: 10, y: 3 }, + { x: 10, y: 4 }, + { x: 9, y: 4 }, + { x: 8, y: 4 }, + { x: 7, y: 4 }, + { x: 6, y: 4 }, + { x: 5, y: 4 }, + { x: 4, y: 4 }, + { x: 3, y: 4 }, + { x: 2, y: 4 }, + { x: 1, y: 4 }, + { x: 1, y: 5 }, + ]; + + // there is only one path through + const result = maze_solver(maze, "x", { x: 10, y: 0 }, { x: 1, y: 5 }); + expect(drawPath(maze, result)).toEqual(drawPath(maze, mazeResult)); +}); + +function drawPath(data: string[], path: Point[]) { + const data2 = data.map((row) => row.split("")); + path.forEach((p) => { + if (data2[p.y] && data2[p.y][p.x]) { + data2[p.y][p.x] = "*"; + } + }); + return data2.map((d) => d.join("")); +} diff --git a/src/day1/MazeSolver.ts b/src/day1/MazeSolver.ts new file mode 100644 index 0000000..0b795b7 --- /dev/null +++ b/src/day1/MazeSolver.ts @@ -0,0 +1,57 @@ +export default function solve( + maze: string[], + wall: string, + start: Point, + end: Point, +): Point[] { + const numRows = maze.length; + const numCols = maze[0].length; + const visited = new Set(); + const queue: { point: Point; path: Point[] }[] = []; + + function isValid(x: number, y: number): boolean { + return ( + x >= 0 && + x < numCols && + y >= 0 && + y < numRows && + maze[y][x] !== wall + ); + } + + const key = (p: Point) => `${p.x},${p.y}`; + + queue.push({ point: start, path: [start] }); + visited.add(key(start)); + + const directions = [ + // up + { x: 0, y: -1 }, + // right + { x: 1, y: 0 }, + // down + { x: 0, y: 1 }, + // left + { x: -1, y: 0 }, + ]; + + while (queue.length > 0) { + const { point, path } = queue.shift()!; + if (point.x === end.x && point.y === end.y) { + return path; + } + + for (const dir of directions) { + const next = { x: point.x + dir.x, y: point.y + dir.y }; + const nextKey = key(next); + + if (isValid(next.x, next.y) && !visited.has(nextKey)) { + visited.add(nextKey); + queue.push({ point: next, path: [...path, next] }); + } + } + } + + // No path found + return []; +} diff --git a/src/day1/MergeSort.test.ts b/src/day1/MergeSort.test.ts new file mode 100644 index 0000000..0ffcdb1 --- /dev/null +++ b/src/day1/MergeSort.test.ts @@ -0,0 +1,7 @@ +import merge_sort from "@code/MergeSort"; + +test("merge-sort", function () { + const arr = [9, 3, 7, 4, 69, 420, 42]; + merge_sort(arr); + expect(arr).toEqual([3, 4, 7, 9, 42, 69, 420]); +}); diff --git a/src/day1/MergeSort.ts b/src/day1/MergeSort.ts new file mode 100644 index 0000000..05281b4 --- /dev/null +++ b/src/day1/MergeSort.ts @@ -0,0 +1,36 @@ +function mergeSortHelper(arr: number[], start: number, end: number): void { + if (start >= end) { + return; + } + + const mid = Math.floor((start + end) / 2); + + mergeSortHelper(arr, start, mid); + mergeSortHelper(arr, mid + 1, end); + + merge(arr, start, mid, end); +} + +function merge(arr: number[], start: number, mid: number, end: number): void { + const left = arr.slice(start, mid + 1); + const right = arr.slice(mid + 1, end + 1); + + let i = 0; + let j = 0; + let k = start; + + while (i < left.length && j < right.length) { + arr[k++] = left[i] <= right[j] ? left[i++] : right[j++]; + } + + while (i < left.length) { + arr[k++] = left[i++]; + } + while (j < right.length) { + arr[k++] = right[j++]; + } +} + +export default function merge_sort(arr: number[]): void { + mergeSortHelper(arr, 0, arr.length - 1); +} diff --git a/src/day1/MinHeap.test.ts b/src/day1/MinHeap.test.ts new file mode 100644 index 0000000..54fc85b --- /dev/null +++ b/src/day1/MinHeap.test.ts @@ -0,0 +1,28 @@ +import MinHeap from "@code/MinHeap"; + +test("min heap", function () { + const heap = new MinHeap(); + + expect(heap.length).toEqual(0); + + heap.insert(5); + heap.insert(3); + heap.insert(69); + heap.insert(420); + heap.insert(4); + heap.insert(1); + heap.insert(8); + heap.insert(7); + + expect(heap.length).toEqual(8); + expect(heap.delete()).toEqual(1); + expect(heap.delete()).toEqual(3); + expect(heap.delete()).toEqual(4); + expect(heap.delete()).toEqual(5); + expect(heap.length).toEqual(4); + expect(heap.delete()).toEqual(7); + expect(heap.delete()).toEqual(8); + expect(heap.delete()).toEqual(69); + expect(heap.delete()).toEqual(420); + expect(heap.length).toEqual(0); +}); diff --git a/src/day1/MinHeap.ts b/src/day1/MinHeap.ts new file mode 100644 index 0000000..3229370 --- /dev/null +++ b/src/day1/MinHeap.ts @@ -0,0 +1,89 @@ +export default class MinHeap { + public length: number; + private data: number[]; + + constructor() { + this.data = []; + this.length = 0; + } + + insert(value: number): void { + this.data[this.length] = value; + this.heapifyUp(this.length); + this.length++; + } + + delete(): number { + if (this.length === 0) { + return -1; + } + + const out = this.data[0]; + this.length--; + + if (this.length === 0) { + this.data = []; + return out; + } + + this.data[0] = this.data[this.length]; + this.heapifyDown(0); + + return out; + } + + private heapifyDown(idx: number): void { + const lIdx = this.leftChild(idx); + const rIdx = this.rightChild(idx); + + if (idx >= this.length || lIdx >= this.length) { + return; + } + + const lV = this.data[lIdx]; + const rV = this.data[rIdx]; + const v = this.data[idx]; + + if (lV > rV && v > rV) { + this.data[idx] = rV; + this.data[rIdx] = v; + this.heapifyDown(rIdx); + } else if (rV > lV && v > lV) { + this.data[idx] = lV; + this.data[lIdx] = v; + this.heapifyDown(lIdx); + } else if (lV == rV && v > rV) { + this.data[idx] = rV; + this.data[rIdx] = v; + this.heapifyDown(rIdx); + } + } + + private heapifyUp(idx: number): void { + if (idx === 0) { + return; + } + + const p = this.parent(idx); + const parentV = this.data[p]; + const v = this.data[idx]; + + if (parentV > v) { + this.data[idx] = parentV; + this.data[p] = v; + this.heapifyUp(p); + } + } + + private parent(idx: number): number { + return Math.floor((idx - 1) / 2); + } + + private leftChild(idx: number): number { + return idx * 2 + 1; + } + + private rightChild(idx: number): number { + return idx * 2 + 2; + } +} diff --git a/src/day1/PrimsAlgorithm.ts b/src/day1/PrimsAlgorithm.ts new file mode 100644 index 0000000..1399c8d --- /dev/null +++ b/src/day1/PrimsAlgorithm.ts @@ -0,0 +1,58 @@ +export default function prims( + list: WeightedAdjacencyList, +): WeightedAdjacencyList | null { + const n = list.length; + if (n === 0) { + return null; + } + + const inMST = new Array(n).fill(false); + const mst: WeightedAdjacencyList = Array.from({ length: n }, () => []); + + const minEdge: { to: number; from: number; weight: number }[] = new Array( + n, + ).fill(null as any); + minEdge[0] = { to: 0, from: -1, weight: 0 }; + + for (let i = 0; i < n; i++) { + let u = -1; + + for (let v = 0; v < n; v++) { + if ( + !inMST[v] && + (u === -1 || + (minEdge[v] && minEdge[v].weight < minEdge[u].weight)) + ) { + u = v; + } + } + + if (u === -1 || minEdge[u] === null) { + return null; + } + + inMST[u] = true; + + const edge = minEdge[u]; + if (edge.from !== -1) { + mst[edge.from].push({ to: u, weight: edge.weight }); + mst[u].push({ to: edge.from, weight: edge.weight }); + } + + for (const neighbor of list[u]) { + if ( + !inMST[neighbor.to] && + (!minEdge[neighbor.to] || + neighbor.weight < minEdge[neighbor.to].weight) + ) { + minEdge[neighbor.to] = { + to: neighbor.to, + from: u, + weight: neighbor.weight, + }; + } + } + } + + return mst; +} diff --git a/src/day1/PrimsList.test.ts b/src/day1/PrimsList.test.ts new file mode 100644 index 0000000..26b92c3 --- /dev/null +++ b/src/day1/PrimsList.test.ts @@ -0,0 +1,30 @@ +import prims from "@code/PrimsAlgorithm"; +import { list1 } from "./graph"; + +test("PrimsAlgorithm", function () { + // there is only one right answer for this graph + expect(prims(list1)).toEqual([ + [ + { to: 2, weight: 1 }, + { to: 1, weight: 3 }, + ], + [ + { to: 0, weight: 3 }, + { to: 4, weight: 1 }, + ], + [{ to: 0, weight: 1 }], + [{ to: 6, weight: 1 }], + [ + { to: 1, weight: 1 }, + { to: 5, weight: 2 }, + ], + [ + { to: 4, weight: 2 }, + { to: 6, weight: 1 }, + ], + [ + { to: 5, weight: 1 }, + { to: 3, weight: 1 }, + ], + ]); +}); diff --git a/src/day1/Queue.test.ts b/src/day1/Queue.test.ts new file mode 100644 index 0000000..e1189ce --- /dev/null +++ b/src/day1/Queue.test.ts @@ -0,0 +1,31 @@ +import Queue from "@code/Queue"; + +test("queue", function () { + const list = new Queue(); + + list.enqueue(5); + list.enqueue(7); + list.enqueue(9); + + expect(list.deque()).toEqual(5); + expect(list.length).toEqual(2); + + // this must be wrong..? + debugger; + + // i hate using debuggers + list.enqueue(11); + debugger; + expect(list.deque()).toEqual(7); + expect(list.deque()).toEqual(9); + expect(list.peek()).toEqual(11); + expect(list.deque()).toEqual(11); + expect(list.deque()).toEqual(undefined); + expect(list.length).toEqual(0); + + // just wanted to make sure that I could not blow up myself when i remove + // everything + list.enqueue(69); + expect(list.peek()).toEqual(69); + expect(list.length).toEqual(1); +}); diff --git a/src/day1/Queue.ts b/src/day1/Queue.ts new file mode 100644 index 0000000..8a79f97 --- /dev/null +++ b/src/day1/Queue.ts @@ -0,0 +1,50 @@ +type Node = { + value: T; + next?: Node; +}; + +export default class Queue { + public length: number; + private head?: Node; + private tail?: Node; + + constructor() { + this.head = undefined; + this.tail = undefined; + this.length = 0; + } + + enqueue(item: T): void { + const node = { value: item } as Node; + this.length++; + if (!this.tail) { + this.head = node; + this.tail = node; + return; + } + + this.tail.next = node; + this.tail = node; + } + + deque(): T | undefined { + if (!this.head) { + return undefined; + } + + this.length--; + const head = this.head; + this.head = this.head.next; + head.next = undefined; + + if (this.length === 0) { + this.tail = undefined; + } + + return head.value; + } + + peek(): T | undefined { + return this.head?.value; + } +} diff --git a/src/day1/QuickSort.test.ts b/src/day1/QuickSort.test.ts new file mode 100644 index 0000000..ca777ec --- /dev/null +++ b/src/day1/QuickSort.test.ts @@ -0,0 +1,9 @@ +import quick_sort from "@code/QuickSort"; + +test("quick-sort", function () { + const arr = [9, 3, 7, 4, 69, 420, 42]; + + debugger; + quick_sort(arr); + expect(arr).toEqual([3, 4, 7, 9, 42, 69, 420]); +}); diff --git a/src/day1/QuickSort.ts b/src/day1/QuickSort.ts new file mode 100644 index 0000000..6354ca5 --- /dev/null +++ b/src/day1/QuickSort.ts @@ -0,0 +1,34 @@ +function qs(arr: number[], lo: number, hi: number): void { + if (lo >= hi) { + return; + } + + const pivotIdx = partition(arr, lo, hi); + + qs(arr, lo, pivotIdx - 1); + qs(arr, pivotIdx + 1, hi); +} + +function partition(arr: number[], lo: number, hi: number): number { + const pivot = arr[hi]; + let idx = lo - 1; + + for (let i = lo; i < hi; i++) { + if (arr[i] <= pivot) { + idx++; + const tmp = arr[i]; + arr[i] = arr[idx]; + arr[idx] = tmp; + } + } + + idx++; + arr[hi] = arr[idx]; + arr[idx] = pivot; + + return idx; +} + +export default function quick_sort(arr: number[]): void { + qs(arr, 0, arr.length - 1); +} diff --git a/src/day1/RingBuffer.test.ts b/src/day1/RingBuffer.test.ts new file mode 100644 index 0000000..6865c1b --- /dev/null +++ b/src/day1/RingBuffer.test.ts @@ -0,0 +1,22 @@ +import RingBuffer from "@code/RingBuffer"; + +test("RingBuffer", function () { + const buffer = new RingBuffer(); + + buffer.push(5); + expect(buffer.pop()).toEqual(5); + expect(buffer.pop()).toEqual(undefined); + + buffer.push(42); + buffer.push(9); + expect(buffer.pop()).toEqual(42); + expect(buffer.pop()).toEqual(9); + expect(buffer.pop()).toEqual(undefined); + + buffer.push(42); + buffer.push(9); + buffer.push(12); + expect(buffer.get(2)).toEqual(12); + expect(buffer.get(1)).toEqual(9); + expect(buffer.get(0)).toEqual(42); +}); diff --git a/src/day1/RingBuffer.ts b/src/day1/RingBuffer.ts new file mode 100644 index 0000000..c1cd737 --- /dev/null +++ b/src/day1/RingBuffer.ts @@ -0,0 +1,59 @@ +export default class RingBuffer { + private items: T[] = []; + private start: number = 0; + private end: number = 0; + private count: number = 0; + + constructor(initialCapacity: number = 4) { + this.items = new Array(initialCapacity); + } + + public get length(): number { + return this.count; + } + + push(item: T): void { + if (this.count === this.items.length) { + this.resize(); + } + + this.items[this.end] = item; + this.end = (this.end + 1) % this.items.length; + this.count++; + } + + pop(): T | undefined { + if (this.count === 0) { + return undefined; + } + + const item = this.items[this.start]; + this.items[this.start] = undefined as any; + this.start = (this.start + 1) % this.items.length; + this.count--; + + return item; + } + + get(idx: number): T | undefined { + if (idx < 0 || idx >= this.count) { + return undefined; + } + + const realIndex = (this.start + idx) % this.items.length; + return this.items[realIndex]; + } + + private resize(): void { + const newCapacity = this.items.length * 2 || 4; + const newItems = new Array(newCapacity); + + for (let i = 0; i < this.count; i++) { + newItems[i] = this.get(i)!; + } + + this.items = newItems; + this.start = 0; + this.end = this.count; + } +} diff --git a/src/day1/SinglyLinkedList.test.ts b/src/day1/SinglyLinkedList.test.ts new file mode 100644 index 0000000..afc8f61 --- /dev/null +++ b/src/day1/SinglyLinkedList.test.ts @@ -0,0 +1,7 @@ +import SinglyLinkedList from "@code/SinglyLinkedList"; +import { test_list } from "./ListTest"; + +test("linked-list", function () { + const list = new SinglyLinkedList(); + test_list(list); +}); diff --git a/src/day1/SinglyLinkedList.ts b/src/day1/SinglyLinkedList.ts new file mode 100644 index 0000000..0050a2e --- /dev/null +++ b/src/day1/SinglyLinkedList.ts @@ -0,0 +1,138 @@ +class Node { + public value: T; + public next?: Node; + + constructor(t: T) { + this.value = t; + } +} + +export default class SinglyLinkedList { + public length: number; + public head?: Node; + public tail?: Node; + + constructor() { + this.length = 0; + this.head = undefined; + } + + prepend(item: T): void { + let node = new Node(item); + if (this.head != null) { + node.next = this.head; + } + this.head = node; + this.length++; + } + + insertAt(item: T, idx: number): void { + let current_node = this.head; + let i = 0; + + while (current_node?.next != null && i < idx) { + current_node = current_node.next; + i += 1; + } + + if (current_node?.next != null) { + let node = new Node(item); + node.next = current_node.next; + current_node.next = node; + this.length++; + } + } + + append(item: T): void { + if (this.length == 0) { + let node = new Node(item); + this.head = node; + this.length++; + return; + } + + let current_node = this.head; + + while (current_node?.next != null) { + current_node = current_node.next; + } + + if (current_node != null) { + let node = new Node(item); + current_node.next = node; + this.length++; + } + } + + remove(item: T): T | undefined { + let current_node = this.head; + let prev_node = this.head; + let node_to_remove = null; + + while (current_node != null) { + if (current_node.value === item) { + node_to_remove = current_node; + break; + } + prev_node = current_node; + current_node = current_node.next; + } + + if (node_to_remove == this.head) { + this.head = node_to_remove.next; + this.length--; + } else if (prev_node?.next != null) { + prev_node.next = node_to_remove?.next; + this.length--; + } + + return current_node?.value; + } + + get(idx: number): T | undefined { + let current_node = this.head; + let i = 0; + + while (current_node != null && i < idx) { + current_node = current_node.next; + i += 1; + } + + return current_node?.value; + } + + removeAt(idx: number): T | undefined { + let current_node = this.head; + + if (idx == 0 && current_node != null) { + this.head = current_node.next; + this.length--; + return current_node.value; + } + + let i = 0; + while (current_node?.next != null && i < idx - 1) { + current_node = current_node.next; + i += 1; + } + + if (current_node?.next != null) { + let node_to_remove = current_node.next; + current_node.next = node_to_remove.next; + this.length--; + return node_to_remove.value; + } + + return undefined; + } + + debug() { + let current_node = this.head; + let result = ""; + while (current_node != null) { + result += ` ${current_node.value},`; + current_node = current_node.next; + } + console.log(result); + } +} diff --git a/src/day1/Stack.test.ts b/src/day1/Stack.test.ts new file mode 100644 index 0000000..1f82b59 --- /dev/null +++ b/src/day1/Stack.test.ts @@ -0,0 +1,25 @@ +import Stack from "@code/Stack"; + +test("stack", function () { + const list = new Stack(); + + list.push(5); + list.push(7); + list.push(9); + + expect(list.pop()).toEqual(9); + expect(list.length).toEqual(2); + + list.push(11); + expect(list.pop()).toEqual(11); + expect(list.pop()).toEqual(7); + expect(list.peek()).toEqual(5); + expect(list.pop()).toEqual(5); + expect(list.pop()).toEqual(undefined); + + // just wanted to make sure that I could not blow up myself when i remove + // everything + list.push(69); + expect(list.peek()).toEqual(69); + expect(list.length).toEqual(1); +}); diff --git a/src/day1/Stack.ts b/src/day1/Stack.ts new file mode 100644 index 0000000..2db2696 --- /dev/null +++ b/src/day1/Stack.ts @@ -0,0 +1,43 @@ +type Node = { + value: T; + prev?: Node; +}; + +export default class Stack { + public length: number; + private head?: Node; + + constructor() { + this.head = undefined; + this.length = 0; + } + + push(item: T): void { + const node = { value: item } as Node; + this.length++; + if (!this.head) { + this.head = node; + return; + } + + node.prev = this.head; + this.head = node; + } + + pop(): T | undefined { + this.length = Math.max(0, this.length - 1); + if (this.length === 0) { + const head = this.head; + this.head = undefined; + return head?.value; + } + + const head = this.head as Node; + this.head = head.prev; + return head?.value; + } + + peek(): T | undefined { + return this.head?.value; + } +} diff --git a/src/day1/Trie.test.ts b/src/day1/Trie.test.ts new file mode 100644 index 0000000..6d86c27 --- /dev/null +++ b/src/day1/Trie.test.ts @@ -0,0 +1,15 @@ +import Trie from "@code/Trie"; + +test("Trie", function () { + const trie = new Trie(); + trie.insert("foo"); + trie.insert("fool"); + trie.insert("foolish"); + trie.insert("bar"); + + expect(trie.find("fo").sort()).toEqual(["foo", "fool", "foolish"]); + + trie.delete("fool"); + + expect(trie.find("fo").sort()).toEqual(["foo", "foolish"]); +}); diff --git a/src/day1/Trie.ts b/src/day1/Trie.ts new file mode 100644 index 0000000..2f892ad --- /dev/null +++ b/src/day1/Trie.ts @@ -0,0 +1,86 @@ +type TrieNode = { + children: TrieNode[]; + isValue: boolean; + value?: string; +}; + +// Creates a new TrieNode with defaults +function createTrieNode() { + return { + children: [], + isValue: false, + }; +} + +// Char code for 'a'. +const start = "a".charCodeAt(0); + +// Returns the distance from 'a' which can be used to index into an array. +function getIdx(item: string, idx: number): number { + return item.toLowerCase().charCodeAt(idx) - start; +} + +export default class Trie { + private head: TrieNode; + + constructor() { + this.head = createTrieNode(); + } + + insert(item: string): void { + let current: TrieNode = this.head; + for (let i = 0; i < item.length; ++i) { + const letter = getIdx(item, i); + if (!current.children[letter]) { + current.children[letter] = createTrieNode(); + } + current = current.children[letter]; + } + + current.isValue = true; + current.value = item; + } + + delete(item: string): void { + let current: TrieNode = this.head; + for (let i = 0; current && i < item.length; ++i) { + current = current.children[getIdx(item, i)]; + } + + if (!current) { + return; + } + + current.value = undefined; + current.isValue = false; + } + + find(partial: string): string[] { + let current = this.head; + for (let i = 0; i < partial.length; ++i) { + current = current.children[getIdx(partial, i)]; + } + + return this.findRecursively(current, []); + } + + // Finds all the possible words to complete node. + private findRecursively( + node: TrieNode | undefined, + out: string[], + ): string[] { + if (!node) { + return out; + } + + if (node.isValue) { + out.push(node.value as string); + } + + for (let i = 0; i < node.children.length; ++i) { + this.findRecursively(node.children[i], out); + } + + return out; + } +} diff --git a/src/day1/TwoCrystalBalls.test.ts b/src/day1/TwoCrystalBalls.test.ts new file mode 100644 index 0000000..f9998fa --- /dev/null +++ b/src/day1/TwoCrystalBalls.test.ts @@ -0,0 +1,13 @@ +import two_crystal_balls from "@code/TwoCrystalBalls"; + +test("two crystal balls", function () { + let idx = Math.floor(Math.random() * 10000); + const data = new Array(10000).fill(false); + + for (let i = idx; i < 10000; ++i) { + data[i] = true; + } + + expect(two_crystal_balls(data)).toEqual(idx); + expect(two_crystal_balls(new Array(821).fill(false))).toEqual(-1); +}); diff --git a/src/day1/TwoCrystalBalls.ts b/src/day1/TwoCrystalBalls.ts new file mode 100644 index 0000000..c92b5bb --- /dev/null +++ b/src/day1/TwoCrystalBalls.ts @@ -0,0 +1,20 @@ +export default function two_crystal_balls(breaks: boolean[]): number { + const jmpAmount = Math.floor(Math.sqrt(breaks.length)); + + let i = jmpAmount; + for (; i < breaks.length; i += jmpAmount) { + if (breaks[i]) { + break; + } + } + + i -= jmpAmount; + + for (let j = 0; j < jmpAmount && i < breaks.length; j++, i++) { + if (breaks[i]) { + return i; + } + } + + return -1; +} diff --git a/src/day1/graph.ts b/src/day1/graph.ts new file mode 100644 index 0000000..104e081 --- /dev/null +++ b/src/day1/graph.ts @@ -0,0 +1,80 @@ +export const list1: WeightedAdjacencyList = []; + +// (1) --- (4) ---- (5) +// / | | /| +// (0) | ------|------- | +// \ |/ | | +// (2) --- (3) ---- (6) +list1[0] = [ + { to: 1, weight: 3 }, + { to: 2, weight: 1 }, +]; +list1[1] = [ + { to: 0, weight: 3 }, + { to: 2, weight: 4 }, + { to: 4, weight: 1 }, +]; +list1[2] = [ + { to: 1, weight: 4 }, + { to: 3, weight: 7 }, + { to: 0, weight: 1 }, +]; +list1[3] = [ + { to: 2, weight: 7 }, + { to: 4, weight: 5 }, + { to: 6, weight: 1 }, +]; +list1[4] = [ + { to: 1, weight: 1 }, + { to: 3, weight: 5 }, + { to: 5, weight: 2 }, +]; +list1[5] = [ + { to: 6, weight: 1 }, + { to: 4, weight: 2 }, + { to: 2, weight: 18 }, +]; +list1[6] = [ + { to: 3, weight: 1 }, + { to: 5, weight: 1 }, +]; + +export const list2: WeightedAdjacencyList = []; + +// >(1)<--->(4) ---->(5) +// / | /| +// (0) ------|------- | +// \ v v v +// >(2) --> (3) <----(6) +list2[0] = [ + { to: 1, weight: 3 }, + { to: 2, weight: 1 }, +]; +list2[1] = [{ to: 4, weight: 1 }]; +list2[2] = [{ to: 3, weight: 7 }]; +list2[3] = []; +list2[4] = [ + { to: 1, weight: 1 }, + { to: 3, weight: 5 }, + { to: 5, weight: 2 }, +]; +list2[5] = [ + { to: 2, weight: 18 }, + { to: 6, weight: 1 }, +]; +list2[6] = [{ to: 3, weight: 1 }]; + +// >(1)<--->(4) ---->(5) +// / | /| +// (0) ------|------- | +// \ v v v +// >(2) --> (3) <----(6) +export const matrix2: WeightedAdjacencyMatrix = [ + [0, 3, 1, 0, 0, 0, 0], // 0 + [0, 0, 0, 0, 1, 0, 0], + [0, 0, 7, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 5, 0, 2, 0], + [0, 0, 18, 0, 0, 0, 1], + [0, 0, 0, 1, 0, 0, 1], +]; diff --git a/src/day1/tree.ts b/src/day1/tree.ts new file mode 100644 index 0000000..83abd1c --- /dev/null +++ b/src/day1/tree.ts @@ -0,0 +1,87 @@ +export const tree: BinaryNode = { + value: 20, + right: { + value: 50, + right: { + value: 100, + right: null, + left: null, + }, + left: { + value: 30, + right: { + value: 45, + right: null, + left: null, + }, + left: { + value: 29, + right: null, + left: null, + }, + }, + }, + left: { + value: 10, + right: { + value: 15, + right: null, + left: null, + }, + left: { + value: 5, + right: { + value: 7, + right: null, + left: null, + }, + left: null, + }, + }, +}; + +export const tree2: BinaryNode = { + value: 20, + right: { + value: 50, + right: null, + left: { + value: 30, + right: { + value: 45, + right: { + value: 49, + left: null, + right: null, + }, + left: null, + }, + left: { + value: 29, + right: null, + left: { + value: 21, + right: null, + left: null, + }, + }, + }, + }, + left: { + value: 10, + right: { + value: 15, + right: null, + left: null, + }, + left: { + value: 5, + right: { + value: 7, + right: null, + left: null, + }, + left: null, + }, + }, +}; diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 0000000..9fe398b --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,52 @@ +declare type Point = { + x: number; + y: number; +}; + +declare type ListNode = { + value: T; + next?: ListNode; + prev?: ListNode; +}; + +declare interface List { + get length(): number; + removeAt(index: number): T | undefined; + remove(item: T): T | undefined; + get(index: number): T | undefined; + prepend(item: T): void; + append(item: T): void; + insertAt(item: T, idx: number): void; +} + +declare type CompleteGraphEdge = { from: number; to: number; weight: number }; +declare type GraphEdge = { to: number; weight: number }; +declare type WeightedAdjacencyList = GraphEdge[][]; +// A number means weight +declare type WeightedAdjacencyMatrix = number[][]; + +declare type AdjacencyList = number[][]; +// A 1 means connected +declare type AdjacencyMatrix = number[][]; + +declare type BinaryNode = { + value: T; + left: BinaryNode | null; + right: BinaryNode | null; +}; + +declare type GeneralNode = { + value: T; + children: GeneralNode[]; +}; + +declare interface ILRU { + update(key: K, value: V): void; + get(key: K): V | undefined; +} + +declare type BinaryNode = { + value: T; + left: BinaryNode | null; + right: BinaryNode | null; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8dfca91 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "outDir": "dist", + "allowJs": true, + "noImplicitAny": true, + "strictNullChecks": true, + "resolveJsonModule": true, + "noImplicitReturns": true, + "esModuleInterop": true, + "target": "esnext", + "module": "commonjs", + "baseUrl": "src", + "paths": { + "@code/*": ["day1/*"] + } + }, + "include": ["./src/**/*"], + "exclude": ["node_modules"] +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..91ec938 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "vitest/config"; +import path from "path"; + +export default defineConfig({ + resolve: { + alias: { + "@code": path.resolve(__dirname, "src/day1"), + }, + }, + test: { + globals: true, + environment: "node", + include: ["src/**/*.test.{ts,js}"], + }, +});