diff --git a/config.json b/config.json index b5b0c64..59c7663 100644 --- a/config.json +++ b/config.json @@ -44,6 +44,14 @@ "prerequisites": [], "difficulty": 2 }, + { + "slug": "binary-search", + "name": "Binary Search", + "uuid": "22fe2851-8b68-4b00-94cd-2a78b211e004", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "two-fer", "name": "Two Fer", diff --git a/exercises/practice/binary-search/.docs/instructions.md b/exercises/practice/binary-search/.docs/instructions.md new file mode 100644 index 0000000..12f4358 --- /dev/null +++ b/exercises/practice/binary-search/.docs/instructions.md @@ -0,0 +1,29 @@ +# Instructions + +Your task is to implement a binary search algorithm. + +A binary search algorithm finds an item in a list by repeatedly splitting it in half, only keeping the half which contains the item we're looking for. +It allows us to quickly narrow down the possible locations of our item until we find it, or until we've eliminated all possible locations. + +~~~~exercism/caution +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. +- 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. +- If every element of the list has been eliminated then the item is not in the list. +- Otherwise, repeat the process on the part of the list that has not been eliminated. + +Here's an example: + +Let's say we're looking for the number 23 in the following sorted list: `[4, 8, 12, 16, 23, 28, 32]`. + +- We start by comparing 23 with the middle element, 16. +- Since 23 is greater than 16, we can eliminate the left half of the list, leaving us with `[23, 28, 32]`. +- We then compare 23 with the new middle element, 28. +- Since 23 is less than 28, we can eliminate the right half of the list: `[23]`. +- We've found our item. diff --git a/exercises/practice/binary-search/.docs/introduction.md b/exercises/practice/binary-search/.docs/introduction.md new file mode 100644 index 0000000..0349659 --- /dev/null +++ b/exercises/practice/binary-search/.docs/introduction.md @@ -0,0 +1,13 @@ +# Introduction + +You have stumbled upon a group of mathematicians who are also singer-songwriters. +They have written a song for each of their favorite numbers, and, as you can imagine, they have a lot of favorite numbers (like [0][zero] or [73][seventy-three] or [6174][kaprekars-constant]). + +You are curious to hear the song for your favorite number, but with so many songs to wade through, finding the right song could take a while. +Fortunately, they have organized their songs in a playlist sorted by the title — which is simply the number that the song is about. + +You realize that you can use a binary search algorithm to quickly find a song given the title. + +[zero]: https://en.wikipedia.org/wiki/0 +[seventy-three]: https://en.wikipedia.org/wiki/73_(number) +[kaprekars-constant]: https://en.wikipedia.org/wiki/6174_(number) diff --git a/exercises/practice/binary-search/.meta/config.json b/exercises/practice/binary-search/.meta/config.json new file mode 100644 index 0000000..9a0b488 --- /dev/null +++ b/exercises/practice/binary-search/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "src/binary-search.art" + ], + "test": [ + "tests/test-binary-search.art" + ], + "example": [ + ".meta/src/example.art" + ] + }, + "blurb": "Implement a binary search algorithm.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Binary_search_algorithm" +} diff --git a/exercises/practice/binary-search/.meta/src/example.art b/exercises/practice/binary-search/.meta/src/example.art new file mode 100644 index 0000000..60cf3c5 --- /dev/null +++ b/exercises/practice/binary-search/.meta/src/example.art @@ -0,0 +1,16 @@ +find: function [values value][ + start: 0 + stop: sub size values 1 + + while [=< start stop] [ + i: div start + stop 2 + elt: values\[i] + case [value] + when? [> elt] -> start: i + 1 + when? [< elt] -> stop: i - 1 + else -> return i + ] + + null +] + diff --git a/exercises/practice/binary-search/.meta/tests.toml b/exercises/practice/binary-search/.meta/tests.toml new file mode 100644 index 0000000..61e2b06 --- /dev/null +++ b/exercises/practice/binary-search/.meta/tests.toml @@ -0,0 +1,43 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[b55c24a9-a98d-4379-a08c-2adcf8ebeee8] +description = "finds a value in an array with one element" + +[73469346-b0a0-4011-89bf-989e443d503d] +description = "finds a value in the middle of an array" + +[327bc482-ab85-424e-a724-fb4658e66ddb] +description = "finds a value at the beginning of an array" + +[f9f94b16-fe5e-472c-85ea-c513804c7d59] +description = "finds a value at the end of an array" + +[f0068905-26e3-4342-856d-ad153cadb338] +description = "finds a value in an array of odd length" + +[fc316b12-c8b3-4f5e-9e89-532b3389de8c] +description = "finds a value in an array of even length" + +[da7db20a-354f-49f7-a6a1-650a54998aa6] +description = "identifies that a value is not included in the array" + +[95d869ff-3daf-4c79-b622-6e805c675f97] +description = "a value smaller than the array's smallest value is not found" + +[8b24ef45-6e51-4a94-9eac-c2bf38fdb0ba] +description = "a value larger than the array's largest value is not found" + +[f439a0fa-cf42-4262-8ad1-64bf41ce566a] +description = "nothing is found in an empty array" + +[2c353967-b56d-40b8-acff-ce43115eed64] +description = "nothing is found when the left and right bounds cross" diff --git a/exercises/practice/binary-search/src/binary-search.art b/exercises/practice/binary-search/src/binary-search.art new file mode 100644 index 0000000..431a66c --- /dev/null +++ b/exercises/practice/binary-search/src/binary-search.art @@ -0,0 +1,4 @@ +find: function [values value][ + panic "Implement the find function" +] + diff --git a/exercises/practice/binary-search/tester.art b/exercises/practice/binary-search/tester.art new file mode 100644 index 0000000..c2ea3ce --- /dev/null +++ b/exercises/practice/binary-search/tester.art @@ -0,0 +1,3 @@ +import {unitt}! + +runTests.failFast findTests "tests" diff --git a/exercises/practice/binary-search/tests/test-binary-search.art b/exercises/practice/binary-search/tests/test-binary-search.art new file mode 100644 index 0000000..88cd89d --- /dev/null +++ b/exercises/practice/binary-search/tests/test-binary-search.art @@ -0,0 +1,71 @@ +import {unitt}! +import {src/binary-search}! + +suite "Binary Search" [ + test "finds a value in a block with one element" [ + vals: [6] + result: find vals 6 + assert -> 0 = result + ] + + test.skip "finds a value in the middle of a block" [ + vals: [1 3 4 6 8 9 11] + result: find vals 6 + assert -> 3 = result + ] + + test.skip "finds a value at the beginning of a block" [ + vals: [1 3 4 6 8 9 11] + result: find vals 1 + assert -> 0 = result + ] + + test.skip "finds a value at the end of a block" [ + vals: [1 3 4 6 8 9 11] + result: find vals 11 + assert -> 6 = result + ] + + test.skip "finds a value in a block of odd length" [ + vals: [1 3 5 8 13 21 34 55 89 144 233 377 634] + result: find vals 144 + assert -> 9 = result + ] + + test.skip "finds a value in a block of even length" [ + vals: [1 3 5 8 13 21 34 55 89 144 233 377] + result: find vals 21 + assert -> 5 = result + ] + + test.skip "identifies that a value is not included in the block" [ + vals: [1 3 4 6 8 9 11] + result: find vals 7 + assert -> null = result + ] + + test.skip "a value smaller than the block's smallest value is not found" [ + vals: [1 3 4 6 8 9 11] + result: find vals 0 + assert -> null = result + ] + + test.skip "a value larger than the block's largest value is not found" [ + vals: [1 3 4 6 8 9 11] + result: find vals 13 + assert -> null = result + ] + + test.skip "nothing is found in an empty block" [ + vals: [] + result: find vals 1 + assert -> null = result + ] + + test.skip "nothing is found when the left and right bounds cross" [ + vals: [1 2] + result: find vals 0 + assert -> null = result + ] +] +