diff --git a/exercises/practice/binary-search/.docs/instructions.md b/exercises/practice/binary-search/.docs/instructions.md index aa1946cfb..12f4358eb 100644 --- a/exercises/practice/binary-search/.docs/instructions.md +++ b/exercises/practice/binary-search/.docs/instructions.md @@ -11,7 +11,7 @@ Binary search only works when a list has been sorted. The algorithm looks like this: -- Find the middle element of a *sorted* list and compare it with the item we're looking for. +- Find the middle element of a _sorted_ list and compare it with the item we're looking for. - If the middle element is our item, then we're done! - If the middle element is greater than our item, we can eliminate that element and all the elements **after** it. - If the middle element is less than our item, we can eliminate that element and all the elements **before** it. diff --git a/exercises/practice/binary-search/.meta/config.json b/exercises/practice/binary-search/.meta/config.json index 74b15a053..e2fe40d6e 100644 --- a/exercises/practice/binary-search/.meta/config.json +++ b/exercises/practice/binary-search/.meta/config.json @@ -24,5 +24,5 @@ }, "blurb": "Implement a binary search algorithm.", "source": "Wikipedia", - "source_url": "http://en.wikipedia.org/wiki/Binary_search_algorithm" + "source_url": "https://en.wikipedia.org/wiki/Binary_search_algorithm" } diff --git a/exercises/practice/binary-search/.meta/src/example.clj b/exercises/practice/binary-search/.meta/src/example.clj index 9ea77cf38..416b0da95 100644 --- a/exercises/practice/binary-search/.meta/src/example.clj +++ b/exercises/practice/binary-search/.meta/src/example.clj @@ -1,14 +1,15 @@ (ns binary-search) -(defn middle [alist] - (-> alist (count) (quot 2))) - (defn search-for - [elem alist] - (let [middle (middle alist) - cur-elem (nth alist middle)] - (cond - (= cur-elem elem) middle - (or (= middle (count alist)) (zero? middle)) (throw (Exception. (format "%s not found in list" elem))) - (< cur-elem elem) (+ middle (search-for elem (drop middle alist))) - (> cur-elem elem) (search-for elem (take middle alist))))) + [n coll] + (let [coll (vec coll)] + (loop [low-idx 0 + high-idx (dec (count coll))] + (if (> low-idx high-idx) + (throw (Exception. "not found")) + (let [mid-index (quot (+ high-idx low-idx) 2) + mid-item (get coll mid-index)] + (cond + (= n mid-item) mid-index + (> mid-item n) (recur low-idx (dec mid-index)) + :else (recur (inc mid-index) high-idx))))))) diff --git a/exercises/practice/binary-search/test/binary_search_test.clj b/exercises/practice/binary-search/test/binary_search_test.clj index 00efed566..60f84640d 100644 --- a/exercises/practice/binary-search/test/binary_search_test.clj +++ b/exercises/practice/binary-search/test/binary_search_test.clj @@ -1,40 +1,52 @@ (ns binary-search-test - (:require [clojure.test :refer [deftest is]] + (:require [clojure.test :refer [deftest is testing]] binary-search)) -(def short-vector [1, 3, 4, 6, 8, 9, 11]) - -(def large-vector [1, 3, 5, 8, 13, 21, 34, 55, 89]) - -(def even-length-vector [1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]) - -(deftest it-finds-position-of-middle-item - (is (= 3 (binary-search/middle short-vector)))) - -(deftest searches-a-singleton - (is (= 0 (binary-search/search-for 4 [4])))) - -(deftest it-finds-position-of-search-data - (is (= 5 (binary-search/search-for 9 short-vector)))) - -(deftest it-finds-position-in-a-larger-list - (is (= 1 (binary-search/search-for 3 large-vector)))) - -(deftest it-finds-position-in-a-larger-list-again - (is (= 7 (binary-search/search-for 55 large-vector)))) - -(deftest it-finds-correct-position-in-a-list-with-an-even-number-of-elements - (is (= 5 (binary-search/search-for 21 even-length-vector)))) - -(deftest it-finds-correct-position-in-a-list-with-an-even-number-of-elements-again - (is (= 6 (binary-search/search-for 34 even-length-vector)))) - -(deftest it-works-on-lists - (is (= 7 (binary-search/search-for 7 (range 10))))) - -(deftest it-works-on-lists-again - (is (= 4 (binary-search/search-for 3 '(-3 -2 0 1 3 4))))) - -(deftest throws-exception-when-element-not-found - (is (thrown-with-msg? Throwable #"not found" - (binary-search/search-for 20 short-vector)))) +(deftest finds-value-in-array-with-one-element + (testing "Finds a value in an array with one element" + (is (= 0 (binary-search/search-for 6 [6]))))) + +(deftest finds-value-in-middle-of-array + (testing "Finds a value in the middle of an array" + (is (= 3 (binary-search/search-for 6 [1, 3, 4, 6, 8, 9, 11]))))) + +(deftest finds-value-at-beginning-of-array + (testing "Finds a value at the beginning of an array" + (is (= 0 (binary-search/search-for 1 [1, 3, 4, 6, 8, 9, 11]))))) + +(deftest finds-value-at-end-of-array + (testing "Finds a value at the end of an array" + (is (= 6 (binary-search/search-for 11 [1, 3, 4, 6, 8, 9, 11]))))) + +(deftest finds-value-in-array-of-odd-length + (testing "Finds a value in an array of odd length" + (is (= 9 (binary-search/search-for 144 [1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634]))))) + +(deftest finds-value-in-array-of-even-length + (testing "Finds a value in an array of even length" + (is (= 5 (binary-search/search-for 21 [1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]))))) + +(deftest identifies-that-value-is-not-in-array + (testing "Identifies that a value is not included in the array" + (is (thrown-with-msg? Throwable #"not found" + (binary-search/search-for 7 [1, 3, 4, 6, 8, 9, 11]))))) + +(deftest value-smaller-than-arrays-smallest-value-not-found + (testing "A value smaller than the array's smallest value is not found" + (is (thrown-with-msg? Throwable #"not found" + (binary-search/search-for 0 [1, 3, 4, 6, 8, 9, 11]))))) + +(deftest value-larger-than-arrays-largest-value-not-found + (testing "A value larger than the array's largest value is not found" + (is (thrown-with-msg? Throwable #"not found" + (binary-search/search-for 13 [1, 3, 4, 6, 8, 9, 11]))))) + +(deftest nothing-found-in-empty-array + (testing "Nothing is found in an empty array" + (is (thrown-with-msg? Throwable #"not found" + (binary-search/search-for 1 []))))) + +(deftest nothing-found-when-left-and-right-bounds-cross + (testing "Nothing is found when the left and right bounds cross" + (is (thrown-with-msg? Throwable #"not found" + (binary-search/search-for 0 [1, 2])))))