aboutsummaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
Diffstat (limited to 'rust')
-rw-r--r--rust/binary-search/.exercism/metadata.json1
-rw-r--r--rust/binary-search/.gitignore8
-rw-r--r--rust/binary-search/Cargo.toml9
-rw-r--r--rust/binary-search/README.md160
-rw-r--r--rust/binary-search/src/lib.rs16
-rw-r--r--rust/binary-search/tests/binary-search.rs93
6 files changed, 287 insertions, 0 deletions
diff --git a/rust/binary-search/.exercism/metadata.json b/rust/binary-search/.exercism/metadata.json
new file mode 100644
index 0000000..2104dfb
--- /dev/null
+++ b/rust/binary-search/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"binary-search","id":"6c46db6d2d3043f5bbe689d8075eb95d","url":"https://exercism.io/my/solutions/6c46db6d2d3043f5bbe689d8075eb95d","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/binary-search/.gitignore b/rust/binary-search/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/binary-search/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/binary-search/Cargo.toml b/rust/binary-search/Cargo.toml
new file mode 100644
index 0000000..aeab7a0
--- /dev/null
+++ b/rust/binary-search/Cargo.toml
@@ -0,0 +1,9 @@
1[package]
2edition = "2018"
3name = "binary-search"
4version = "1.3.0"
5
6[dependencies]
7
8[features]
9generic = []
diff --git a/rust/binary-search/README.md b/rust/binary-search/README.md
new file mode 100644
index 0000000..d447602
--- /dev/null
+++ b/rust/binary-search/README.md
@@ -0,0 +1,160 @@
1# Binary Search
2
3Implement a binary search algorithm.
4
5Searching a sorted collection is a common task. A dictionary is a sorted
6list of word definitions. Given a word, one can find its definition. A
7telephone book is a sorted list of people's names, addresses, and
8telephone numbers. Knowing someone's name allows one to quickly find
9their telephone number and address.
10
11If the list to be searched contains more than a few items (a dozen, say)
12a binary search will require far fewer comparisons than a linear search,
13but it imposes the requirement that the list be sorted.
14
15In computer science, a binary search or half-interval search algorithm
16finds the position of a specified input value (the search "key") within
17an array sorted by key value.
18
19In each step, the algorithm compares the search key value with the key
20value of the middle element of the array.
21
22If the keys match, then a matching element has been found and its index,
23or position, is returned.
24
25Otherwise, if the search key is less than the middle element's key, then
26the algorithm repeats its action on the sub-array to the left of the
27middle element or, if the search key is greater, on the sub-array to the
28right.
29
30If the remaining array to be searched is empty, then the key cannot be
31found in the array and a special "not found" indication is returned.
32
33A binary search halves the number of items to check with each iteration,
34so locating an item (or determining its absence) takes logarithmic time.
35A binary search is a dichotomic divide and conquer search algorithm.
36
37## Restrictions
38
39Rust provides in its standard library already a
40[binary search function](https://doc.rust-lang.org/std/primitive.slice.html#method.binary_search).
41For this exercise you should not use this function but just other basic tools instead.
42
43## Hints
44
45[Slices](https://doc.rust-lang.org/book/2018-edition/ch04-03-slices.html) have additionally to
46the normal element access via indexing (slice[index]) many useful functions like
47[split_at](https://doc.rust-lang.org/std/primitive.slice.html#method.split_at) or [getting
48subslices](https://doc.rust-lang.org/std/primitive.slice.html#method.get) (slice[start..end]).
49
50You can solve this exercise by just using boring old element access via indexing, but maybe the
51other provided functions can make your code cleaner and safer.
52
53## For bonus points
54
55Did you get the tests passing and the code clean? If you want to, there
56are some additional things you could try.
57
58- Currently your find function will probably only work for slices of numbers,
59 but the Rust type system is flexible enough to create a find function which
60 works on all slices which contains elements which can be ordered.
61- Additionally this find function can work not only on slices, but at the
62 same time also on a Vec or an Array.
63
64To run the bonus tests, remove the `#[ignore]` flag and execute the tests with
65the `generic` feature, like this:
66
67```bash
68$ cargo test --features generic
69```
70
71Then please share your thoughts in a comment on the submission. Did this
72experiment make the code better? Worse? Did you learn anything from it?
73
74### Hints for Bonus Points
75
76- To get your function working with all kind of elements which can be ordered,
77 have a look at the [Ord Trait](https://doc.rust-lang.org/std/cmp/trait.Ord.html).
78- To get your function working directly on Vec and Array, you can use the
79 [AsRef Trait](https://doc.rust-lang.org/std/convert/trait.AsRef.html)
80
81
82## Rust Installation
83
84Refer to the [exercism help page][help-page] for Rust installation and learning
85resources.
86
87## Writing the Code
88
89Execute the tests with:
90
91```bash
92$ cargo test
93```
94
95All but the first test have been ignored. After you get the first test to
96pass, open the tests source file which is located in the `tests` directory
97and remove the `#[ignore]` flag from the next test and get the tests to pass
98again. Each separate test is a function with `#[test]` flag above it.
99Continue, until you pass every test.
100
101If you wish to run all ignored tests without editing the tests source file, use:
102
103```bash
104$ cargo test -- --ignored
105```
106
107To run a specific test, for example `some_test`, you can use:
108
109```bash
110$ cargo test some_test
111```
112
113If the specific test is ignored use:
114
115```bash
116$ cargo test some_test -- --ignored
117```
118
119To learn more about Rust tests refer to the [online test documentation][rust-tests]
120
121Make sure to read the [Modules][modules] chapter if you
122haven't already, it will help you with organizing your files.
123
124## Further improvements
125
126After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
127
128To format your solution, inside the solution directory use
129
130```bash
131cargo fmt
132```
133
134To see, if your solution contains some common ineffective use cases, inside the solution directory use
135
136```bash
137cargo clippy --all-targets
138```
139
140## Submitting the solution
141
142Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
143
144## Feedback, Issues, Pull Requests
145
146The [exercism/rust](https://github.com/exercism/rust) repository on GitHub is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
147
148If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
149
150[help-page]: https://exercism.io/tracks/rust/learning
151[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
152[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
153[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
154
155## Source
156
157Wikipedia [http://en.wikipedia.org/wiki/Binary_search_algorithm](http://en.wikipedia.org/wiki/Binary_search_algorithm)
158
159## Submitting Incomplete Solutions
160It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/binary-search/src/lib.rs b/rust/binary-search/src/lib.rs
new file mode 100644
index 0000000..dc80137
--- /dev/null
+++ b/rust/binary-search/src/lib.rs
@@ -0,0 +1,16 @@
1pub fn find<T: Ord, C: AsRef<[T]>>(array: C, key: T) -> Option<usize> {
2 let array = array.as_ref();
3 match array.len() {
4 0 => None,
5 1 => Some(0).filter(|_| array[0] == key),
6 n => {
7 let mid = n / 2;
8 let (a1, a2) = array.split_at(mid);
9 if key < array[mid] {
10 find(a1, key)
11 } else {
12 find(a2, key).map(|i| i + mid)
13 }
14 }
15 }
16}
diff --git a/rust/binary-search/tests/binary-search.rs b/rust/binary-search/tests/binary-search.rs
new file mode 100644
index 0000000..aa5cc8b
--- /dev/null
+++ b/rust/binary-search/tests/binary-search.rs
@@ -0,0 +1,93 @@
1use binary_search::find;
2
3#[test]
4fn finds_a_value_in_an_array_with_one_element() {
5 assert_eq!(find(&[6], 6), Some(0));
6}
7
8#[test]
9fn finds_first_value_in_an_array_with_two_element() {
10 assert_eq!(find(&[1, 2], 1), Some(0));
11}
12
13#[test]
14fn finds_second_value_in_an_array_with_two_element() {
15 assert_eq!(find(&[1, 2], 2), Some(1));
16}
17
18#[test]
19fn finds_a_value_in_the_middle_of_an_array() {
20 assert_eq!(find(&[1, 3, 4, 6, 8, 9, 11], 6), Some(3));
21}
22
23#[test]
24fn finds_a_value_at_the_beginning_of_an_array() {
25 assert_eq!(find(&[1, 3, 4, 6, 8, 9, 11], 1), Some(0));
26}
27
28#[test]
29fn finds_a_value_at_the_end_of_an_array() {
30 assert_eq!(find(&[1, 3, 4, 6, 8, 9, 11], 11), Some(6));
31}
32
33#[test]
34fn finds_a_value_in_an_array_of_odd_length() {
35 assert_eq!(
36 find(&[1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634], 144),
37 Some(9)
38 );
39}
40
41#[test]
42fn finds_a_value_in_an_array_of_even_length() {
43 assert_eq!(
44 find(&[1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377], 21),
45 Some(5)
46 );
47}
48
49#[test]
50fn identifies_that_a_value_is_not_included_in_the_array() {
51 assert_eq!(find(&[1, 3, 4, 6, 8, 9, 11], 7), None);
52}
53
54#[test]
55fn a_value_smaller_than_the_arrays_smallest_value_is_not_included() {
56 assert_eq!(find(&[1, 3, 4, 6, 8, 9, 11], 0), None);
57}
58
59#[test]
60fn a_value_larger_than_the_arrays_largest_value_is_not_included() {
61 assert_eq!(find(&[1, 3, 4, 6, 8, 9, 11], 13), None);
62}
63
64#[test]
65fn nothing_is_included_in_an_empty_array() {
66 assert_eq!(find(&[], 1), None);
67}
68
69#[test]
70fn nothing_is_found_when_the_left_and_right_bounds_cross() {
71 assert_eq!(find(&[1, 2], 0), None);
72}
73
74#[test]
75#[cfg(feature = "generic")]
76fn works_for_arrays() {
77 assert_eq!(find([6], 6), Some(0));
78}
79
80#[test]
81#[cfg(feature = "generic")]
82fn works_for_vec() {
83 let vector = vec![6];
84 assert_eq!(find(&vector, 6), Some(0));
85 assert_eq!(find(vector, 6), Some(0));
86}
87
88#[test]
89#[cfg(feature = "generic")]
90fn works_for_str_elements() {
91 assert_eq!(find(["a"], "a"), Some(0));
92 assert_eq!(find(["a", "b"], "b"), Some(1));
93}