From fa7ab7dfa7b5cdbe3e631eeee6ba1dfe2fdfa22c Mon Sep 17 00:00:00 2001 From: monkey0722 Date: Tue, 14 Apr 2026 05:45:11 +0900 Subject: [PATCH 1/7] feat(math): add various mathematical functions and tests - Implement Euler's Totient Function in `eulerTotient.ts` - Add Extended Euclidean Algorithm and modular inverse in `extendedGcd.ts` - Create tests for Extended GCD and modular inverse in `extendedGcd.test.ts` - Implement factorial function in `factorial.ts` with corresponding tests - Add Fibonacci number calculation using matrix exponentiation in `fibMatrix.ts` with tests - Implement GCD function in `gcd.ts` and tests for various cases - Create Matrix class with operations (addition, multiplication, determinant, inverse) in `matrix.ts` and tests - Implement modular exponentiation function in `modPow.ts` with tests - Add prime factorization function in `primeFactors.ts` with tests - Implement Sieve of Eratosthenes for prime number generation in `sieveOfEratosthenes.ts` with tests - Update `tsconfig.json` to include all source files --- .../algorithms}/dp/coin-change/coinChange.test.ts | 0 {algorithms => src/algorithms}/dp/coin-change/coinChange.ts | 0 {algorithms => src/algorithms}/dp/knapsack/knapsack.test.ts | 0 {algorithms => src/algorithms}/dp/knapsack/knapsack.ts | 0 {algorithms => src/algorithms}/graph/a-star/aStar.test.ts | 0 {algorithms => src/algorithms}/graph/a-star/aStar.ts | 0 .../algorithms}/graph/bellman-ford/bellmanFordSearch.test.ts | 0 .../algorithms}/graph/bellman-ford/bellmanFordSearch.ts | 0 {algorithms => src/algorithms}/graph/bfs/bfs.test.ts | 0 {algorithms => src/algorithms}/graph/bfs/bfs.ts | 0 .../algorithms}/graph/dijkstra/dijkstra.test.ts | 0 {algorithms => src/algorithms}/graph/dijkstra/dijkstra.ts | 0 .../graph/topological-sort/topological-sort.test.ts | 0 .../algorithms}/graph/topological-sort/topological-sort.ts | 0 .../algorithms}/search/binary-search/binarySearch.test.ts | 0 .../algorithms}/search/binary-search/binarySearch.ts | 0 .../search/interpolation-search/interpolationSearch.test.ts | 0 .../search/interpolation-search/interpolationSearch.ts | 0 .../algorithms}/search/jump-search/jumpSearch.test.ts | 0 .../algorithms}/search/jump-search/jumpSearch.ts | 0 .../algorithms}/search/linear-search/linearSearch.test.ts | 0 .../algorithms}/search/linear-search/linearSearch.ts | 0 .../sorting/bubble-sort-counters/bubbleSortCounters.test.ts | 0 .../sorting/bubble-sort-counters/bubbleSortCounters.ts | 0 .../algorithms}/sorting/bubble-sort/bubbleSort.test.ts | 0 .../algorithms}/sorting/bubble-sort/bubbleSort.ts | 0 .../algorithms}/sorting/heap-sort/heapSort.test.ts | 0 {algorithms => src/algorithms}/sorting/heap-sort/heapSort.ts | 0 .../insertion-sort-counters/insertionSortCounters.test.ts | 0 .../sorting/insertion-sort-counters/insertionSortCounters.ts | 0 .../algorithms}/sorting/insertion-sort/insertionSort.test.ts | 0 .../algorithms}/sorting/insertion-sort/insertionSort.ts | 0 .../sorting/merge-sort-counters/mergeSortCounters.test.ts | 0 .../sorting/merge-sort-counters/mergeSortCounters.ts | 0 .../algorithms}/sorting/merge-sort/mergeSort.test.ts | 0 .../algorithms}/sorting/merge-sort/mergeSort.ts | 0 .../algorithms}/sorting/quick-sort/quickSort.test.ts | 0 .../algorithms}/sorting/quick-sort/quickSort.ts | 0 .../selection-sort-counters/selectionSortCounters.test.ts | 0 .../sorting/selection-sort-counters/selectionSortCounters.ts | 0 .../algorithms}/sorting/selection-sort/selectionSort.test.ts | 0 .../algorithms}/sorting/selection-sort/selectionSort.ts | 0 .../sorting/shell-sort-counters/shellSortCounters.test.ts | 0 .../sorting/shell-sort-counters/shellSortCounters.ts | 0 .../algorithms}/sorting/shell-sort/shellSort.test.ts | 0 .../algorithms}/sorting/shell-sort/shellSort.ts | 0 {algorithms => src/algorithms}/sorting/types.ts | 0 {algorithms => src/algorithms}/string/lcs/lcs.test.ts | 0 {algorithms => src/algorithms}/string/lcs/lcs.ts | 0 .../string/levenshtein-distance/levenshteinDistance.test.ts | 0 .../string/levenshtein-distance/levenshteinDistance.ts | 0 .../data-structures}/binary-tree/binaryTree.test.ts | 0 .../data-structures}/binary-tree/binaryTree.ts | 0 {data-structures => src/data-structures}/graph/graph.test.ts | 0 {data-structures => src/data-structures}/graph/graph.ts | 0 .../data-structures}/hash-table/hashTable.test.ts | 0 .../data-structures}/hash-table/hashTable.ts | 0 {data-structures => src/data-structures}/heap/minHeap.test.ts | 0 {data-structures => src/data-structures}/heap/minHeap.ts | 0 .../data-structures}/list-node/linkedList.test.ts | 0 .../data-structures}/list-node/linkedList.ts | 0 .../data-structures}/queue/circularQueue.test.ts | 0 .../data-structures}/queue/circularQueue.ts | 0 {data-structures => src/data-structures}/queue/queue.test.ts | 0 {data-structures => src/data-structures}/queue/queue.ts | 0 .../data-structures}/red-black-tree/redBlackTree.test.ts | 0 .../data-structures}/red-black-tree/redBlackTree.ts | 0 {data-structures => src/data-structures}/stack/stack.test.ts | 0 {data-structures => src/data-structures}/stack/stack.ts | 0 {data-structures => src/data-structures}/trie/trie.test.ts | 0 {data-structures => src/data-structures}/trie/trie.ts | 0 .../data-structures}/union-find/unionFind.test.ts | 0 .../data-structures}/union-find/unionFind.ts | 0 .../math}/binomial-coefficient/binomialCoefficient.test.ts | 0 .../math}/binomial-coefficient/binomialCoefficient.ts | 0 {math => src/math}/euler-totient/eulerTotient.test.ts | 0 {math => src/math}/euler-totient/eulerTotient.ts | 0 {math => src/math}/extended-gcd/extendedGcd.test.ts | 0 {math => src/math}/extended-gcd/extendedGcd.ts | 0 {math => src/math}/factorial/factorial.test.ts | 0 {math => src/math}/factorial/factorial.ts | 0 {math => src/math}/fib-matrix/fibMatrix.test.ts | 0 {math => src/math}/fib-matrix/fibMatrix.ts | 0 {math => src/math}/gcd/gcb.test.ts | 0 {math => src/math}/gcd/gcd.ts | 0 {math => src/math}/matrix/matrix.test.ts | 0 {math => src/math}/matrix/matrix.ts | 0 {math => src/math}/mod-pow/modPow.test.ts | 0 {math => src/math}/mod-pow/modPow.ts | 0 {math => src/math}/prime-factors/primeFactors.test.ts | 0 {math => src/math}/prime-factors/primeFactors.ts | 0 .../math}/sieve-of-eratosthenes/sieveOfEratosthenes.test.ts | 0 .../math}/sieve-of-eratosthenes/sieveOfEratosthenes.ts | 0 tsconfig.json | 4 +--- 94 files changed, 1 insertion(+), 3 deletions(-) rename {algorithms => src/algorithms}/dp/coin-change/coinChange.test.ts (100%) rename {algorithms => src/algorithms}/dp/coin-change/coinChange.ts (100%) rename {algorithms => src/algorithms}/dp/knapsack/knapsack.test.ts (100%) rename {algorithms => src/algorithms}/dp/knapsack/knapsack.ts (100%) rename {algorithms => src/algorithms}/graph/a-star/aStar.test.ts (100%) rename {algorithms => src/algorithms}/graph/a-star/aStar.ts (100%) rename {algorithms => src/algorithms}/graph/bellman-ford/bellmanFordSearch.test.ts (100%) rename {algorithms => src/algorithms}/graph/bellman-ford/bellmanFordSearch.ts (100%) rename {algorithms => src/algorithms}/graph/bfs/bfs.test.ts (100%) rename {algorithms => src/algorithms}/graph/bfs/bfs.ts (100%) rename {algorithms => src/algorithms}/graph/dijkstra/dijkstra.test.ts (100%) rename {algorithms => src/algorithms}/graph/dijkstra/dijkstra.ts (100%) rename {algorithms => src/algorithms}/graph/topological-sort/topological-sort.test.ts (100%) rename {algorithms => src/algorithms}/graph/topological-sort/topological-sort.ts (100%) rename {algorithms => src/algorithms}/search/binary-search/binarySearch.test.ts (100%) rename {algorithms => src/algorithms}/search/binary-search/binarySearch.ts (100%) rename {algorithms => src/algorithms}/search/interpolation-search/interpolationSearch.test.ts (100%) rename {algorithms => src/algorithms}/search/interpolation-search/interpolationSearch.ts (100%) rename {algorithms => src/algorithms}/search/jump-search/jumpSearch.test.ts (100%) rename {algorithms => src/algorithms}/search/jump-search/jumpSearch.ts (100%) rename {algorithms => src/algorithms}/search/linear-search/linearSearch.test.ts (100%) rename {algorithms => src/algorithms}/search/linear-search/linearSearch.ts (100%) rename {algorithms => src/algorithms}/sorting/bubble-sort-counters/bubbleSortCounters.test.ts (100%) rename {algorithms => src/algorithms}/sorting/bubble-sort-counters/bubbleSortCounters.ts (100%) rename {algorithms => src/algorithms}/sorting/bubble-sort/bubbleSort.test.ts (100%) rename {algorithms => src/algorithms}/sorting/bubble-sort/bubbleSort.ts (100%) rename {algorithms => src/algorithms}/sorting/heap-sort/heapSort.test.ts (100%) rename {algorithms => src/algorithms}/sorting/heap-sort/heapSort.ts (100%) rename {algorithms => src/algorithms}/sorting/insertion-sort-counters/insertionSortCounters.test.ts (100%) rename {algorithms => src/algorithms}/sorting/insertion-sort-counters/insertionSortCounters.ts (100%) rename {algorithms => src/algorithms}/sorting/insertion-sort/insertionSort.test.ts (100%) rename {algorithms => src/algorithms}/sorting/insertion-sort/insertionSort.ts (100%) rename {algorithms => src/algorithms}/sorting/merge-sort-counters/mergeSortCounters.test.ts (100%) rename {algorithms => src/algorithms}/sorting/merge-sort-counters/mergeSortCounters.ts (100%) rename {algorithms => src/algorithms}/sorting/merge-sort/mergeSort.test.ts (100%) rename {algorithms => src/algorithms}/sorting/merge-sort/mergeSort.ts (100%) rename {algorithms => src/algorithms}/sorting/quick-sort/quickSort.test.ts (100%) rename {algorithms => src/algorithms}/sorting/quick-sort/quickSort.ts (100%) rename {algorithms => src/algorithms}/sorting/selection-sort-counters/selectionSortCounters.test.ts (100%) rename {algorithms => src/algorithms}/sorting/selection-sort-counters/selectionSortCounters.ts (100%) rename {algorithms => src/algorithms}/sorting/selection-sort/selectionSort.test.ts (100%) rename {algorithms => src/algorithms}/sorting/selection-sort/selectionSort.ts (100%) rename {algorithms => src/algorithms}/sorting/shell-sort-counters/shellSortCounters.test.ts (100%) rename {algorithms => src/algorithms}/sorting/shell-sort-counters/shellSortCounters.ts (100%) rename {algorithms => src/algorithms}/sorting/shell-sort/shellSort.test.ts (100%) rename {algorithms => src/algorithms}/sorting/shell-sort/shellSort.ts (100%) rename {algorithms => src/algorithms}/sorting/types.ts (100%) rename {algorithms => src/algorithms}/string/lcs/lcs.test.ts (100%) rename {algorithms => src/algorithms}/string/lcs/lcs.ts (100%) rename {algorithms => src/algorithms}/string/levenshtein-distance/levenshteinDistance.test.ts (100%) rename {algorithms => src/algorithms}/string/levenshtein-distance/levenshteinDistance.ts (100%) rename {data-structures => src/data-structures}/binary-tree/binaryTree.test.ts (100%) rename {data-structures => src/data-structures}/binary-tree/binaryTree.ts (100%) rename {data-structures => src/data-structures}/graph/graph.test.ts (100%) rename {data-structures => src/data-structures}/graph/graph.ts (100%) rename {data-structures => src/data-structures}/hash-table/hashTable.test.ts (100%) rename {data-structures => src/data-structures}/hash-table/hashTable.ts (100%) rename {data-structures => src/data-structures}/heap/minHeap.test.ts (100%) rename {data-structures => src/data-structures}/heap/minHeap.ts (100%) rename {data-structures => src/data-structures}/list-node/linkedList.test.ts (100%) rename {data-structures => src/data-structures}/list-node/linkedList.ts (100%) rename {data-structures => src/data-structures}/queue/circularQueue.test.ts (100%) rename {data-structures => src/data-structures}/queue/circularQueue.ts (100%) rename {data-structures => src/data-structures}/queue/queue.test.ts (100%) rename {data-structures => src/data-structures}/queue/queue.ts (100%) rename {data-structures => src/data-structures}/red-black-tree/redBlackTree.test.ts (100%) rename {data-structures => src/data-structures}/red-black-tree/redBlackTree.ts (100%) rename {data-structures => src/data-structures}/stack/stack.test.ts (100%) rename {data-structures => src/data-structures}/stack/stack.ts (100%) rename {data-structures => src/data-structures}/trie/trie.test.ts (100%) rename {data-structures => src/data-structures}/trie/trie.ts (100%) rename {data-structures => src/data-structures}/union-find/unionFind.test.ts (100%) rename {data-structures => src/data-structures}/union-find/unionFind.ts (100%) rename {math => src/math}/binomial-coefficient/binomialCoefficient.test.ts (100%) rename {math => src/math}/binomial-coefficient/binomialCoefficient.ts (100%) rename {math => src/math}/euler-totient/eulerTotient.test.ts (100%) rename {math => src/math}/euler-totient/eulerTotient.ts (100%) rename {math => src/math}/extended-gcd/extendedGcd.test.ts (100%) rename {math => src/math}/extended-gcd/extendedGcd.ts (100%) rename {math => src/math}/factorial/factorial.test.ts (100%) rename {math => src/math}/factorial/factorial.ts (100%) rename {math => src/math}/fib-matrix/fibMatrix.test.ts (100%) rename {math => src/math}/fib-matrix/fibMatrix.ts (100%) rename {math => src/math}/gcd/gcb.test.ts (100%) rename {math => src/math}/gcd/gcd.ts (100%) rename {math => src/math}/matrix/matrix.test.ts (100%) rename {math => src/math}/matrix/matrix.ts (100%) rename {math => src/math}/mod-pow/modPow.test.ts (100%) rename {math => src/math}/mod-pow/modPow.ts (100%) rename {math => src/math}/prime-factors/primeFactors.test.ts (100%) rename {math => src/math}/prime-factors/primeFactors.ts (100%) rename {math => src/math}/sieve-of-eratosthenes/sieveOfEratosthenes.test.ts (100%) rename {math => src/math}/sieve-of-eratosthenes/sieveOfEratosthenes.ts (100%) diff --git a/algorithms/dp/coin-change/coinChange.test.ts b/src/algorithms/dp/coin-change/coinChange.test.ts similarity index 100% rename from algorithms/dp/coin-change/coinChange.test.ts rename to src/algorithms/dp/coin-change/coinChange.test.ts diff --git a/algorithms/dp/coin-change/coinChange.ts b/src/algorithms/dp/coin-change/coinChange.ts similarity index 100% rename from algorithms/dp/coin-change/coinChange.ts rename to src/algorithms/dp/coin-change/coinChange.ts diff --git a/algorithms/dp/knapsack/knapsack.test.ts b/src/algorithms/dp/knapsack/knapsack.test.ts similarity index 100% rename from algorithms/dp/knapsack/knapsack.test.ts rename to src/algorithms/dp/knapsack/knapsack.test.ts diff --git a/algorithms/dp/knapsack/knapsack.ts b/src/algorithms/dp/knapsack/knapsack.ts similarity index 100% rename from algorithms/dp/knapsack/knapsack.ts rename to src/algorithms/dp/knapsack/knapsack.ts diff --git a/algorithms/graph/a-star/aStar.test.ts b/src/algorithms/graph/a-star/aStar.test.ts similarity index 100% rename from algorithms/graph/a-star/aStar.test.ts rename to src/algorithms/graph/a-star/aStar.test.ts diff --git a/algorithms/graph/a-star/aStar.ts b/src/algorithms/graph/a-star/aStar.ts similarity index 100% rename from algorithms/graph/a-star/aStar.ts rename to src/algorithms/graph/a-star/aStar.ts diff --git a/algorithms/graph/bellman-ford/bellmanFordSearch.test.ts b/src/algorithms/graph/bellman-ford/bellmanFordSearch.test.ts similarity index 100% rename from algorithms/graph/bellman-ford/bellmanFordSearch.test.ts rename to src/algorithms/graph/bellman-ford/bellmanFordSearch.test.ts diff --git a/algorithms/graph/bellman-ford/bellmanFordSearch.ts b/src/algorithms/graph/bellman-ford/bellmanFordSearch.ts similarity index 100% rename from algorithms/graph/bellman-ford/bellmanFordSearch.ts rename to src/algorithms/graph/bellman-ford/bellmanFordSearch.ts diff --git a/algorithms/graph/bfs/bfs.test.ts b/src/algorithms/graph/bfs/bfs.test.ts similarity index 100% rename from algorithms/graph/bfs/bfs.test.ts rename to src/algorithms/graph/bfs/bfs.test.ts diff --git a/algorithms/graph/bfs/bfs.ts b/src/algorithms/graph/bfs/bfs.ts similarity index 100% rename from algorithms/graph/bfs/bfs.ts rename to src/algorithms/graph/bfs/bfs.ts diff --git a/algorithms/graph/dijkstra/dijkstra.test.ts b/src/algorithms/graph/dijkstra/dijkstra.test.ts similarity index 100% rename from algorithms/graph/dijkstra/dijkstra.test.ts rename to src/algorithms/graph/dijkstra/dijkstra.test.ts diff --git a/algorithms/graph/dijkstra/dijkstra.ts b/src/algorithms/graph/dijkstra/dijkstra.ts similarity index 100% rename from algorithms/graph/dijkstra/dijkstra.ts rename to src/algorithms/graph/dijkstra/dijkstra.ts diff --git a/algorithms/graph/topological-sort/topological-sort.test.ts b/src/algorithms/graph/topological-sort/topological-sort.test.ts similarity index 100% rename from algorithms/graph/topological-sort/topological-sort.test.ts rename to src/algorithms/graph/topological-sort/topological-sort.test.ts diff --git a/algorithms/graph/topological-sort/topological-sort.ts b/src/algorithms/graph/topological-sort/topological-sort.ts similarity index 100% rename from algorithms/graph/topological-sort/topological-sort.ts rename to src/algorithms/graph/topological-sort/topological-sort.ts diff --git a/algorithms/search/binary-search/binarySearch.test.ts b/src/algorithms/search/binary-search/binarySearch.test.ts similarity index 100% rename from algorithms/search/binary-search/binarySearch.test.ts rename to src/algorithms/search/binary-search/binarySearch.test.ts diff --git a/algorithms/search/binary-search/binarySearch.ts b/src/algorithms/search/binary-search/binarySearch.ts similarity index 100% rename from algorithms/search/binary-search/binarySearch.ts rename to src/algorithms/search/binary-search/binarySearch.ts diff --git a/algorithms/search/interpolation-search/interpolationSearch.test.ts b/src/algorithms/search/interpolation-search/interpolationSearch.test.ts similarity index 100% rename from algorithms/search/interpolation-search/interpolationSearch.test.ts rename to src/algorithms/search/interpolation-search/interpolationSearch.test.ts diff --git a/algorithms/search/interpolation-search/interpolationSearch.ts b/src/algorithms/search/interpolation-search/interpolationSearch.ts similarity index 100% rename from algorithms/search/interpolation-search/interpolationSearch.ts rename to src/algorithms/search/interpolation-search/interpolationSearch.ts diff --git a/algorithms/search/jump-search/jumpSearch.test.ts b/src/algorithms/search/jump-search/jumpSearch.test.ts similarity index 100% rename from algorithms/search/jump-search/jumpSearch.test.ts rename to src/algorithms/search/jump-search/jumpSearch.test.ts diff --git a/algorithms/search/jump-search/jumpSearch.ts b/src/algorithms/search/jump-search/jumpSearch.ts similarity index 100% rename from algorithms/search/jump-search/jumpSearch.ts rename to src/algorithms/search/jump-search/jumpSearch.ts diff --git a/algorithms/search/linear-search/linearSearch.test.ts b/src/algorithms/search/linear-search/linearSearch.test.ts similarity index 100% rename from algorithms/search/linear-search/linearSearch.test.ts rename to src/algorithms/search/linear-search/linearSearch.test.ts diff --git a/algorithms/search/linear-search/linearSearch.ts b/src/algorithms/search/linear-search/linearSearch.ts similarity index 100% rename from algorithms/search/linear-search/linearSearch.ts rename to src/algorithms/search/linear-search/linearSearch.ts diff --git a/algorithms/sorting/bubble-sort-counters/bubbleSortCounters.test.ts b/src/algorithms/sorting/bubble-sort-counters/bubbleSortCounters.test.ts similarity index 100% rename from algorithms/sorting/bubble-sort-counters/bubbleSortCounters.test.ts rename to src/algorithms/sorting/bubble-sort-counters/bubbleSortCounters.test.ts diff --git a/algorithms/sorting/bubble-sort-counters/bubbleSortCounters.ts b/src/algorithms/sorting/bubble-sort-counters/bubbleSortCounters.ts similarity index 100% rename from algorithms/sorting/bubble-sort-counters/bubbleSortCounters.ts rename to src/algorithms/sorting/bubble-sort-counters/bubbleSortCounters.ts diff --git a/algorithms/sorting/bubble-sort/bubbleSort.test.ts b/src/algorithms/sorting/bubble-sort/bubbleSort.test.ts similarity index 100% rename from algorithms/sorting/bubble-sort/bubbleSort.test.ts rename to src/algorithms/sorting/bubble-sort/bubbleSort.test.ts diff --git a/algorithms/sorting/bubble-sort/bubbleSort.ts b/src/algorithms/sorting/bubble-sort/bubbleSort.ts similarity index 100% rename from algorithms/sorting/bubble-sort/bubbleSort.ts rename to src/algorithms/sorting/bubble-sort/bubbleSort.ts diff --git a/algorithms/sorting/heap-sort/heapSort.test.ts b/src/algorithms/sorting/heap-sort/heapSort.test.ts similarity index 100% rename from algorithms/sorting/heap-sort/heapSort.test.ts rename to src/algorithms/sorting/heap-sort/heapSort.test.ts diff --git a/algorithms/sorting/heap-sort/heapSort.ts b/src/algorithms/sorting/heap-sort/heapSort.ts similarity index 100% rename from algorithms/sorting/heap-sort/heapSort.ts rename to src/algorithms/sorting/heap-sort/heapSort.ts diff --git a/algorithms/sorting/insertion-sort-counters/insertionSortCounters.test.ts b/src/algorithms/sorting/insertion-sort-counters/insertionSortCounters.test.ts similarity index 100% rename from algorithms/sorting/insertion-sort-counters/insertionSortCounters.test.ts rename to src/algorithms/sorting/insertion-sort-counters/insertionSortCounters.test.ts diff --git a/algorithms/sorting/insertion-sort-counters/insertionSortCounters.ts b/src/algorithms/sorting/insertion-sort-counters/insertionSortCounters.ts similarity index 100% rename from algorithms/sorting/insertion-sort-counters/insertionSortCounters.ts rename to src/algorithms/sorting/insertion-sort-counters/insertionSortCounters.ts diff --git a/algorithms/sorting/insertion-sort/insertionSort.test.ts b/src/algorithms/sorting/insertion-sort/insertionSort.test.ts similarity index 100% rename from algorithms/sorting/insertion-sort/insertionSort.test.ts rename to src/algorithms/sorting/insertion-sort/insertionSort.test.ts diff --git a/algorithms/sorting/insertion-sort/insertionSort.ts b/src/algorithms/sorting/insertion-sort/insertionSort.ts similarity index 100% rename from algorithms/sorting/insertion-sort/insertionSort.ts rename to src/algorithms/sorting/insertion-sort/insertionSort.ts diff --git a/algorithms/sorting/merge-sort-counters/mergeSortCounters.test.ts b/src/algorithms/sorting/merge-sort-counters/mergeSortCounters.test.ts similarity index 100% rename from algorithms/sorting/merge-sort-counters/mergeSortCounters.test.ts rename to src/algorithms/sorting/merge-sort-counters/mergeSortCounters.test.ts diff --git a/algorithms/sorting/merge-sort-counters/mergeSortCounters.ts b/src/algorithms/sorting/merge-sort-counters/mergeSortCounters.ts similarity index 100% rename from algorithms/sorting/merge-sort-counters/mergeSortCounters.ts rename to src/algorithms/sorting/merge-sort-counters/mergeSortCounters.ts diff --git a/algorithms/sorting/merge-sort/mergeSort.test.ts b/src/algorithms/sorting/merge-sort/mergeSort.test.ts similarity index 100% rename from algorithms/sorting/merge-sort/mergeSort.test.ts rename to src/algorithms/sorting/merge-sort/mergeSort.test.ts diff --git a/algorithms/sorting/merge-sort/mergeSort.ts b/src/algorithms/sorting/merge-sort/mergeSort.ts similarity index 100% rename from algorithms/sorting/merge-sort/mergeSort.ts rename to src/algorithms/sorting/merge-sort/mergeSort.ts diff --git a/algorithms/sorting/quick-sort/quickSort.test.ts b/src/algorithms/sorting/quick-sort/quickSort.test.ts similarity index 100% rename from algorithms/sorting/quick-sort/quickSort.test.ts rename to src/algorithms/sorting/quick-sort/quickSort.test.ts diff --git a/algorithms/sorting/quick-sort/quickSort.ts b/src/algorithms/sorting/quick-sort/quickSort.ts similarity index 100% rename from algorithms/sorting/quick-sort/quickSort.ts rename to src/algorithms/sorting/quick-sort/quickSort.ts diff --git a/algorithms/sorting/selection-sort-counters/selectionSortCounters.test.ts b/src/algorithms/sorting/selection-sort-counters/selectionSortCounters.test.ts similarity index 100% rename from algorithms/sorting/selection-sort-counters/selectionSortCounters.test.ts rename to src/algorithms/sorting/selection-sort-counters/selectionSortCounters.test.ts diff --git a/algorithms/sorting/selection-sort-counters/selectionSortCounters.ts b/src/algorithms/sorting/selection-sort-counters/selectionSortCounters.ts similarity index 100% rename from algorithms/sorting/selection-sort-counters/selectionSortCounters.ts rename to src/algorithms/sorting/selection-sort-counters/selectionSortCounters.ts diff --git a/algorithms/sorting/selection-sort/selectionSort.test.ts b/src/algorithms/sorting/selection-sort/selectionSort.test.ts similarity index 100% rename from algorithms/sorting/selection-sort/selectionSort.test.ts rename to src/algorithms/sorting/selection-sort/selectionSort.test.ts diff --git a/algorithms/sorting/selection-sort/selectionSort.ts b/src/algorithms/sorting/selection-sort/selectionSort.ts similarity index 100% rename from algorithms/sorting/selection-sort/selectionSort.ts rename to src/algorithms/sorting/selection-sort/selectionSort.ts diff --git a/algorithms/sorting/shell-sort-counters/shellSortCounters.test.ts b/src/algorithms/sorting/shell-sort-counters/shellSortCounters.test.ts similarity index 100% rename from algorithms/sorting/shell-sort-counters/shellSortCounters.test.ts rename to src/algorithms/sorting/shell-sort-counters/shellSortCounters.test.ts diff --git a/algorithms/sorting/shell-sort-counters/shellSortCounters.ts b/src/algorithms/sorting/shell-sort-counters/shellSortCounters.ts similarity index 100% rename from algorithms/sorting/shell-sort-counters/shellSortCounters.ts rename to src/algorithms/sorting/shell-sort-counters/shellSortCounters.ts diff --git a/algorithms/sorting/shell-sort/shellSort.test.ts b/src/algorithms/sorting/shell-sort/shellSort.test.ts similarity index 100% rename from algorithms/sorting/shell-sort/shellSort.test.ts rename to src/algorithms/sorting/shell-sort/shellSort.test.ts diff --git a/algorithms/sorting/shell-sort/shellSort.ts b/src/algorithms/sorting/shell-sort/shellSort.ts similarity index 100% rename from algorithms/sorting/shell-sort/shellSort.ts rename to src/algorithms/sorting/shell-sort/shellSort.ts diff --git a/algorithms/sorting/types.ts b/src/algorithms/sorting/types.ts similarity index 100% rename from algorithms/sorting/types.ts rename to src/algorithms/sorting/types.ts diff --git a/algorithms/string/lcs/lcs.test.ts b/src/algorithms/string/lcs/lcs.test.ts similarity index 100% rename from algorithms/string/lcs/lcs.test.ts rename to src/algorithms/string/lcs/lcs.test.ts diff --git a/algorithms/string/lcs/lcs.ts b/src/algorithms/string/lcs/lcs.ts similarity index 100% rename from algorithms/string/lcs/lcs.ts rename to src/algorithms/string/lcs/lcs.ts diff --git a/algorithms/string/levenshtein-distance/levenshteinDistance.test.ts b/src/algorithms/string/levenshtein-distance/levenshteinDistance.test.ts similarity index 100% rename from algorithms/string/levenshtein-distance/levenshteinDistance.test.ts rename to src/algorithms/string/levenshtein-distance/levenshteinDistance.test.ts diff --git a/algorithms/string/levenshtein-distance/levenshteinDistance.ts b/src/algorithms/string/levenshtein-distance/levenshteinDistance.ts similarity index 100% rename from algorithms/string/levenshtein-distance/levenshteinDistance.ts rename to src/algorithms/string/levenshtein-distance/levenshteinDistance.ts diff --git a/data-structures/binary-tree/binaryTree.test.ts b/src/data-structures/binary-tree/binaryTree.test.ts similarity index 100% rename from data-structures/binary-tree/binaryTree.test.ts rename to src/data-structures/binary-tree/binaryTree.test.ts diff --git a/data-structures/binary-tree/binaryTree.ts b/src/data-structures/binary-tree/binaryTree.ts similarity index 100% rename from data-structures/binary-tree/binaryTree.ts rename to src/data-structures/binary-tree/binaryTree.ts diff --git a/data-structures/graph/graph.test.ts b/src/data-structures/graph/graph.test.ts similarity index 100% rename from data-structures/graph/graph.test.ts rename to src/data-structures/graph/graph.test.ts diff --git a/data-structures/graph/graph.ts b/src/data-structures/graph/graph.ts similarity index 100% rename from data-structures/graph/graph.ts rename to src/data-structures/graph/graph.ts diff --git a/data-structures/hash-table/hashTable.test.ts b/src/data-structures/hash-table/hashTable.test.ts similarity index 100% rename from data-structures/hash-table/hashTable.test.ts rename to src/data-structures/hash-table/hashTable.test.ts diff --git a/data-structures/hash-table/hashTable.ts b/src/data-structures/hash-table/hashTable.ts similarity index 100% rename from data-structures/hash-table/hashTable.ts rename to src/data-structures/hash-table/hashTable.ts diff --git a/data-structures/heap/minHeap.test.ts b/src/data-structures/heap/minHeap.test.ts similarity index 100% rename from data-structures/heap/minHeap.test.ts rename to src/data-structures/heap/minHeap.test.ts diff --git a/data-structures/heap/minHeap.ts b/src/data-structures/heap/minHeap.ts similarity index 100% rename from data-structures/heap/minHeap.ts rename to src/data-structures/heap/minHeap.ts diff --git a/data-structures/list-node/linkedList.test.ts b/src/data-structures/list-node/linkedList.test.ts similarity index 100% rename from data-structures/list-node/linkedList.test.ts rename to src/data-structures/list-node/linkedList.test.ts diff --git a/data-structures/list-node/linkedList.ts b/src/data-structures/list-node/linkedList.ts similarity index 100% rename from data-structures/list-node/linkedList.ts rename to src/data-structures/list-node/linkedList.ts diff --git a/data-structures/queue/circularQueue.test.ts b/src/data-structures/queue/circularQueue.test.ts similarity index 100% rename from data-structures/queue/circularQueue.test.ts rename to src/data-structures/queue/circularQueue.test.ts diff --git a/data-structures/queue/circularQueue.ts b/src/data-structures/queue/circularQueue.ts similarity index 100% rename from data-structures/queue/circularQueue.ts rename to src/data-structures/queue/circularQueue.ts diff --git a/data-structures/queue/queue.test.ts b/src/data-structures/queue/queue.test.ts similarity index 100% rename from data-structures/queue/queue.test.ts rename to src/data-structures/queue/queue.test.ts diff --git a/data-structures/queue/queue.ts b/src/data-structures/queue/queue.ts similarity index 100% rename from data-structures/queue/queue.ts rename to src/data-structures/queue/queue.ts diff --git a/data-structures/red-black-tree/redBlackTree.test.ts b/src/data-structures/red-black-tree/redBlackTree.test.ts similarity index 100% rename from data-structures/red-black-tree/redBlackTree.test.ts rename to src/data-structures/red-black-tree/redBlackTree.test.ts diff --git a/data-structures/red-black-tree/redBlackTree.ts b/src/data-structures/red-black-tree/redBlackTree.ts similarity index 100% rename from data-structures/red-black-tree/redBlackTree.ts rename to src/data-structures/red-black-tree/redBlackTree.ts diff --git a/data-structures/stack/stack.test.ts b/src/data-structures/stack/stack.test.ts similarity index 100% rename from data-structures/stack/stack.test.ts rename to src/data-structures/stack/stack.test.ts diff --git a/data-structures/stack/stack.ts b/src/data-structures/stack/stack.ts similarity index 100% rename from data-structures/stack/stack.ts rename to src/data-structures/stack/stack.ts diff --git a/data-structures/trie/trie.test.ts b/src/data-structures/trie/trie.test.ts similarity index 100% rename from data-structures/trie/trie.test.ts rename to src/data-structures/trie/trie.test.ts diff --git a/data-structures/trie/trie.ts b/src/data-structures/trie/trie.ts similarity index 100% rename from data-structures/trie/trie.ts rename to src/data-structures/trie/trie.ts diff --git a/data-structures/union-find/unionFind.test.ts b/src/data-structures/union-find/unionFind.test.ts similarity index 100% rename from data-structures/union-find/unionFind.test.ts rename to src/data-structures/union-find/unionFind.test.ts diff --git a/data-structures/union-find/unionFind.ts b/src/data-structures/union-find/unionFind.ts similarity index 100% rename from data-structures/union-find/unionFind.ts rename to src/data-structures/union-find/unionFind.ts diff --git a/math/binomial-coefficient/binomialCoefficient.test.ts b/src/math/binomial-coefficient/binomialCoefficient.test.ts similarity index 100% rename from math/binomial-coefficient/binomialCoefficient.test.ts rename to src/math/binomial-coefficient/binomialCoefficient.test.ts diff --git a/math/binomial-coefficient/binomialCoefficient.ts b/src/math/binomial-coefficient/binomialCoefficient.ts similarity index 100% rename from math/binomial-coefficient/binomialCoefficient.ts rename to src/math/binomial-coefficient/binomialCoefficient.ts diff --git a/math/euler-totient/eulerTotient.test.ts b/src/math/euler-totient/eulerTotient.test.ts similarity index 100% rename from math/euler-totient/eulerTotient.test.ts rename to src/math/euler-totient/eulerTotient.test.ts diff --git a/math/euler-totient/eulerTotient.ts b/src/math/euler-totient/eulerTotient.ts similarity index 100% rename from math/euler-totient/eulerTotient.ts rename to src/math/euler-totient/eulerTotient.ts diff --git a/math/extended-gcd/extendedGcd.test.ts b/src/math/extended-gcd/extendedGcd.test.ts similarity index 100% rename from math/extended-gcd/extendedGcd.test.ts rename to src/math/extended-gcd/extendedGcd.test.ts diff --git a/math/extended-gcd/extendedGcd.ts b/src/math/extended-gcd/extendedGcd.ts similarity index 100% rename from math/extended-gcd/extendedGcd.ts rename to src/math/extended-gcd/extendedGcd.ts diff --git a/math/factorial/factorial.test.ts b/src/math/factorial/factorial.test.ts similarity index 100% rename from math/factorial/factorial.test.ts rename to src/math/factorial/factorial.test.ts diff --git a/math/factorial/factorial.ts b/src/math/factorial/factorial.ts similarity index 100% rename from math/factorial/factorial.ts rename to src/math/factorial/factorial.ts diff --git a/math/fib-matrix/fibMatrix.test.ts b/src/math/fib-matrix/fibMatrix.test.ts similarity index 100% rename from math/fib-matrix/fibMatrix.test.ts rename to src/math/fib-matrix/fibMatrix.test.ts diff --git a/math/fib-matrix/fibMatrix.ts b/src/math/fib-matrix/fibMatrix.ts similarity index 100% rename from math/fib-matrix/fibMatrix.ts rename to src/math/fib-matrix/fibMatrix.ts diff --git a/math/gcd/gcb.test.ts b/src/math/gcd/gcb.test.ts similarity index 100% rename from math/gcd/gcb.test.ts rename to src/math/gcd/gcb.test.ts diff --git a/math/gcd/gcd.ts b/src/math/gcd/gcd.ts similarity index 100% rename from math/gcd/gcd.ts rename to src/math/gcd/gcd.ts diff --git a/math/matrix/matrix.test.ts b/src/math/matrix/matrix.test.ts similarity index 100% rename from math/matrix/matrix.test.ts rename to src/math/matrix/matrix.test.ts diff --git a/math/matrix/matrix.ts b/src/math/matrix/matrix.ts similarity index 100% rename from math/matrix/matrix.ts rename to src/math/matrix/matrix.ts diff --git a/math/mod-pow/modPow.test.ts b/src/math/mod-pow/modPow.test.ts similarity index 100% rename from math/mod-pow/modPow.test.ts rename to src/math/mod-pow/modPow.test.ts diff --git a/math/mod-pow/modPow.ts b/src/math/mod-pow/modPow.ts similarity index 100% rename from math/mod-pow/modPow.ts rename to src/math/mod-pow/modPow.ts diff --git a/math/prime-factors/primeFactors.test.ts b/src/math/prime-factors/primeFactors.test.ts similarity index 100% rename from math/prime-factors/primeFactors.test.ts rename to src/math/prime-factors/primeFactors.test.ts diff --git a/math/prime-factors/primeFactors.ts b/src/math/prime-factors/primeFactors.ts similarity index 100% rename from math/prime-factors/primeFactors.ts rename to src/math/prime-factors/primeFactors.ts diff --git a/math/sieve-of-eratosthenes/sieveOfEratosthenes.test.ts b/src/math/sieve-of-eratosthenes/sieveOfEratosthenes.test.ts similarity index 100% rename from math/sieve-of-eratosthenes/sieveOfEratosthenes.test.ts rename to src/math/sieve-of-eratosthenes/sieveOfEratosthenes.test.ts diff --git a/math/sieve-of-eratosthenes/sieveOfEratosthenes.ts b/src/math/sieve-of-eratosthenes/sieveOfEratosthenes.ts similarity index 100% rename from math/sieve-of-eratosthenes/sieveOfEratosthenes.ts rename to src/math/sieve-of-eratosthenes/sieveOfEratosthenes.ts diff --git a/tsconfig.json b/tsconfig.json index 46abf15..a5de76f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,9 +15,7 @@ "types": ["node", "jest"] }, "include": [ - "./data-structures/**/*", - "./math/**/*", - "./algorithms/**/*" + "./src/**/*" ], "exclude": ["node_modules"] } From d2c8b592074ef1a9b767e0d5d352481a43438689 Mon Sep 17 00:00:00 2001 From: monkey0722 Date: Tue, 14 Apr 2026 05:47:31 +0900 Subject: [PATCH 2/7] feat(scripts): add check:all script to run tests, lint, and typecheck --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 48121a7..68fb976 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "typecheck": "tsc --noEmit --skipLibCheck", "lint": "eslint ./**/*.ts", "lint:fix": "eslint --fix ./**/*.ts", - "prettier": "prettier --write './**/*.{js,ts,tsx}' --ignore-path '.gitignore'" + "prettier": "prettier --write './**/*.{js,ts,tsx}' --ignore-path '.gitignore'", + "check:all": "yarn test && yarn lint && yarn typecheck" }, "devDependencies": { "@types/jest": "^30.0.0", From 6bd462e8acf910a43e069e4e9fff8d6dcfd6361d Mon Sep 17 00:00:00 2001 From: monkey0722 Date: Tue, 14 Apr 2026 06:00:06 +0900 Subject: [PATCH 3/7] fix(tsconfig): update target and lib to ES2024 --- tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index a5de76f..52740c2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,8 +2,8 @@ "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", - "target": "ES2025", - "lib": ["ES2025", "DOM"], + "target": "ES2024", + "lib": ["ES2024", "DOM"], "isolatedModules": true, "strict": true, "noImplicitReturns": true, From 0de3af9d15885b6aff984317c6b2a4ea8f0abe96 Mon Sep 17 00:00:00 2001 From: monkey0722 Date: Tue, 14 Apr 2026 06:00:23 +0900 Subject: [PATCH 4/7] feat(dfs): implement depth-first search algorithms and path reconstruction --- src/algorithms/graph/dfs/dfs.test.ts | 152 +++++++++++++++++++++++++++ src/algorithms/graph/dfs/dfs.ts | 119 +++++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 src/algorithms/graph/dfs/dfs.test.ts create mode 100644 src/algorithms/graph/dfs/dfs.ts diff --git a/src/algorithms/graph/dfs/dfs.test.ts b/src/algorithms/graph/dfs/dfs.test.ts new file mode 100644 index 0000000..561e3dc --- /dev/null +++ b/src/algorithms/graph/dfs/dfs.test.ts @@ -0,0 +1,152 @@ +import {dfs, dfsRecursive, reconstructPath} from './dfs'; + +describe('DFS Algorithm (Iterative)', () => { + test('should traverse a simple graph', () => { + const graph = [ + [1, 2], // Edges from vertex 0 + [0, 3, 4], // Edges from vertex 1 + [0, 5], // Edges from vertex 2 + [1], // Edges from vertex 3 + [1], // Edges from vertex 4 + [2], // Edges from vertex 5 + ]; + const {visited, predecessors} = dfs(graph, 0); + expect(visited[0]).toBe(0); + expect(visited.length).toBe(6); + expect(new Set(visited).size).toBe(6); + expect(predecessors[0]).toBe(-1); + }); + + test('should handle disconnected graph', () => { + const graph = [ + [1], // Edges from vertex 0 + [0], // Edges from vertex 1 + [3], // Edges from vertex 2 + [2], // Edges from vertex 3 + [], // Edges from vertex 4 (isolated) + ]; + const {visited, predecessors} = dfs(graph, 0); + expect(visited).toEqual([0, 1]); + expect(predecessors[1]).toBe(0); + expect(predecessors[2]).toBe(-1); + expect(predecessors[3]).toBe(-1); + expect(predecessors[4]).toBe(-1); + }); + + test('should throw error for invalid start vertex', () => { + const graph = [[1, 2], [0], [0]]; + expect(() => dfs(graph, -1)).toThrow('Start vertex is out of range'); + expect(() => dfs(graph, 3)).toThrow('Start vertex is out of range'); + }); + + test('should handle a graph with a single vertex', () => { + const graph = [[]]; + const {visited, predecessors} = dfs(graph, 0); + expect(visited).toEqual([0]); + expect(predecessors).toEqual([-1]); + }); + + test('should handle cyclic graphs correctly', () => { + const graph = [ + [1, 2], // Edges from vertex 0 + [0, 2], // Edges from vertex 1 + [0, 1], // Edges from vertex 2 + ]; + const {visited} = dfs(graph, 0); + expect(visited.length).toBe(3); + expect(new Set(visited).size).toBe(3); + expect(visited[0]).toBe(0); + }); + + test('should handle large graphs efficiently', () => { + const largeGraph: number[][] = Array(1000) + .fill(0) + .map((_, i) => { + if (i === 0) return [1]; + if (i === 999) return [998]; + return [i - 1, i + 1]; + }); + + const startTime = performance.now(); + const {visited} = dfs(largeGraph, 0); + const endTime = performance.now(); + + expect(visited.length).toBe(1000); + expect(visited[0]).toBe(0); + expect(endTime - startTime).toBeLessThan(1000); + }); +}); + +describe('DFS Algorithm (Recursive)', () => { + test('should traverse a simple graph in depth-first order', () => { + const graph = [ + [1, 2], // Edges from vertex 0 + [0, 3, 4], // Edges from vertex 1 + [0, 5], // Edges from vertex 2 + [1], // Edges from vertex 3 + [1], // Edges from vertex 4 + [2], // Edges from vertex 5 + ]; + const {visited} = dfsRecursive(graph, 0); + expect(visited[0]).toBe(0); + expect(visited.length).toBe(6); + expect(new Set(visited).size).toBe(6); + // Recursive DFS follows adjacency list order: 0 -> 1 -> 3 -> 4 -> 2 -> 5 + expect(visited).toEqual([0, 1, 3, 4, 2, 5]); + }); + + test('should handle disconnected graph', () => { + const graph = [ + [1], // Edges from vertex 0 + [0], // Edges from vertex 1 + [3], // Edges from vertex 2 + [2], // Edges from vertex 3 + [], // Edges from vertex 4 (isolated) + ]; + const {visited} = dfsRecursive(graph, 0); + expect(visited).toEqual([0, 1]); + }); + + test('should throw error for invalid start vertex', () => { + const graph = [[1, 2], [0], [0]]; + expect(() => dfsRecursive(graph, -1)).toThrow('Start vertex is out of range'); + expect(() => dfsRecursive(graph, 3)).toThrow('Start vertex is out of range'); + }); + + test('should handle a graph with a single vertex', () => { + const graph = [[]]; + const {visited, predecessors} = dfsRecursive(graph, 0); + expect(visited).toEqual([0]); + expect(predecessors).toEqual([-1]); + }); +}); + +describe('reconstructPath (DFS)', () => { + test('should reconstruct a valid path', () => { + const graph = [[1, 2], [3], [4], [], []]; + const {predecessors} = dfsRecursive(graph, 0); + const path = reconstructPath(0, 3, predecessors); + expect(path).toEqual([0, 1, 3]); + }); + + test('should handle path from vertex to itself', () => { + const graph = [[1], [2], []]; + const {predecessors} = dfsRecursive(graph, 0); + const path = reconstructPath(0, 0, predecessors); + expect(path).toEqual([0]); + }); + + test('should return null for unreachable vertices', () => { + const graph = [[1], [0], [3], [2]]; + const {predecessors} = dfsRecursive(graph, 0); + const path = reconstructPath(0, 2, predecessors); + expect(path).toBeNull(); + }); + + test('should handle invalid target vertex', () => { + const graph = [[1], [0]]; + const {predecessors} = dfsRecursive(graph, 0); + const path = reconstructPath(0, 2, predecessors); + expect(path).toBeNull(); + }); +}); diff --git a/src/algorithms/graph/dfs/dfs.ts b/src/algorithms/graph/dfs/dfs.ts new file mode 100644 index 0000000..d1266fc --- /dev/null +++ b/src/algorithms/graph/dfs/dfs.ts @@ -0,0 +1,119 @@ +/** + * Performs a depth-first search (DFS) traversal on a graph. + * DFS explores as far as possible along each branch before backtracking. + * + * @param {number[][]} graph - An adjacency list representation of the graph. + * @param {number} start - The starting vertex. + * @returns {{ visited: number[], predecessors: number[] }} + * An object containing the order of visited vertices + * and predecessors array for path reconstruction. + * @throws {Error} If the start vertex is out of range. + */ +export function dfs( + graph: number[][], + start: number, +): { + visited: number[]; + predecessors: number[]; +} { + if (start < 0 || start >= graph.length) { + throw new Error('Start vertex is out of range'); + } + const n = graph.length; + const predecessors: number[] = Array(n).fill(-1); + const seen: boolean[] = Array(n).fill(false); + const visited: number[] = []; + const stack: number[] = [start]; + seen[start] = true; + + while (stack.length > 0) { + const current = stack.pop()!; + visited.push(current); + + for (const neighbor of graph[current]) { + if (!seen[neighbor]) { + seen[neighbor] = true; + predecessors[neighbor] = current; + stack.push(neighbor); + } + } + } + + return {visited, predecessors}; +} + +/** + * Performs a recursive depth-first search (DFS) traversal on a graph. + * + * @param {number[][]} graph - An adjacency list representation of the graph. + * @param {number} start - The starting vertex. + * @returns {{ visited: number[], predecessors: number[] }} + * An object containing the order of visited vertices + * and predecessors array for path reconstruction. + * @throws {Error} If the start vertex is out of range. + */ +export function dfsRecursive( + graph: number[][], + start: number, +): { + visited: number[]; + predecessors: number[]; +} { + if (start < 0 || start >= graph.length) { + throw new Error('Start vertex is out of range'); + } + const n = graph.length; + const predecessors: number[] = Array(n).fill(-1); + const seen: boolean[] = Array(n).fill(false); + const visited: number[] = []; + + function traverse(vertex: number): void { + seen[vertex] = true; + visited.push(vertex); + for (const neighbor of graph[vertex]) { + if (!seen[neighbor]) { + predecessors[neighbor] = vertex; + traverse(neighbor); + } + } + } + + traverse(start); + return {visited, predecessors}; +} + +/** + * Reconstructs the path from a source vertex to a target vertex + * using the predecessors array obtained from DFS. + * + * @param {number} source - The source vertex. + * @param {number} target - The target vertex. + * @param {number[]} predecessors - The predecessors array from DFS. + * @returns {number[] | null} The path from source to target, or null if no path exists. + */ +export function reconstructPath( + source: number, + target: number, + predecessors: number[], +): number[] | null { + if ( + target < 0 || + target >= predecessors.length || + (predecessors[target] === -1 && source !== target) + ) { + return null; + } + + const path: number[] = []; + let current = target; + + while (current !== -1) { + path.unshift(current); + if (current === source) { + break; + } + current = predecessors[current]; + } + + return path[0] === source ? path : null; +} From c73e923b9904d7eccf10263268541436a4876e3e Mon Sep 17 00:00:00 2001 From: monkey0722 Date: Tue, 14 Apr 2026 06:00:29 +0900 Subject: [PATCH 5/7] feat(rabin-karp): implement Rabin-Karp algorithm for string search --- .../string/rabin-karp/rabin-karp.test.ts | 67 +++++++++++++++++++ .../string/rabin-karp/rabin-karp.ts | 63 +++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 src/algorithms/string/rabin-karp/rabin-karp.test.ts create mode 100644 src/algorithms/string/rabin-karp/rabin-karp.ts diff --git a/src/algorithms/string/rabin-karp/rabin-karp.test.ts b/src/algorithms/string/rabin-karp/rabin-karp.test.ts new file mode 100644 index 0000000..9d84aca --- /dev/null +++ b/src/algorithms/string/rabin-karp/rabin-karp.test.ts @@ -0,0 +1,67 @@ +import {rabinKarp} from './rabin-karp'; + +describe('Rabin-Karp Algorithm', () => { + test('should find a single occurrence', () => { + expect(rabinKarp('hello world', 'world')).toEqual([6]); + }); + + test('should find multiple occurrences', () => { + expect(rabinKarp('ababababab', 'abab')).toEqual([0, 2, 4, 6]); + }); + + test('should return empty array when pattern is not found', () => { + expect(rabinKarp('hello world', 'xyz')).toEqual([]); + }); + + test('should return empty array for empty pattern', () => { + expect(rabinKarp('hello', '')).toEqual([]); + }); + + test('should return empty array when pattern is longer than text', () => { + expect(rabinKarp('hi', 'hello')).toEqual([]); + }); + + test('should handle pattern equal to text', () => { + expect(rabinKarp('abc', 'abc')).toEqual([0]); + }); + + test('should handle single character pattern', () => { + expect(rabinKarp('abcabc', 'a')).toEqual([0, 3]); + }); + + test('should handle single character text and pattern', () => { + expect(rabinKarp('a', 'a')).toEqual([0]); + expect(rabinKarp('a', 'b')).toEqual([]); + }); + + test('should handle repeated characters', () => { + expect(rabinKarp('aaaaaa', 'aaa')).toEqual([0, 1, 2, 3]); + }); + + test('should handle pattern at the end of text', () => { + expect(rabinKarp('abcdef', 'def')).toEqual([3]); + }); + + test('should handle pattern at the beginning of text', () => { + expect(rabinKarp('abcdef', 'abc')).toEqual([0]); + }); + + test('should handle large text efficiently', () => { + const text = 'a'.repeat(10000) + 'b'; + const pattern = 'a'.repeat(100) + 'b'; + + const startTime = performance.now(); + const result = rabinKarp(text, pattern); + const endTime = performance.now(); + + expect(result).toEqual([9900]); + expect(endTime - startTime).toBeLessThan(1000); + }); + + test('should handle hash collisions correctly', () => { + // Use longer strings to increase collision potential + const text = 'The quick brown fox jumps over the lazy dog'; + const pattern = 'fox'; + expect(rabinKarp(text, pattern)).toEqual([16]); + }); +}); diff --git a/src/algorithms/string/rabin-karp/rabin-karp.ts b/src/algorithms/string/rabin-karp/rabin-karp.ts new file mode 100644 index 0000000..e5e7929 --- /dev/null +++ b/src/algorithms/string/rabin-karp/rabin-karp.ts @@ -0,0 +1,63 @@ +/** + * Performs Rabin-Karp string search using a rolling hash. + * Finds all occurrences of a pattern in a text string. + * + * Uses a polynomial rolling hash with a large prime modulus + * to efficiently compare substrings. + * + * @param {string} text - The text to search in. + * @param {string} pattern - The pattern to search for. + * @returns {number[]} An array of starting indices where the pattern is found. + */ +export function rabinKarp(text: string, pattern: string): number[] { + const results: number[] = []; + const n = text.length; + const m = pattern.length; + + if (m === 0) return results; + if (m > n) return results; + + const base = 256; + const mod = 1_000_000_007; + + // Compute base^(m-1) % mod for removing the leading character + let highPow = 1; + for (let i = 0; i < m - 1; i++) { + highPow = (highPow * base) % mod; + } + + // Compute initial hash values for pattern and the first window of text + let patternHash = 0; + let textHash = 0; + for (let i = 0; i < m; i++) { + patternHash = (patternHash * base + pattern.charCodeAt(i)) % mod; + textHash = (textHash * base + text.charCodeAt(i)) % mod; + } + + for (let i = 0; i <= n - m; i++) { + // If hashes match, verify character by character to avoid false positives + if (patternHash === textHash) { + let match = true; + for (let j = 0; j < m; j++) { + if (text[i + j] !== pattern[j]) { + match = false; + break; + } + } + if (match) { + results.push(i); + } + } + + // Compute hash for the next window by rolling the hash + if (i < n - m) { + textHash = ((textHash - text.charCodeAt(i) * highPow) * base + text.charCodeAt(i + m)) % mod; + // Ensure non-negative + if (textHash < 0) { + textHash += mod; + } + } + } + + return results; +} From ce06af964996e20b521863356c00ae3762fe165a Mon Sep 17 00:00:00 2001 From: monkey0722 Date: Tue, 14 Apr 2026 06:06:13 +0900 Subject: [PATCH 6/7] feat(dfs): enhance DFS tests and add stack depth limitation for recursive implementation --- src/algorithms/graph/dfs/dfs.test.ts | 17 ++++++++++++++--- src/algorithms/graph/dfs/dfs.ts | 5 +++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/algorithms/graph/dfs/dfs.test.ts b/src/algorithms/graph/dfs/dfs.test.ts index 561e3dc..604ddd6 100644 --- a/src/algorithms/graph/dfs/dfs.test.ts +++ b/src/algorithms/graph/dfs/dfs.test.ts @@ -11,9 +11,9 @@ describe('DFS Algorithm (Iterative)', () => { [2], // Edges from vertex 5 ]; const {visited, predecessors} = dfs(graph, 0); - expect(visited[0]).toBe(0); - expect(visited.length).toBe(6); - expect(new Set(visited).size).toBe(6); + // Iterative DFS uses a stack (LIFO), so the last neighbor pushed + // is visited first — yielding a different order from recursive DFS. + expect(visited).toEqual([0, 2, 5, 1, 4, 3]); expect(predecessors[0]).toBe(-1); }); @@ -121,6 +121,17 @@ describe('DFS Algorithm (Recursive)', () => { }); }); +describe('DFS Recursive - stack depth limitation', () => { + test('should throw RangeError on a very deep linear graph', () => { + const depth = 20000; + const deepGraph: number[][] = Array(depth) + .fill(0) + .map((_, i) => (i < depth - 1 ? [i + 1] : [])); + + expect(() => dfsRecursive(deepGraph, 0)).toThrow(RangeError); + }); +}); + describe('reconstructPath (DFS)', () => { test('should reconstruct a valid path', () => { const graph = [[1, 2], [3], [4], [], []]; diff --git a/src/algorithms/graph/dfs/dfs.ts b/src/algorithms/graph/dfs/dfs.ts index d1266fc..c459d06 100644 --- a/src/algorithms/graph/dfs/dfs.ts +++ b/src/algorithms/graph/dfs/dfs.ts @@ -45,6 +45,11 @@ export function dfs( /** * Performs a recursive depth-first search (DFS) traversal on a graph. * + * Note: This implementation uses the call stack for recursion, so it may throw + * a RangeError (Maximum call stack size exceeded) on graphs with depth + * exceeding ~10,000 vertices. For large or deep graphs, use the iterative + * {@link dfs} instead. + * * @param {number[][]} graph - An adjacency list representation of the graph. * @param {number} start - The starting vertex. * @returns {{ visited: number[], predecessors: number[] }} From 066c4abf01bff0868d7129ec861097e8b17cbfec Mon Sep 17 00:00:00 2001 From: monkey0722 Date: Tue, 14 Apr 2026 06:06:27 +0900 Subject: [PATCH 7/7] feat(rabin-karp): enhance Rabin-Karp algorithm to handle non-ASCII characters and prevent integer overflow --- .../string/rabin-karp/rabin-karp.test.ts | 15 +++++++++++ .../string/rabin-karp/rabin-karp.ts | 27 ++++++++++--------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/algorithms/string/rabin-karp/rabin-karp.test.ts b/src/algorithms/string/rabin-karp/rabin-karp.test.ts index 9d84aca..d236db0 100644 --- a/src/algorithms/string/rabin-karp/rabin-karp.test.ts +++ b/src/algorithms/string/rabin-karp/rabin-karp.test.ts @@ -64,4 +64,19 @@ describe('Rabin-Karp Algorithm', () => { const pattern = 'fox'; expect(rabinKarp(text, pattern)).toEqual([16]); }); + + test('should handle non-ASCII characters without integer overflow', () => { + const ch = String.fromCharCode(50000); + const text = ch.repeat(25); + const pattern = ch.repeat(3); + // Should find all 23 overlapping occurrences + const expected = Array.from({length: 23}, (_, i) => i); + expect(rabinKarp(text, pattern)).toEqual(expected); + }); + + test('should find pattern in Unicode text', () => { + const text = 'こんにちは世界、こんにちは日本'; + const pattern = 'こんにちは'; + expect(rabinKarp(text, pattern)).toEqual([0, 8]); + }); }); diff --git a/src/algorithms/string/rabin-karp/rabin-karp.ts b/src/algorithms/string/rabin-karp/rabin-karp.ts index e5e7929..c6836be 100644 --- a/src/algorithms/string/rabin-karp/rabin-karp.ts +++ b/src/algorithms/string/rabin-karp/rabin-karp.ts @@ -2,8 +2,8 @@ * Performs Rabin-Karp string search using a rolling hash. * Finds all occurrences of a pattern in a text string. * - * Uses a polynomial rolling hash with a large prime modulus - * to efficiently compare substrings. + * Uses a polynomial rolling hash with BigInt arithmetic + * to safely handle non-ASCII characters without integer overflow. * * @param {string} text - The text to search in. * @param {string} pattern - The pattern to search for. @@ -17,21 +17,21 @@ export function rabinKarp(text: string, pattern: string): number[] { if (m === 0) return results; if (m > n) return results; - const base = 256; - const mod = 1_000_000_007; + const base = 256n; + const mod = 1_000_000_007n; // Compute base^(m-1) % mod for removing the leading character - let highPow = 1; + let highPow = 1n; for (let i = 0; i < m - 1; i++) { highPow = (highPow * base) % mod; } // Compute initial hash values for pattern and the first window of text - let patternHash = 0; - let textHash = 0; + let patternHash = 0n; + let textHash = 0n; for (let i = 0; i < m; i++) { - patternHash = (patternHash * base + pattern.charCodeAt(i)) % mod; - textHash = (textHash * base + text.charCodeAt(i)) % mod; + patternHash = (patternHash * base + BigInt(pattern.charCodeAt(i))) % mod; + textHash = (textHash * base + BigInt(text.charCodeAt(i))) % mod; } for (let i = 0; i <= n - m; i++) { @@ -51,9 +51,12 @@ export function rabinKarp(text: string, pattern: string): number[] { // Compute hash for the next window by rolling the hash if (i < n - m) { - textHash = ((textHash - text.charCodeAt(i) * highPow) * base + text.charCodeAt(i + m)) % mod; - // Ensure non-negative - if (textHash < 0) { + textHash = + ((textHash - BigInt(text.charCodeAt(i)) * highPow) * base + + BigInt(text.charCodeAt(i + m))) % + mod; + // Ensure non-negative (BigInt % can return negative) + if (textHash < 0n) { textHash += mod; } }