Skip to content

Commit 6e26a3c

Browse files
rename binary-search to binary-chop (#288)
Avoid collision with Factor's binary-search vocab. https://forum.exercism.org/t/factor-track-feedback/60226/17
1 parent ad75b3b commit 6e26a3c

11 files changed

Lines changed: 250 additions & 5 deletions

File tree

config.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -979,9 +979,9 @@
979979
"difficulty": 3
980980
},
981981
{
982-
"slug": "binary-search",
982+
"slug": "binary-chop",
983983
"name": "Binary Search",
984-
"uuid": "ea3a619c-0d03-4688-821a-22379470d7e1",
984+
"uuid": "49cc7b5c-d2fc-4332-89a5-9890c340f25f",
985985
"practices": [
986986
"recursion"
987987
],
@@ -993,6 +993,15 @@
993993
],
994994
"difficulty": 3
995995
},
996+
{
997+
"slug": "binary-search",
998+
"name": "Binary Search (deprecated)",
999+
"uuid": "ea3a619c-0d03-4688-821a-22379470d7e1",
1000+
"practices": [],
1001+
"prerequisites": [],
1002+
"difficulty": 3,
1003+
"status": "deprecated"
1004+
},
9961005
{
9971006
"slug": "bob",
9981007
"name": "Bob",
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Instructions
2+
3+
Your task is to implement a binary search algorithm.
4+
5+
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.
6+
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.
7+
8+
~~~~exercism/caution
9+
Binary search only works when a list has been sorted.
10+
~~~~
11+
12+
The algorithm looks like this:
13+
14+
- Find the middle element of a _sorted_ list and compare it with the item we're looking for.
15+
- If the middle element is our item, then we're done!
16+
- If the middle element is greater than our item, we can eliminate that element and all the elements **after** it.
17+
- If the middle element is less than our item, we can eliminate that element and all the elements **before** it.
18+
- If every element of the list has been eliminated then the item is not in the list.
19+
- Otherwise, repeat the process on the part of the list that has not been eliminated.
20+
21+
Here's an example:
22+
23+
Let's say we're looking for the number 23 in the following sorted list: `[4, 8, 12, 16, 23, 28, 32]`.
24+
25+
- We start by comparing 23 with the middle element, 16.
26+
- Since 23 is greater than 16, we can eliminate the left half of the list, leaving us with `[23, 28, 32]`.
27+
- We then compare 23 with the new middle element, 28.
28+
- Since 23 is less than 28, we can eliminate the right half of the list: `[23]`.
29+
- We've found our item.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Introduction
2+
3+
You have stumbled upon a group of mathematicians who are also singer-songwriters.
4+
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]).
5+
6+
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.
7+
Fortunately, they have organized their songs in a playlist sorted by the title — which is simply the number that the song is about.
8+
9+
You realize that you can use a binary search algorithm to quickly find a song given the title.
10+
11+
[zero]: https://en.wikipedia.org/wiki/0
12+
[seventy-three]: https://en.wikipedia.org/wiki/73_(number)
13+
[kaprekars-constant]: https://en.wikipedia.org/wiki/6174_(number)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"binary-chop/binary-chop.factor"
8+
],
9+
"test": [
10+
"binary-chop/binary-chop-tests.factor"
11+
],
12+
"example": [
13+
".meta/example.factor"
14+
]
15+
},
16+
"blurb": "Implement a binary search algorithm.",
17+
"source": "Wikipedia",
18+
"source_url": "https://en.wikipedia.org/wiki/Binary_search_algorithm"
19+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
USING: combinators kernel locals math sequences ;
2+
IN: binary-chop
3+
4+
ERROR: value-not-in-array ;
5+
6+
:: search-range ( array value low high -- index )
7+
low high > [ value-not-in-array ] [
8+
low high + 2 /i :> mid
9+
mid array nth :> probe
10+
{
11+
{ [ probe value = ] [ mid ] }
12+
{ [ probe value < ] [ array value mid 1 + high search-range ] }
13+
[ array value low mid 1 - search-range ]
14+
} cond
15+
] if ;
16+
17+
: find ( array value -- index )
18+
over length 1 - [ 0 ] dip search-range ;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module BinarySearch
2+
3+
function gen_test_case(case)
4+
array = format_int_array(case["input"]["array"])
5+
value = to_int_str(case["input"]["value"])
6+
expected = case["expected"]
7+
if expected isa AbstractDict && haskey(expected, "error")
8+
return """[ $(array) $(value) find ] [ value-not-in-array? ] must-fail-with"""
9+
end
10+
return "{ $(to_int_str(expected)) }\n[ $(array) $(value) find ] unit-test"
11+
end
12+
13+
end
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[b55c24a9-a98d-4379-a08c-2adcf8ebeee8]
13+
description = "finds a value in an array with one element"
14+
15+
[73469346-b0a0-4011-89bf-989e443d503d]
16+
description = "finds a value in the middle of an array"
17+
18+
[327bc482-ab85-424e-a724-fb4658e66ddb]
19+
description = "finds a value at the beginning of an array"
20+
21+
[f9f94b16-fe5e-472c-85ea-c513804c7d59]
22+
description = "finds a value at the end of an array"
23+
24+
[f0068905-26e3-4342-856d-ad153cadb338]
25+
description = "finds a value in an array of odd length"
26+
27+
[fc316b12-c8b3-4f5e-9e89-532b3389de8c]
28+
description = "finds a value in an array of even length"
29+
30+
[da7db20a-354f-49f7-a6a1-650a54998aa6]
31+
description = "identifies that a value is not included in the array"
32+
33+
[95d869ff-3daf-4c79-b622-6e805c675f97]
34+
description = "a value smaller than the array's smallest value is not found"
35+
36+
[8b24ef45-6e51-4a94-9eac-c2bf38fdb0ba]
37+
description = "a value larger than the array's largest value is not found"
38+
39+
[f439a0fa-cf42-4262-8ad1-64bf41ce566a]
40+
description = "nothing is found in an empty array"
41+
42+
[2c353967-b56d-40b8-acff-ce43115eed64]
43+
description = "nothing is found when the left and right bounds cross"
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
USING: binary-chop exercism-tools io kernel tools.test unicode ;
2+
IN: binary-chop.tests
3+
4+
"finds a value in an array with one element" description
5+
{ 0 }
6+
[ { 6 } 6 find ] unit-test
7+
8+
STOP-HERE
9+
10+
"finds a value in the middle of an array" description
11+
{ 3 }
12+
[ { 1 3 4 6 8 9 11 } 6 find ] unit-test
13+
14+
"finds a value at the beginning of an array" description
15+
{ 0 }
16+
[ { 1 3 4 6 8 9 11 } 1 find ] unit-test
17+
18+
"finds a value at the end of an array" description
19+
{ 6 }
20+
[ { 1 3 4 6 8 9 11 } 11 find ] unit-test
21+
22+
"finds a value in an array of odd length" description
23+
{ 9 }
24+
[ { 1 3 5 8 13 21 34 55 89 144 233 377 634 } 144 find ] unit-test
25+
26+
"finds a value in an array of even length" description
27+
{ 5 }
28+
[ { 1 3 5 8 13 21 34 55 89 144 233 377 } 21 find ] unit-test
29+
30+
"identifies that a value is not included in the array" description
31+
[ { 1 3 4 6 8 9 11 } 7 find ] [ value-not-in-array? ] must-fail-with
32+
33+
"a value smaller than the array's smallest value is not found" description
34+
[ { 1 3 4 6 8 9 11 } 0 find ] [ value-not-in-array? ] must-fail-with
35+
36+
"a value larger than the array's largest value is not found" description
37+
[ { 1 3 4 6 8 9 11 } 13 find ] [ value-not-in-array? ] must-fail-with
38+
39+
"nothing is found in an empty array" description
40+
[ { } 1 find ] [ value-not-in-array? ] must-fail-with
41+
42+
"nothing is found when the left and right bounds cross" description
43+
[ { 1 2 } 0 find ] [ value-not-in-array? ] must-fail-with
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
USING: kernel ;
2+
IN: binary-chop
3+
4+
ERROR: value-not-in-array ;
5+
6+
: find ( array value -- index )
7+
"unimplemented" throw ;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
USING: accessors command-line continuations debugger io kernel
2+
lexer namespaces prettyprint.config sequences
3+
source-files.errors.debugger system tools.test vocabs
4+
vocabs.loader ;
5+
IN: exercism-tools
6+
7+
SYNTAX: STOP-HERE
8+
lexer get [ text>> length ] keep line<< ;
9+
10+
SYNTAX: TASK:
11+
lexer get next-line ;
12+
13+
! Label the test that follows with its description.
14+
: description ( str -- )
15+
"###DESC### " write print ;
16+
17+
! Print one failure block in a stable, parser-friendly form.
18+
:: print-failure ( failure -- )
19+
"###FAIL_BEGIN###" print
20+
failure error-location print
21+
[ failure error>> [ error. ] [ 2drop ] recover ] without-limits
22+
"###FAIL_END###" print
23+
flush ;
24+
25+
: print-failures ( -- )
26+
test-failures get [ print-failure ] each ;
27+
28+
: run-exercism-tests ( -- )
29+
vocab-roots [ "." prefix ] change-global
30+
command-line get first
31+
[ require ] [ test ] bi
32+
test-failures get empty?
33+
[ 0 exit ] [ print-failures 1 exit ] if ;
34+
35+
MAIN: run-exercism-tests

0 commit comments

Comments
 (0)