├── .github └── workflows │ ├── clojure_test.yml │ └── upload_coverage_report.yml ├── .gitignore ├── DIRECTORY.md ├── LICENSE ├── README.md ├── deps.edn ├── src ├── data_structures │ ├── dynamic_array │ │ └── core.clj │ ├── lists │ │ ├── compress.clj │ │ ├── flatten_nested_list.clj │ │ ├── kth_element_in_a_list.clj │ │ ├── last_item_in_a_list.clj │ │ ├── length_of_list.clj │ │ ├── linked_list.clj │ │ ├── pack_consecutive_repetitions_in_sublist.clj │ │ ├── palindrome.clj │ │ ├── penultimate_item_in_a_list.clj │ │ ├── reverse_a_list.clj │ │ └── run_length_encoding.clj │ ├── queue │ │ ├── list.clj │ │ └── vector.clj │ └── stack │ │ └── core.clj ├── linear_algebra │ └── matrices │ │ ├── general.clj │ │ └── operators.clj └── sorts │ ├── heap_sort.clj │ ├── insertion_sort.clj │ ├── merge_sort.clj │ └── quick_sort.clj └── test ├── data_structures ├── dynamic_array │ └── core_test.clj ├── lists │ ├── compress_test.clj │ ├── flatten_nested_list_test.clj │ ├── kth_element_in_a_list_test.clj │ ├── last_item_in_a_list_test.clj │ ├── length_of_list_test.clj │ ├── linked_list_test.clj │ ├── pack_consecutive_repetitions_in_sublist_test.clj │ ├── palindrome_test.clj │ ├── penultimate_item_in_a_list_test.clj │ ├── reverse_a_list_test.clj │ └── run_length_encoding_test.clj ├── queue │ ├── list_test.clj │ └── vector_test.clj └── stack │ └── core_test.clj ├── linear_algebra └── matrices │ ├── general_test.clj │ └── operators_test.clj ├── sorts ├── heap_sort_test.clj ├── insertion_sort_test.clj ├── merge_sort_test.clj └── quick_sort_test.clj └── utils.clj /.github/workflows/clojure_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: clojure_test 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | workflow_dispatch: 7 | push: 8 | branches: 9 | - main 10 | pull_request: 11 | 12 | jobs: 13 | clojure_test: 14 | runs-on: ${{matrix.os}} 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | os: 19 | - ubuntu-latest 20 | clojure_version: 21 | - "1.10.3.1029" 22 | 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v4 26 | 27 | - name: Setup java 28 | uses: actions/setup-java@v3 29 | with: 30 | java-version: 17 31 | distribution: 'adopt' 32 | 33 | - name: Setup clojure 34 | uses: DeLaGuardo/setup-clojure@12.1 35 | with: 36 | cli: ${{matrix.clojure_version}} 37 | 38 | - name: Run tests 39 | run: | 40 | clojure -X:test 41 | ... 42 | -------------------------------------------------------------------------------- /.github/workflows/upload_coverage_report.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: upload_coverage_report 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | workflow_dispatch: 7 | push: 8 | branches: 9 | - main 10 | pull_request: 11 | 12 | jobs: 13 | upload_coverage_report: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | 20 | - name: Setup java 21 | uses: actions/setup-java@v3 22 | with: 23 | java-version: 17 24 | distribution: 'adopt' 25 | 26 | - name: Setup clojure 27 | uses: DeLaGuardo/setup-clojure@12.1 28 | with: 29 | cli: "1.10.3.1029" 30 | 31 | - name: Run tests 32 | run: | 33 | clojure -X:coverage 34 | 35 | - name: Upload coverage to codecov 36 | uses: codecov/codecov-action@v3 37 | with: 38 | files: "target/coverage/codecov.json" 39 | fail_ci_if_error: true 40 | ... 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | profiles.clj 5 | pom.xml 6 | pom.xml.asc 7 | *.jar 8 | *.class 9 | /.lein-* 10 | /.nrepl-port 11 | .hgignore 12 | .hg/ 13 | .idea/ 14 | *.db 15 | CHANGELOG.md 16 | *.iml 17 | /.cpcache 18 | -------------------------------------------------------------------------------- /DIRECTORY.md: -------------------------------------------------------------------------------- 1 | # Problem directory 2 | 3 | 4 | ## Data Structures 5 | 6 | * List 7 | * [List data structure implementation](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/linked_list.clj) 8 | * [Last item in a list](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/last_item_in_a_list.clj) 9 | * [Penultimate item in a list](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/penultimate_item_in_a_list.clj) 10 | * [Length of a list](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/length_of_list.clj) 11 | * [Kth element in a list](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/kth_element_in_a_list.clj) 12 | * [Reverse a list](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/reverse_a_list.clj) 13 | * [Check for palindrome](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/palindrome.clj) 14 | * [Flatten a nested list](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/flatten_nested_list.clj) 15 | * [Compress a list by removing consecutive repetitions](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/compress.clj) 16 | * [Sublist of a list by consecutive repetitions](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/pack_consecutive_repetitions_in_sublist.clj) 17 | * [Run length encoding](https://github.com/TheAlgorithms/Clojure/blob/main/src/data_structures/lists/run_length_encoding.clj) 18 | 19 | * [Dynamic Array implementation](/src/data_structures/dynamic_array/core.clj) 20 | * [Immutable Stack implementation](/src/data_structures/stack/core.clj) 21 | * Immutable Queue implementations 22 | * [using vector](/src/data_structures/queue/vector.clj) 23 | * [using list](/src/data_structures/queue/list.clj) 24 | 25 | ## Sorting 26 | * [Merge Sort](https://github.com/TheAlgorithms/Clojure/blob/main/src/sorts/merge_sort.clj) 27 | * [Quick Sort](https://github.com/TheAlgorithms/Clojure/blob/main/src/sorts/quick_sort.clj) 28 | * [Heap Sort](https://github.com/TheAlgorithms/Clojure/blob/main/src/sorts/heap_sort.clj) 29 | * [Insertion Sort](https://github.com/TheAlgorithms/Clojure/blob/main/src/sorts/insertion_sort.clj) 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | 3 | MIT License 4 | 5 | Copyright (c) 2016-2021 The Algorithms 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Algorithms - Clojure 2 | [![CodeCoverage](https://codecov.io/gh/TheAlgorithms/Clojure/graph/badge.svg?token=nRkPKfbs42)](https://codecov.io/gh/TheAlgorithms/Clojure)  3 | [![Discord](https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=00d37d)](https://the-algorithms.com/discord)  4 | [![Gitter chat](https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square)](https://gitter.im/TheAlgorithms)  5 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg?logo=paypal&style=flat-square)](https://www.paypal.me/TheAlgorithms/100)  6 | [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod&style=flat-square)](https://gitpod.io/#https://github.com/TheAlgorithms/Clojure)  7 | 8 | ### All algorithms implemented in Clojure (for education) 9 | 10 | These implementations are for learning purposes only. Therefore they may be less efficient than the implementations in the Clojure standard library. 11 | 12 | #### To run all the tests execute 13 | ```bash 14 | clojure -X:test 15 | ``` 16 | 17 | ## List of Algorithms 18 | 19 | See our [directory](DIRECTORY.md). 20 | 21 | ## Community Channel 22 | 23 | We're on [Gitter](https://gitter.im/TheAlgorithms)! Please join us. 24 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src"] 2 | :deps {org.clojure/clojure {:mvn/version "1.11.1"}} 3 | :aliases {:test {:extra-paths ["test"] 4 | :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"} 5 | io.github.cognitect-labs/test-runner {:git/tag "v0.5.0" :git/sha "48c3c67"}} 6 | :exec-fn cognitect.test-runner.api/test} 7 | :coverage {:extra-paths ["test"] 8 | :extra-deps {cloverage/cloverage {:mvn/version "1.2.4"}} 9 | :main-opts ["--main" "cloverage.coverage" 10 | "--test-ns-path" "test"] 11 | :exec-fn cloverage.coverage/run-project 12 | :exec-args {:src-ns-path ["src"] 13 | :test-ns-path ["test"] 14 | :codecov? true}}}} 15 | -------------------------------------------------------------------------------- /src/data_structures/dynamic_array/core.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.dynamic-array.core 2 | (:refer-clojure :exclude [get set empty? remove])) 3 | 4 | ;; See tests for the documentation on implementation 5 | 6 | (defn ->DynamicArray 7 | [initial-capacity] 8 | (when (>= 0 initial-capacity) 9 | (throw (IllegalArgumentException. "Invalid initial capacity"))) 10 | [initial-capacity []]) 11 | 12 | (defn capacity 13 | [dynamic-array] 14 | (let [[cap _] dynamic-array] 15 | cap)) 16 | 17 | (defn length 18 | [dynamic-array] 19 | (let [[_ store] dynamic-array] 20 | (count store))) 21 | 22 | (defn empty? 23 | [dynamic-array] 24 | (zero? (length dynamic-array))) 25 | 26 | (defn get 27 | [dynamic-array idx] 28 | (assert (< -1 idx (length dynamic-array)) "Invalid index value supplied") 29 | (let [[_ store] dynamic-array] 30 | (nth store idx))) 31 | 32 | (defn set 33 | [dynamic-array idx value] 34 | (assert (<= 0 idx) "Invalid index value supplied") 35 | (let [[capacity store] dynamic-array] 36 | (if (< idx (dec capacity)) 37 | [capacity (assoc store idx value)] 38 | [(* 2 (inc idx)) (into [] 39 | cat 40 | [store 41 | (vec (repeat (- idx (count store)) nil)) 42 | [value]])]))) 43 | 44 | (defn remove 45 | [dynamic-array idx] 46 | (assert (< -1 idx (length dynamic-array)) "Invalid index value supplied") 47 | (let [[capacity store] dynamic-array] 48 | [capacity (into [] 49 | cat 50 | [(subvec store 0 idx) 51 | (subvec store (inc idx))])])) 52 | 53 | (defn next-idx 54 | [dynamic-array] 55 | (length dynamic-array)) 56 | 57 | (defn append 58 | [dynamic-array value] 59 | (let [[capacity store] dynamic-array] 60 | (if (not= capacity (count store)) 61 | [capacity (conj store value)] 62 | [(* 2 capacity) (conj store value)]))) 63 | 64 | (defn pop-array 65 | [dynamic-array] 66 | (assert (not (empty? dynamic-array)) "Nothing to pop") 67 | (let [[capacity store] dynamic-array] 68 | [capacity (pop store)])) 69 | 70 | (defn to-string 71 | [dynamic-array] 72 | (let [^StringBuilder sb (StringBuilder.)] 73 | (.append sb "[ ") 74 | (doseq [i (range (length dynamic-array))] 75 | (.append sb (get dynamic-array i)) 76 | (.append sb " ")) 77 | (.append sb "]") 78 | (.toString sb))) 79 | -------------------------------------------------------------------------------- /src/data_structures/lists/compress.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.compress) 2 | 3 | (defn compress-1 4 | [ls] 5 | (loop [ls ls 6 | acc [] 7 | prev nil] 8 | (if (empty? ls) 9 | acc 10 | (let [[head & tail] ls] 11 | (if (= head prev) 12 | (recur tail acc prev) 13 | (recur tail (concat acc [head]) head)))))) 14 | 15 | (defn compress-2 16 | [ls] 17 | (if (empty? ls) 18 | [] 19 | (->> (reduce (fn [acc x] 20 | (if (= x (first acc)) 21 | acc 22 | (conj acc x))) '() ls) 23 | reverse))) 24 | 25 | (defn compress-3 26 | [ls] 27 | ((comp (partial map first) 28 | (partial partition-by identity)) ls)) 29 | -------------------------------------------------------------------------------- /src/data_structures/lists/flatten_nested_list.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.flatten-nested-list) 2 | 3 | ;Flatten a nested list structure. 4 | ;Transform a list, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively). 5 | ; 6 | ;Example: 7 | ;* (my-flatten '(a (b (c d) e))) 8 | ;(A B C D E) 9 | 10 | (defn flatten-1 11 | "Non tail recursive way which will eventually blow the stack up" 12 | [ls] 13 | (if (empty? ls) 14 | '() 15 | (let [[head & tail] ls] 16 | (if (coll? head) 17 | (concat (flatten-1 head) (flatten-1 tail)) 18 | (conj (flatten-1 tail) head))))) 19 | 20 | (defn flatten-2 21 | "Tail recursive way" 22 | [ls] 23 | (loop [ls ls 24 | acc []] 25 | (if (empty? ls) 26 | acc 27 | (let [head (first ls) 28 | tail (rest ls)] 29 | (if (coll? head) 30 | (recur (concat head tail) acc) 31 | (recur tail (conj acc head))))))) -------------------------------------------------------------------------------- /src/data_structures/lists/kth_element_in_a_list.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.kth-element-in-a-list) 2 | 3 | (defn get-kth-element-1 4 | [ls k] 5 | (if (or (empty? ls) (= 1 k)) 6 | (first ls) 7 | (recur (rest ls) (dec k)))) 8 | 9 | (defn get-kth-element-2 10 | [ls k] 11 | (first (drop (dec k) ls))) -------------------------------------------------------------------------------- /src/data_structures/lists/last_item_in_a_list.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.last-item-in-a-list) 2 | 3 | ;(*) Find the last box of a list. 4 | ;Example: 5 | ;* (my-last '(a b c d)) 6 | ;(d) 7 | 8 | (defn get-last-item 9 | [[head & tail]] 10 | (if (empty? tail) 11 | head 12 | (recur tail))) 13 | -------------------------------------------------------------------------------- /src/data_structures/lists/length_of_list.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.length-of-list) 2 | 3 | (defn length-of-list-1 4 | [ls] 5 | (loop [ls ls count 0] 6 | (if (empty? ls) 7 | count 8 | (recur (rest ls) (inc count))))) 9 | 10 | (defn length-of-list-2 11 | [ls] 12 | ((comp 13 | (partial apply +) 14 | (partial map (constantly 1))) ls)) 15 | -------------------------------------------------------------------------------- /src/data_structures/lists/linked_list.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.linked-list) 2 | 3 | (defprotocol LinkedList 4 | (is-empty? [lst]) 5 | (prepend [lst value]) 6 | (head [lst]) 7 | (tail [lst])) 8 | 9 | (defrecord Cons [value next] 10 | LinkedList 11 | (is-empty? [_] (nil? next)) 12 | (prepend [lst new-value] (->Cons new-value lst)) 13 | (head [lst] value) 14 | (tail [lst] next)) 15 | 16 | (defn linked-list->collection 17 | ([linked-list] 18 | (linked-list->collection linked-list [])) 19 | ([linked-list empty-collection] 20 | (let [accumulator (conj empty-collection (head linked-list))] 21 | (if (is-empty? linked-list) 22 | accumulator 23 | (recur (tail linked-list) accumulator))))) 24 | -------------------------------------------------------------------------------- /src/data_structures/lists/pack_consecutive_repetitions_in_sublist.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.pack-consecutive-repetitions-in-sublist) 2 | 3 | (defn pack-1 4 | [ls] 5 | (-> (reduce (fn [acc x] 6 | (if (and (seq? (first acc)) (= (first (first acc)) x)) 7 | (cons (cons x (first acc)) (rest acc)) 8 | (cons (list x) acc))) () ls) 9 | reverse)) 10 | 11 | (defn pack-2 12 | [ls] 13 | (partition-by identity ls)) 14 | 15 | (defn pack-3 16 | [ls] 17 | (lazy-seq 18 | (when-let [s (seq ls)] 19 | (let [f (first s) 20 | repeated-elements (take-while #(= f %) s)] 21 | (cons repeated-elements (pack-3 (drop (count repeated-elements) s))))))) 22 | -------------------------------------------------------------------------------- /src/data_structures/lists/palindrome.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.palindrome) 2 | 3 | (defn palindrome-1? 4 | [ls] 5 | (= ls (reduce conj () ls))) 6 | 7 | (defn palindrome-2? 8 | [ls] 9 | (= 0 (compare (vec ls) (vec (reduce conj () ls))))) 10 | 11 | (defn palindrome-3? [ls] 12 | (loop [front 0 back (dec (count ls))] 13 | (or (>= front back) 14 | (and (= (nth ls front) (nth ls back)) 15 | (recur (inc front) (dec back)))))) 16 | 17 | -------------------------------------------------------------------------------- /src/data_structures/lists/penultimate_item_in_a_list.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.penultimate-item-in-a-list) 2 | 3 | ;(*) Find the last but one box of a list. 4 | ;Example: 5 | ;* (my-but-last '(a b c d)) 6 | ;(C D) 7 | 8 | (defn get-penultimate-item 9 | [[head snd & tail]] 10 | (if (nil? snd) 11 | nil 12 | (if (empty? tail) 13 | head 14 | (recur (cons snd tail))))) -------------------------------------------------------------------------------- /src/data_structures/lists/reverse_a_list.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.reverse-a-list) 2 | 3 | (defn reverse-list-01 4 | [ls] 5 | (loop [ls ls acc ()] 6 | (if (empty? ls) 7 | acc 8 | (recur (rest ls) (conj acc (first ls)))))) 9 | 10 | (defn reverse-list-02 11 | [ls] 12 | (if (empty? ls) 13 | '() 14 | (reduce conj () ls))) 15 | 16 | (defn reverse-list-03 17 | [ls] 18 | (into () (into [] ls))) -------------------------------------------------------------------------------- /src/data_structures/lists/run_length_encoding.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.run-length-encoding) 2 | 3 | ;Run-length encoding of a list. 4 | ;Use the result of packing consecutive repetitions to implement the so-called run-length encoding data compression method. 5 | ;Consecutive duplicates of elements are encoded as lists (N E) where N is the number of duplicates of 6 | ;the element E. 7 | 8 | (defn encode-1 9 | [ls] 10 | ((comp 11 | (partial map #(list (count %) (first %))) 12 | (partial partition-by identity)) ls)) 13 | 14 | (defn encode-2 15 | [ls] 16 | (lazy-seq 17 | (when-let [s (seq ls)] 18 | (let [f (first s) 19 | repeated (take-while #(= f %) s) 20 | count-of-repeated (count repeated)] 21 | (cons (list count-of-repeated f) 22 | (encode-2 (drop count-of-repeated s))))))) -------------------------------------------------------------------------------- /src/data_structures/queue/list.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.queue.list) 2 | 3 | (defn ->Queue 4 | [] 5 | '()) 6 | 7 | (defn enqueue 8 | [queue value] 9 | (conj queue value)) 10 | 11 | (defn dequeue 12 | [queue] 13 | (if (empty? queue) 14 | queue 15 | (drop-last 1 queue))) 16 | 17 | (defn peek-queue 18 | "this implementation is more performant than using `last` or `reverse` 19 | they both traverse the entire collection whereas count is stored on the PersistenceList object" 20 | [queue] 21 | (when-not (empty? queue) 22 | (nth queue (dec (count queue))))) 23 | 24 | (defn empty-queue? 25 | [queue] 26 | (empty? queue)) 27 | -------------------------------------------------------------------------------- /src/data_structures/queue/vector.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.queue.vector) 2 | 3 | (defn ->Queue 4 | [] 5 | []) 6 | 7 | (defn enqueue 8 | [queue value] 9 | (conj queue value)) 10 | 11 | (defn dequeue 12 | [queue] 13 | (if (empty? queue) 14 | queue 15 | (subvec queue 1))) 16 | 17 | (defn peek-queue 18 | [queue] 19 | (first queue)) 20 | 21 | (defn empty-queue? 22 | [queue] 23 | (empty? queue)) 24 | -------------------------------------------------------------------------------- /src/data_structures/stack/core.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.stack.core) 2 | 3 | (defn ->Stack 4 | [length] 5 | [length []]) 6 | 7 | (defn length 8 | [stack] 9 | (first stack)) 10 | 11 | (defn empty-stack? 12 | [stack] 13 | (let [[_ store] stack] 14 | (= (count store) 0))) 15 | 16 | (defn full-stack? 17 | [stack] 18 | (let [[length store] stack] 19 | (= (count store) length))) 20 | 21 | (defn push-in-stack 22 | [stack val] 23 | (assert (not (full-stack? stack)) "Stack is full") 24 | (let [[length store] stack] 25 | [length (conj store val)])) 26 | 27 | (defn pop-from-stack 28 | [stack] 29 | (if (empty-stack? stack) 30 | stack 31 | (let [[length store] stack] 32 | [length (pop store)]))) 33 | 34 | (defn peek-at-stack 35 | [stack] 36 | (when-not (empty-stack? stack) 37 | (let [[_ store] stack] 38 | (nth store (dec (count store)))))) 39 | 40 | (defn to-string 41 | [stack] 42 | (let [sb (StringBuilder.)] 43 | (.append sb "[ ") 44 | (let [[_ store] stack] 45 | (doseq [el store] 46 | (.append sb el) 47 | (.append sb " "))) 48 | (.append sb "]") 49 | (.toString sb))) 50 | -------------------------------------------------------------------------------- /src/linear_algebra/matrices/general.clj: -------------------------------------------------------------------------------- 1 | (ns linear-algebra.matrices.general) 2 | 3 | (defn matrix 4 | ([m] 5 | (matrix m m)) 6 | ([m n] 7 | (matrix m n (vec (repeat (* m n) 0)))) 8 | ([m n A] 9 | (if (= (* m n) (count A)) 10 | (vec (map #(subvec A (* % n) (* (inc %) n)) 11 | (range m))) 12 | nil))) 13 | 14 | (defn identity-matrix [m] 15 | (loop [id-mat [] row 0] 16 | (if (>= row m) 17 | id-mat 18 | (recur (conj id-mat (vec (concat (repeat row 0) [1] (repeat (- m row 1) 0)))) 19 | (inc row))))) 20 | 21 | 22 | (defn get-dimensions [A] 23 | [(count A) (count (nth A 0))]) 24 | 25 | (defn get-element [m n A] 26 | (if (and (< m (first (get-dimensions A))) 27 | (< n (last (get-dimensions A)))) 28 | (nth (nth A m) n) 29 | nil)) 30 | 31 | -------------------------------------------------------------------------------- /src/linear_algebra/matrices/operators.clj: -------------------------------------------------------------------------------- 1 | (ns linear-algebra.matrices.operators 2 | (:require [linear-algebra.matrices.general :refer :all])) 3 | 4 | (defn item-by-item [op A B] 5 | (if (= (get-dimensions A) (get-dimensions B)) 6 | (loop [res [] row 0] 7 | (if (>= row (first (get-dimensions A))) 8 | res 9 | (recur (conj res (mapv op (nth A row) (nth B row))) 10 | (inc row)))) 11 | nil)) 12 | 13 | (defn add [A B] 14 | (item-by-item + A B)) 15 | 16 | (defn sub [A B] 17 | (item-by-item - A B)) 18 | -------------------------------------------------------------------------------- /src/sorts/heap_sort.clj: -------------------------------------------------------------------------------- 1 | (ns sorts.heap-sort 2 | (:import 3 | (java.util Collection) 4 | [java.util.concurrent PriorityBlockingQueue])) 5 | 6 | (defn lazy-heap-sort 7 | [long-seq] 8 | (let [heap (PriorityBlockingQueue. ^Collection long-seq)] 9 | (repeatedly (count long-seq) #(.take heap)))) 10 | -------------------------------------------------------------------------------- /src/sorts/insertion_sort.clj: -------------------------------------------------------------------------------- 1 | (ns sorts.insertion-sort) 2 | 3 | (defn insertion-sort 4 | [number-seq] 5 | (loop [sorted [] 6 | unsorted number-seq] 7 | (if (empty? unsorted) 8 | sorted 9 | (let [x (first unsorted) 10 | smaller (filter #(<= % x) sorted) 11 | larger (filter #(> % x) sorted)] 12 | (recur (concat smaller [x] larger) (rest unsorted)))))) 13 | -------------------------------------------------------------------------------- /src/sorts/merge_sort.clj: -------------------------------------------------------------------------------- 1 | (ns sorts.merge-sort) 2 | 3 | (defn mrg 4 | "Merge the left and right arrays" 5 | [[l & restl :as left] [r & restr :as right]] 6 | (cond 7 | (and left (empty? right)) left 8 | (and (empty? left) right) right 9 | (and left right) (if (< l r) 10 | (cons l (mrg restl right)) 11 | (cons r (mrg left restr))))) 12 | 13 | (defn merge-sort 14 | "This is a pure Clojure implementation of the merge sort algorithm" 15 | [collection] 16 | (if (< (count collection) 2) 17 | collection ; this either empty or single 18 | (let [midpoint (/ (count collection) 2) 19 | [left right] (split-at midpoint collection)] 20 | (mrg (merge-sort left) (merge-sort right))))) 21 | (defn lazy-merge-sort 22 | [int-seq] 23 | (letfn [(merge* 24 | [[f1 & r1 :as l1] [f2 & r2 :as l2]] 25 | (cond 26 | (nil? f1) l2 27 | (nil? f2) l1 28 | (<= f1 f2) (lazy-seq (cons f1 (merge* r1 l2))) 29 | (> f1 f2) (lazy-seq (cons f2 (merge* l1 r2)))))] 30 | (if (next int-seq) 31 | (let [[left right] (split-at (/ (count int-seq) 2) int-seq)] 32 | (merge* (lazy-merge-sort left) (lazy-merge-sort right))) 33 | int-seq))) 34 | -------------------------------------------------------------------------------- /src/sorts/quick_sort.clj: -------------------------------------------------------------------------------- 1 | (ns sorts.quick-sort) 2 | 3 | (defn lazy-quick-sort [[head & tail]] 4 | (when head 5 | (lazy-cat (lazy-quick-sort (filter #(< % head) tail)) 6 | [head] 7 | (lazy-quick-sort (remove #(< % head) tail))))) 8 | 9 | (defn quick-sort 10 | [int-seq] 11 | (loop [done [] 12 | [part & parts] (list int-seq)] 13 | (if-let [[pivot & xs] (seq part)] 14 | (recur 15 | done 16 | (let [smaller? #(< % pivot)] 17 | (list* 18 | (filter smaller? xs) 19 | pivot 20 | (remove smaller? xs) 21 | parts))) 22 | (if-let [[x & parts] parts] 23 | (recur (conj done x) parts) 24 | done)))) 25 | -------------------------------------------------------------------------------- /test/data_structures/dynamic_array/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.dynamic-array.core-test 2 | (:require [clojure.test :refer [deftest testing is]] 3 | [data-structures.dynamic-array.core :as da])) 4 | 5 | (deftest ->DynamicArray-test 6 | (testing "throws when invalid initial capacity is provided" 7 | (is (thrown? IllegalArgumentException (da/->DynamicArray 0))) 8 | (is (thrown? IllegalArgumentException (da/->DynamicArray -1)))) 9 | 10 | (testing "returns a dynamic array for a valid capacity" 11 | (is (= [3 []] (da/->DynamicArray 3))))) 12 | 13 | (deftest empty?-test 14 | (testing "return true if dynamic array is empty" 15 | (let [dynamic-array (da/->DynamicArray 3)] 16 | (is (true? (da/empty? dynamic-array))))) 17 | 18 | (testing "return false if dynamic array is empty" 19 | (is (false? (da/empty? (-> (da/->DynamicArray 3) 20 | (da/append 10) 21 | (da/append 20))))))) 22 | 23 | (deftest length-test 24 | (testing "returns the length of the dynamic array" 25 | (let [dynamic-array (da/->DynamicArray 3)] 26 | (is (= 0 (da/length dynamic-array))) 27 | (is (= 3 (da/capacity dynamic-array))))) 28 | 29 | (testing "returns the length of the dynamic array" 30 | (let [dynamic-array (-> (da/->DynamicArray 3) 31 | (da/append 10) 32 | (da/append 20) 33 | (da/append 30) 34 | (da/append 40))] 35 | (is (= 4 (da/length dynamic-array))) 36 | (is (= 6 (da/capacity dynamic-array)))))) 37 | 38 | (deftest next-idx-test 39 | (testing "returns initial index as the starting point when dynamic array is empty" 40 | (let [dynamic-array (da/->DynamicArray 3)] 41 | (is (= 0 (da/next-idx dynamic-array))))) 42 | 43 | (testing "returns current filled index as the starting point when dynamic array is empty" 44 | (is (= 3 (as-> (da/->DynamicArray 3) dynamic-array 45 | (da/set dynamic-array (da/next-idx dynamic-array) 10) 46 | (da/set dynamic-array (da/next-idx dynamic-array) 20) 47 | (da/set dynamic-array (da/next-idx dynamic-array) 30) 48 | (da/next-idx dynamic-array)))))) 49 | 50 | (deftest set-test 51 | (testing "throws Assertion error when index is less than 0" 52 | (let [dynamic-array (da/->DynamicArray 3)] 53 | (is (thrown? AssertionError (da/set dynamic-array -1 10))))) 54 | 55 | (testing "stores the element within the dynamic array when a valid index is provided" 56 | (let [dynamic-array (as-> (da/->DynamicArray 3) dynamic-array 57 | (da/set dynamic-array (da/next-idx dynamic-array) 10))] 58 | (is (false? (da/empty? dynamic-array))) 59 | (is (= 1 (da/next-idx dynamic-array))))) 60 | 61 | (testing "expands dynamic array to incorporate more elements" 62 | (let [dynamic-array (as-> (da/->DynamicArray 3) dynamic-array 63 | (da/set dynamic-array (da/next-idx dynamic-array) 10) 64 | (da/set dynamic-array (da/next-idx dynamic-array) 20) 65 | (da/set dynamic-array (da/next-idx dynamic-array) 30) 66 | (da/set dynamic-array (da/next-idx dynamic-array) 40))] 67 | (is (= 4 (da/next-idx dynamic-array))) 68 | (is (= 6 (da/capacity dynamic-array))))) 69 | 70 | (testing "expands dynamic array to incorporate for an arbitrary large index and sets next-idx accordingly" 71 | (let [dynamic-array (as-> (da/->DynamicArray 3) dynamic-array 72 | (da/set dynamic-array (da/next-idx dynamic-array) 10) 73 | (da/set dynamic-array (da/next-idx dynamic-array) 20) 74 | (da/set dynamic-array (da/next-idx dynamic-array) 30) 75 | (da/set dynamic-array (da/next-idx dynamic-array) 40) 76 | (da/set dynamic-array 60 40))] 77 | (is (= 61 (da/next-idx dynamic-array)) "This behaviour causes fragmentation in the dynamic array") 78 | (is (= 122 (da/capacity dynamic-array)))))) 79 | 80 | (deftest get-test 81 | (let [dynamic-array (da/->DynamicArray 3)] 82 | (testing "throws Assertion error when index is less than 0" 83 | (is (thrown? AssertionError (da/get dynamic-array -1)))) 84 | 85 | (testing "throws Assertion error when index is greater than next-index" 86 | (is (thrown? AssertionError (da/get dynamic-array (inc (da/next-idx dynamic-array)))))) 87 | 88 | (testing "fetches the content of the dynamic array stored at valid index" 89 | (da/set dynamic-array (da/next-idx dynamic-array) 40) 90 | (is (= 40 (as-> dynamic-array $ 91 | (da/set $ (da/next-idx $) 40) 92 | (da/get $ (dec (da/next-idx $))))))))) 93 | 94 | (deftest remove-test 95 | (let [dynamic-array (da/->DynamicArray 3)] 96 | (testing "throws Assertion error when index is less than 0" 97 | (is (thrown? AssertionError (da/remove dynamic-array -1)))) 98 | 99 | (testing "throws Assertion error when index is greater than next index" 100 | (is (thrown? AssertionError (da/remove dynamic-array (inc (da/next-idx dynamic-array)))))) 101 | 102 | (testing "removes the element from the dynamic array and returns it if the index is valid" 103 | (let [dynamic-array (as-> dynamic-array $ 104 | (da/set $ (da/next-idx $) 10) 105 | (da/set $ (da/next-idx $) 20) 106 | (da/set $ (da/next-idx $) 30) 107 | (da/set $ (da/next-idx $) 40))] 108 | (is (= 4 (da/next-idx dynamic-array)) "Sanity check to ensure that next-index is correctly calculated") 109 | (is (= [6 [10 20 40]] (da/remove dynamic-array 2))) 110 | (is (= 3 (da/next-idx (da/remove dynamic-array 2)))) 111 | (is (= "[ 10 20 40 ]" (da/to-string (da/remove dynamic-array 2)))))))) 112 | 113 | (deftest append-test 114 | (testing "appends values to dynamic array" 115 | (let [dynamic-array (-> (da/->DynamicArray 3) 116 | (da/append 10) 117 | (da/append 20))] 118 | (is (= 2 (da/next-idx dynamic-array))) 119 | (is (= 3 (da/capacity dynamic-array))) 120 | 121 | (testing "expands dynamic array to allocate more elements" 122 | (let [dynamic-array (-> dynamic-array 123 | (da/append 30) 124 | (da/append 40))] 125 | (is (= 4 (da/next-idx dynamic-array))) 126 | (is (= 6 (da/capacity dynamic-array)))))))) 127 | 128 | (deftest pop-array-test 129 | (let [dynamic-array (da/->DynamicArray 3)] 130 | (testing "throws when the dynamic array is empty" 131 | (is (thrown? AssertionError (da/pop-array dynamic-array)))) 132 | 133 | (testing "pops the element from dynamic array and returns it" 134 | (let [dynamic-array (-> dynamic-array 135 | (da/append 10) 136 | (da/append 20) 137 | (da/append 30) 138 | (da/pop-array))] 139 | (is (= [3 [10 20]] dynamic-array)) 140 | (is (= 2 (da/next-idx dynamic-array))))))) 141 | 142 | (deftest to-string-test 143 | (testing "provides string representation of an empty array" 144 | (let [dynamic-array (da/->DynamicArray 3)] 145 | (is (= "[ ]" (da/to-string dynamic-array))))) 146 | 147 | (testing "provides string representation of a non empty array" 148 | (with-local-vars [dynamic-array (da/->DynamicArray 10)] 149 | (doseq [i (range 10 15)] 150 | (var-set dynamic-array (da/append (var-get dynamic-array) i))) 151 | (is (= "[ 10 11 12 13 14 ]" (da/to-string (var-get dynamic-array))))))) 152 | -------------------------------------------------------------------------------- /test/data_structures/lists/compress_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.compress-test 2 | (:require [clojure.test :refer :all] 3 | [data-structures.lists.compress :refer :all])) 4 | 5 | (deftest compress-1-test 6 | (testing "returns only the single occurrence of members" 7 | (is (= '("a" "b" "c" "d" "e") (compress-1 '("a" "a" "a" "b" "b" "c" "c" "d" "e" "e"))))) 8 | (testing "returns empty list for empty list input" 9 | (let [actual (compress-1 '())] 10 | (is (and (coll? actual) (empty? actual)))))) 11 | 12 | (deftest compress-2-test 13 | (testing "returns only the single occurrence of members" 14 | (is (= '("a" "b" "c" "d" "e") (compress-2 '("a" "a" "a" "b" "b" "c" "c" "d" "e" "e"))))) 15 | (testing "returns empty list for empty list input" 16 | (let [actual (compress-2 '())] 17 | (is (and (coll? actual) (empty? actual)))))) 18 | 19 | (deftest compress-3-test 20 | (testing "returns only the single occurrence of members" 21 | (is (= '("a" "b" "c" "d" "e") (compress-3 '("a" "a" "a" "b" "b" "c" "c" "d" "e" "e"))))) 22 | (testing "returns empty list for empty list input" 23 | (let [actual (compress-3 '())] 24 | (is (and (coll? actual) (empty? actual)))))) -------------------------------------------------------------------------------- /test/data_structures/lists/flatten_nested_list_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.flatten-nested-list-test 2 | (:require [clojure.test :refer :all] 3 | [data-structures.lists.flatten-nested-list :refer :all])) 4 | 5 | 6 | (deftest flatten-1-test 7 | (testing "should flatten and return the a flat list" 8 | (is (= '(:a :b :c :d :e :f :g :h :i :j) (flatten-1 [:a [:b [:c [:d [:e [:f] :g] :h] :i] :j]])))) 9 | (testing "should return a empty list for input empty list" 10 | (is (coll? (flatten-1 '()))) 11 | (is (empty? (flatten-1 '()))))) 12 | 13 | (deftest flatten-2-test 14 | (testing "should flatten and return the a flat list" 15 | (is (= '(:a :b :c :d :e :f :g :h :i :j) (flatten-2 [:a [:b [:c [:d [:e [:f] :g] :h] :i] :j]])))) 16 | (testing "should return a empty list for input empty list" 17 | (is (coll? (flatten-2 '()))) 18 | (is (empty? (flatten-2 '()))))) 19 | -------------------------------------------------------------------------------- /test/data_structures/lists/kth_element_in_a_list_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.kth-element-in-a-list-test 2 | (:require [clojure.test :refer :all] 3 | [data-structures.lists.kth-element-in-a-list :as kth-element-in-a-list])) 4 | 5 | (deftest get-kth-element-test 6 | (testing "should return c when index k = 3" 7 | (is (= "c" (kth-element-in-a-list/get-kth-element-1 (list "a" "b" "c" "d") 3)))) 8 | (testing "should return nil when index k = 4 and list has 3 elements" 9 | (is (nil? (kth-element-in-a-list/get-kth-element-1 (list "a" "b" "c") 4)))) 10 | (testing "should return nil when index k = 4 and list is empty" 11 | (is (nil? (kth-element-in-a-list/get-kth-element-1 (list) 4))))) 12 | 13 | (deftest get-kth-element-2-test 14 | (testing "should return c when index k = 3" 15 | (is (= "c" (kth-element-in-a-list/get-kth-element-2 (list "a" "b" "c" "d") 3)))) 16 | (testing "should return nil when index k = 4 and list has 3 elements" 17 | (is (nil? (kth-element-in-a-list/get-kth-element-2 (list "a" "b" "c") 4)))) 18 | (testing "should return nil when index k = 4 and list is empty" 19 | (is (nil? (kth-element-in-a-list/get-kth-element-2 (list) 4))))) 20 | -------------------------------------------------------------------------------- /test/data_structures/lists/last_item_in_a_list_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.last-item-in-a-list-test 2 | (:require 3 | [clojure.test :refer :all] 4 | [data-structures.lists.last-item-in-a-list :refer [get-last-item]])) 5 | 6 | (deftest get-last-item-test 7 | (testing "should return the last element of list" 8 | (is (is (= "d" (get-last-item (list "a" "b" "c" "d")))))) 9 | 10 | (testing "should return nil if the list is empty" 11 | (is (nil? (get-last-item (list)))))) 12 | -------------------------------------------------------------------------------- /test/data_structures/lists/length_of_list_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.length-of-list-test 2 | (:require 3 | [clojure.test :refer :all] 4 | [data-structures.lists.length-of-list :refer :all])) 5 | 6 | (deftest length-of-list-1-test 7 | (testing "should return a length of 4" 8 | (is (= 4 (length-of-list-1 (list 1 2 3 4))))) 9 | (testing "should return a length of 0" 10 | (is (= 0 (length-of-list-1 (list))))) 11 | (testing "should return a length of 5" 12 | (is (= 5 (length-of-list-1 (list 1 2 3 4 5)))))) 13 | 14 | 15 | (deftest length-of-list-2-test 16 | (testing "should return a length of 4" 17 | (is (= 4 (length-of-list-2 (list 1 2 3 4))))) 18 | (testing "should return a length of 0" 19 | (is (= 0 (length-of-list-2 (list))))) 20 | (testing "should return a length of 5" 21 | (is (= 5 (length-of-list-2 (list 1 2 3 4 5)))))) 22 | -------------------------------------------------------------------------------- /test/data_structures/lists/linked_list_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.linked-list-test 2 | (:require 3 | [clojure.test :refer [deftest testing is]] 4 | [data-structures.lists.linked-list :refer [->Cons linked-list->collection]])) 5 | 6 | (deftest linked-list->collection-test 7 | (testing "returns a collection from LinkedList" 8 | (is (= [1 3 4 2] 9 | (linked-list->collection (->Cons 1 (->Cons 3 (->Cons 4 (->Cons 2 nil))))))))) 10 | -------------------------------------------------------------------------------- /test/data_structures/lists/pack_consecutive_repetitions_in_sublist_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.pack-consecutive-repetitions-in-sublist-test 2 | (:require [clojure.test :refer :all] 3 | [data-structures.lists.pack-consecutive-repetitions-in-sublist :refer :all])) 4 | 5 | 6 | (deftest pack-1-test 7 | (testing "should return separate lists of members with their repeated occurrences of list" 8 | (is (= [[1 1 1] [2] [3 3 3] [4 4]] (pack-1 [1 1 1 2 3 3 3 4 4])))) 9 | (testing "should return separate lists of members of list" 10 | (is (= [[1] [2] [3] [4]] (pack-1 [1 2 3 4])))) 11 | (testing "should empty list for empty list" 12 | (let [actual (pack-1 [])] 13 | (is (and (coll? actual) (empty? actual)))))) 14 | 15 | (deftest pack-2-test 16 | (testing "should return separate lists of members with their repeated occurrences of list" 17 | (is (= [[1 1 1] [2] [3 3 3] [4 4]] (pack-2 [1 1 1 2 3 3 3 4 4])))) 18 | (testing "should return separate lists of members of list" 19 | (is (= [[1] [2] [3] [4]] (pack-2 [1 2 3 4])))) 20 | (testing "should empty list for empty list" 21 | (let [actual (pack-2 [])] 22 | (is (and (coll? actual) (empty? actual)))))) 23 | 24 | (deftest pack-3-test 25 | (testing "should return separate lists of members with their repeated occurrences of list" 26 | (is (= [[1 1 1] [2] [3 3 3] [4 4]] (pack-3 [1 1 1 2 3 3 3 4 4])))) 27 | (testing "should return separate lists of members of list" 28 | (is (= [[1] [2] [3] [4]] (pack-3 [1 2 3 4])))) 29 | (testing "should empty list for empty list" 30 | (let [actual (pack-3 [])] 31 | (is (and (coll? actual) (empty? actual)))))) -------------------------------------------------------------------------------- /test/data_structures/lists/palindrome_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.palindrome-test 2 | (:require [clojure.test :refer :all] 3 | [data-structures.lists.palindrome :refer :all])) 4 | 5 | (deftest palindrome-1?-test 6 | (testing "should return true for a palindrome" 7 | (is (true? (palindrome-1? [:x :a :m :a :x])))) 8 | (testing "should return false for an empty list" 9 | (is (false? (palindrome-1? [:s :i :m]))))) 10 | 11 | (deftest palindrome-2?-test 12 | (testing "should return true for a palindrome" 13 | (is (true? (palindrome-2? [:x :a :m :a :x])))) 14 | (testing "should return false for an empty list" 15 | (is (false? (palindrome-2? [:s :i :m]))))) 16 | 17 | (deftest palindrome-3?-test 18 | (testing "should return true for a palindrome" 19 | (is (true? (palindrome-3? [:x :a :m :a :x])))) 20 | (testing "should return false for an empty list" 21 | (is (false? (palindrome-3? [:s :i :m]))))) 22 | -------------------------------------------------------------------------------- /test/data_structures/lists/penultimate_item_in_a_list_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.penultimate-item-in-a-list-test 2 | (:require [clojure.test :refer :all] 3 | [data-structures.lists.penultimate-item-in-a-list :refer [get-penultimate-item]])) 4 | 5 | (deftest get-penultimate-item-test 6 | (testing "should return c as the second but last element" 7 | (is (= "c" (get-penultimate-item (list "a" "b" "c" "d"))))) 8 | (testing "should return a as the second but last element" 9 | (is (= "a" (get-penultimate-item (list "a" "b"))))) 10 | (testing "should return nil as the second but last element" 11 | (is (nil? (get-penultimate-item (list "a"))))) 12 | (testing "should return nil if the list is empty as the second but last element" 13 | (is (nil? (get-penultimate-item (list)))))) 14 | -------------------------------------------------------------------------------- /test/data_structures/lists/reverse_a_list_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.reverse-a-list-test 2 | (:require [clojure.test :refer :all] 3 | [data-structures.lists.reverse-a-list :refer :all])) 4 | 5 | (deftest reverse-list-01-test 6 | (testing "should reverse the list" 7 | (is (= '(5 4 3 2 1) (reverse-list-01 '(1 2 3 4 5))))) 8 | (testing "should return empty list for an empty list" 9 | (is (= '() (reverse-list-01 '()))))) 10 | 11 | (deftest reverse-list-02-test 12 | (testing "should reverse the list" 13 | (is (= '(5 4 3 2 1) (reverse-list-02 '(1 2 3 4 5))))) 14 | (testing "should return empty list for an empty list" 15 | (is (= '() (reverse-list-02 '()))))) 16 | 17 | (deftest reverse-list-03-test 18 | (testing "should reverse the list" 19 | (is (= '(5 4 3 2 1) (reverse-list-03 '(1 2 3 4 5))))) 20 | (testing "should return empty list for an empty list" 21 | (is (= '() (reverse-list-03 '()))))) 22 | -------------------------------------------------------------------------------- /test/data_structures/lists/run_length_encoding_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.lists.run-length-encoding-test 2 | (:require [clojure.test :refer :all] 3 | [data-structures.lists.run-length-encoding :refer :all])) 4 | 5 | (deftest encode-1-test 6 | (testing "should return a collection of frequency and element as a tuple" 7 | (is (= '((3 "a") (1 "b") (2 "c") (3 "d")) (encode-1 '("a" "a" "a" "b" "c" "c" "d" "d" "d"))))) 8 | (testing "should return empty list with 0 if input list is 0" 9 | (is (= '() (encode-1 '()))))) 10 | 11 | (deftest encode-2-test 12 | (testing "should return a collection of frequency and element as a tuple" 13 | (is (= '((3 "a") (1 "b") (2 "c") (3 "d")) (encode-2 '("a" "a" "a" "b" "c" "c" "d" "d" "d"))))) 14 | (testing "should return empty list with 0 if input list is 0" 15 | (is (= '() (encode-2 '()))))) -------------------------------------------------------------------------------- /test/data_structures/queue/list_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.queue.list-test 2 | (:require [clojure.test :refer [deftest testing is]] 3 | [data-structures.queue.list :as q])) 4 | 5 | (deftest ->Queue-test 6 | (is (list? (q/->Queue)))) 7 | 8 | (deftest enqueue-test 9 | (is (= '(30 20 10) (-> (q/->Queue) (q/enqueue 10) (q/enqueue 20) (q/enqueue 30))))) 10 | 11 | (deftest dequeue-test 12 | (is (= [] (-> (q/->Queue) (q/dequeue)))) 13 | (is (= '(30 20) (-> (q/->Queue) (q/enqueue 10) (q/enqueue 20) (q/enqueue 30) (q/dequeue))))) 14 | 15 | (deftest peek-queue-test 16 | (is (= nil (-> (q/->Queue) (q/peek-queue))) "returns nil for empty queue") 17 | (is (= 10 (-> (q/->Queue) (q/enqueue 10) (q/enqueue 20) (q/enqueue 30) (q/peek-queue))))) 18 | 19 | (deftest empty-queue?-test 20 | (is (q/empty-queue? (q/->Queue))) 21 | (is (false? (-> (q/->Queue) (q/enqueue 10) (q/enqueue 20) q/empty-queue?)))) 22 | -------------------------------------------------------------------------------- /test/data_structures/queue/vector_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.queue.vector-test 2 | (:require 3 | [clojure.test :refer [deftest testing is]] 4 | [data-structures.queue.vector :as q])) 5 | 6 | (deftest ->Queue-test 7 | (is (vector? (q/->Queue)))) 8 | 9 | (deftest enqueue-test 10 | (is (= [10 20 30] (-> (q/->Queue) (q/enqueue 10) (q/enqueue 20) (q/enqueue 30))))) 11 | 12 | (deftest dequeue-test 13 | (is (= [] (-> (q/->Queue) (q/dequeue)))) 14 | (is (= [20 30] (-> (q/->Queue) (q/enqueue 10) (q/enqueue 20) (q/enqueue 30) (q/dequeue))))) 15 | 16 | (deftest peek-queue-test 17 | (is (nil? (-> (q/->Queue) (q/peek-queue))) "returns nil for empty queue") 18 | (is (= 10 (-> (q/->Queue) (q/enqueue 10) (q/enqueue 20) (q/enqueue 30) (q/peek-queue))))) 19 | 20 | (deftest empty-queue?-test 21 | (is (q/empty-queue? (q/->Queue))) 22 | (is (false? (-> (q/->Queue) (q/enqueue 10) (q/enqueue 20) q/empty-queue?)))) 23 | -------------------------------------------------------------------------------- /test/data_structures/stack/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns data-structures.stack.core-test 2 | (:require 3 | [clojure.test :refer [deftest testing is]] 4 | [data-structures.stack.core :as s])) 5 | 6 | (deftest ->Stack-test 7 | (testing "returns stack of desired size" 8 | (is (= [10 []] (s/->Stack 10))))) 9 | 10 | (deftest length-test 11 | (testing "returns length of the stack" 12 | (is (= 10 (-> (s/->Stack 10) 13 | (s/length)))))) 14 | 15 | (deftest empty-stack?-test 16 | (testing "returns true when stack is empty" 17 | (is (true? (s/empty-stack? (s/->Stack 10))))) 18 | (testing "returns false when stack is not empty" 19 | (is (false? (-> (s/->Stack 10) 20 | (s/push-in-stack "a-value") 21 | (s/empty-stack?)))))) 22 | 23 | (deftest full-stack?-test 24 | (testing "returns false when the stack is not full" 25 | (is (false? (s/full-stack? (s/push-in-stack (s/->Stack 3) "a-value"))))) 26 | (testing "returns true when the stack is full" 27 | (is (true? (-> (s/->Stack 3) 28 | (s/push-in-stack "a-value") 29 | (s/push-in-stack "other-value") 30 | (s/push-in-stack "another-other-value") 31 | (s/full-stack?)))))) 32 | 33 | (deftest push-in-stack-test 34 | (testing "pushes element in a not full stack" 35 | (is (= [3 ["a-value" "other-value" "another-other-value"]] 36 | (-> (s/->Stack 3) 37 | (s/push-in-stack "a-value") 38 | (s/push-in-stack "other-value") 39 | (s/push-in-stack "another-other-value"))))) 40 | 41 | (testing "throws error when trying to push element in a full stack" 42 | (is (thrown? AssertionError 43 | (-> (s/->Stack 3) 44 | (s/push-in-stack "a-value") 45 | (s/push-in-stack "other-value") 46 | (s/push-in-stack "another-other-value") 47 | (s/push-in-stack "yet-another-other-value")))))) 48 | 49 | (deftest peek-at-stack-test 50 | (testing "returns peeking at an empty stack" 51 | (is (nil? (-> (s/->Stack 3) 52 | (s/peek-at-stack))))) 53 | 54 | (testing "returns the last pushed value if stack is not empty" 55 | (is (= "another-other-value" (-> (s/->Stack 3) 56 | (s/push-in-stack "a-value") 57 | (s/push-in-stack "other-value") 58 | (s/push-in-stack "another-other-value") 59 | (s/peek-at-stack)))))) 60 | 61 | (deftest pop-from-stack-test 62 | (testing "returns original stack when popping from empty stack" 63 | (is (= [3 []] (-> (s/->Stack 3) 64 | (s/pop-from-stack))))) 65 | 66 | (testing "returns modified stack when popping from non empty stack" 67 | (is (= [3 ["a-value" "other-value"]] 68 | (-> (s/->Stack 3) 69 | (s/push-in-stack "a-value") 70 | (s/push-in-stack "other-value") 71 | (s/push-in-stack "another-other-value") 72 | (s/pop-from-stack)))))) 73 | 74 | (deftest to-string-test 75 | (testing "returns string for a stack" 76 | (is (= "[ ]" (-> (s/->Stack 3) 77 | (s/to-string)))) 78 | 79 | (is (= "[ a-value other-value another-other-value ]" 80 | (-> (s/->Stack 3) 81 | (s/push-in-stack "a-value") 82 | (s/push-in-stack "other-value") 83 | (s/push-in-stack "another-other-value") 84 | (s/to-string)))))) 85 | -------------------------------------------------------------------------------- /test/linear_algebra/matrices/general_test.clj: -------------------------------------------------------------------------------- 1 | (ns linear-algebra.matrices.general-test 2 | (:require [clojure.test :refer :all] 3 | [linear-algebra.matrices.general :refer :all])) 4 | 5 | (deftest matrix-test 6 | (testing "returns a 4x3 zero matrix" 7 | (is (= [[0 0 0] [0 0 0] [0 0 0] [0 0 0]] (matrix 4 3)))) 8 | (testing "returns a 4x4 zero matrix" 9 | (is (= [[0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0]] (matrix 4)))) 10 | (testing "returns a 3x2 matrix" 11 | (is (= [[1 2] [3 4] [5 6]] (matrix 3 2 [1 2 3 4 5 6])))) 12 | (testing "returns nil because of false dimensions" 13 | (is (nil? (matrix 4 5 [1 2 3 4 5 6 7]))))) 14 | 15 | (deftest identity-matrix-test 16 | (testing "returns 3x3 identity matrix" 17 | (is (= (matrix 3 3 [1 0 0 0 1 0 0 0 1]) (identity-matrix 3))))) 18 | 19 | (deftest get-dimensions-test 20 | (testing "returns dimensions 3x4" 21 | (is (= [3 4] (get-dimensions (matrix 3 4))))) 22 | (testing "returns dimensions 5x1" 23 | (is (= [5 1] (get-dimensions (matrix 5 1)))))) 24 | 25 | (deftest get-element-test 26 | (testing "returns the element 6" 27 | (is (= 6 (get-element 1 2 (matrix 3 3 [1 2 3 4 5 6 7 8 9]))))) 28 | (testing "returns the element 1" 29 | (is (= 1 (get-element 0 0 (matrix 3 3 [1 2 3 4 5 6 7 8 9]))))) 30 | (testing "returns nil because m or n is out of bounds" 31 | (is (nil? (get-element 2 6 (matrix 4 4)))))) 32 | 33 | -------------------------------------------------------------------------------- /test/linear_algebra/matrices/operators_test.clj: -------------------------------------------------------------------------------- 1 | (ns linear-algebra.matrices.operators-test 2 | (:require [clojure.test :refer :all] 3 | [linear-algebra.matrices.general :refer :all] 4 | [linear-algebra.matrices.operators :refer :all])) 5 | 6 | (deftest add-test 7 | (testing "return sum of A and B" 8 | (is (= (matrix 2 2 [7 7 2 2]) 9 | (add (matrix 2 2 [5 3 1 0]) 10 | (matrix 2 2 [2 4 1 2]))))) 11 | (testing "return sum of A and B" 12 | (is (= (matrix 4 1 [9 1 4 1]) 13 | (add (matrix 4 1 [1 1 1 1]) 14 | (matrix 4 1 [8 0 3 0]))))) 15 | (testing "return nil because dimensions don't match" 16 | (is (nil? (add (matrix 2 2 [1 2 3 4]) 17 | (matrix 3 2 [1 2 3 4 5 6])))))) 18 | 19 | (deftest sub-test 20 | (testing "return sum of A and B" 21 | (is (= (matrix 2 2 [3 -1 0 -2]) 22 | (sub (matrix 2 2 [5 3 1 0]) 23 | (matrix 2 2 [2 4 1 2]))))) 24 | (testing "return sum of A and B" 25 | (is (= (matrix 4 1 [-7 1 -2 1]) 26 | (sub (matrix 4 1 [1 1 1 1]) 27 | (matrix 4 1 [8 0 3 0]))))) 28 | (testing "return nil because dimensions don't match" 29 | (is (nil? (sub (matrix 2 2 [1 2 3 4]) 30 | (matrix 3 2 [1 2 3 4 5 6])))))) 31 | -------------------------------------------------------------------------------- /test/sorts/heap_sort_test.clj: -------------------------------------------------------------------------------- 1 | (ns sorts.heap-sort-test 2 | (:require 3 | [utils :refer [random-number-seq]] 4 | [clojure.test :refer [deftest testing is]] 5 | [sorts.heap-sort :refer [lazy-heap-sort]])) 6 | 7 | (deftest lazy-heap-sort-test 8 | (testing "lazy-heap-sort sorts the collection" 9 | (let [input (random-number-seq 100) 10 | expected (sort input)] 11 | (is (= expected (lazy-heap-sort input)))))) 12 | -------------------------------------------------------------------------------- /test/sorts/insertion_sort_test.clj: -------------------------------------------------------------------------------- 1 | (ns sorts.insertion-sort-test 2 | (:require [clojure.test :refer :all]) 3 | (:require 4 | [utils :refer [random-number-seq]] 5 | [clojure.test :refer [deftest testing is]] 6 | [sorts.insertion-sort :refer [insertion-sort]])) 7 | 8 | (deftest insertion-sort-test 9 | (testing "loop based insertion sort sorts the collection" 10 | (let [input (random-number-seq 100) 11 | expected (sort input)] 12 | (is (= expected (insertion-sort input)))))) 13 | -------------------------------------------------------------------------------- /test/sorts/merge_sort_test.clj: -------------------------------------------------------------------------------- 1 | (ns sorts.merge-sort-test 2 | (:require 3 | [clojure.test :refer :all] 4 | [sorts.merge-sort :as sut] 5 | [utils :refer [random-number-seq]])) 6 | 7 | (deftest merge-sort-test 8 | (testing "single item arary" 9 | (is (= (sut/merge-sort [7]) 10 | [7]))) 11 | 12 | (testing "repeated item arary" 13 | (is (= (sut/merge-sort [7 7 2 2]) 14 | [2 2 7 7]))) 15 | 16 | (testing "empty array" 17 | (is (= (sut/merge-sort []) 18 | []))) 19 | 20 | (testing "sorted array" 21 | (is (= (sut/merge-sort [1 2 3 4]) 22 | [1 2 3 4]))) 23 | 24 | (testing "unsorted array" 25 | (is (= [3 4 5 9 10 11 20] 26 | (sut/merge-sort [4 3 5 10 20 11 9])))) 27 | 28 | (testing "unsorted array worst case" 29 | (is (= (sut/merge-sort [1 2 3 4 5 6 7 8 9 10 11 12 13 14 0]) 30 | [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14])))) 31 | 32 | (deftest lazy-merge-sort-test 33 | (testing "lazy-merge-sort sorts the collection" 34 | (let [input (random-number-seq 100) 35 | expected (sort input)] 36 | (is (= expected (sut/lazy-merge-sort input)))))) 37 | -------------------------------------------------------------------------------- /test/sorts/quick_sort_test.clj: -------------------------------------------------------------------------------- 1 | (ns sorts.quick-sort-test 2 | (:require 3 | [utils :refer [random-number-seq]] 4 | [clojure.test :refer [deftest testing is]] 5 | [sorts.quick-sort :refer [lazy-quick-sort quick-sort]])) 6 | 7 | (deftest lazy-quick-sort-test 8 | (testing "lazy-quicksort sorts the collection" 9 | (let [input (random-number-seq 100) 10 | expected (sort input)] 11 | (is (= expected (lazy-quick-sort input)))))) 12 | 13 | (deftest quick-sort-test 14 | (testing "loop based quicksort sorts the collection" 15 | (let [input (random-number-seq 100) 16 | expected (sort input)] 17 | (is (= expected (quick-sort input)))))) 18 | -------------------------------------------------------------------------------- /test/utils.clj: -------------------------------------------------------------------------------- 1 | (ns utils) 2 | 3 | (defn random-number-seq 4 | [size] 5 | (shuffle (range size))) 6 | --------------------------------------------------------------------------------