diff --git a/exercises/practice/binary-search/.approaches/introduction.md b/exercises/practice/binary-search/.approaches/introduction.md index 85aa49ae9..212f6c84b 100644 --- a/exercises/practice/binary-search/.approaches/introduction.md +++ b/exercises/practice/binary-search/.approaches/introduction.md @@ -42,23 +42,19 @@ For more information, check the [Looping approach][approach-looping]. ```rust use std::cmp::Ordering; -fn find_rec, T: Ord>(array: U, key: T, offset: usize) -> Option { +fn find, T: Ord>(array: U, key: T) -> Option { let array = array.as_ref(); - if array.len() == 0 { + if array.is_empty() { return None; } let mid = array.len() / 2; match array[mid].cmp(&key) { Ordering::Equal => Some(offset + mid), - Ordering::Less => find_rec(&array[mid + 1..], key, offset + mid + 1), - Ordering::Greater => find_rec(&array[..mid], key, offset), + Ordering::Greater => find(&array[..mid], key), + Ordering::Less => find(&array[mid + 1..], key).map(|p| p + mid + 1), } } - -pub fn find, T: Ord>(array: U, key: T) -> Option { - find_rec(array, key, 0) -} ``` For more information, check the [Recursion approach][approach-recursion]. diff --git a/exercises/practice/binary-search/.approaches/recursion/content.md b/exercises/practice/binary-search/.approaches/recursion/content.md index dcae57b84..44f0ad692 100644 --- a/exercises/practice/binary-search/.approaches/recursion/content.md +++ b/exercises/practice/binary-search/.approaches/recursion/content.md @@ -3,28 +3,24 @@ ```rust use std::cmp::Ordering; -fn find_rec, T: Ord>(array: U, key: T, offset: usize) -> Option { +fn find, T: Ord>(array: U, key: T) -> Option { let array = array.as_ref(); - if array.len() == 0 { + if array.is_empty() { return None; } let mid = array.len() / 2; match array[mid].cmp(&key) { - Ordering::Equal => Some(offset + mid), - Ordering::Less => find_rec(&array[mid + 1..], key, offset + mid + 1), - Ordering::Greater => find_rec(&array[..mid], key, offset), + Ordering::Equal => Some(mid), + Ordering::Greater => find(&array[..mid], key), + Ordering::Less => find(&array[mid + 1..], key).map(|p| p + mid + 1), } } - -pub fn find, T: Ord>(array: U, key: T) -> Option { - find_rec(array, key, 0) -} ``` This approach starts by using the [`Ordering`][ordering-enum] enum. -The `find_rec()` function has a signature to support the optional generic tests. +The `find()` function has a signature to support the optional generic tests. To support slices, arrays and Vecs, which can be of varying lengths and sizes at runtime, the compiler needs to be given informaton it can know at compile time. A reference to any of those containers will always be of the same size (essentially the size of a pointer), @@ -33,16 +29,11 @@ so [`AsRef`][asref] is used to constrain the generic type to be anything that is The `<[T]>` is used to constrain the reference type to an indexable type `T`. The `T` is constrained to be anything which implements the [`Ord`][ord] trait, which essentially means the values must be able to be ordered. -So, the `key` is of type `T` (orderable), and the `array` is of type `U` (a reference to an indexable container of orderable values -of the same type as the `key`.) - -Since slices of the `array` will keep getting shorter with each recursive call to itself, `find_rec()` has an `offset` parameter -to keep track of the actual midpoint as it relates to the original `array`. +So, the `key` is of type `T` (orderable), and the `array` is of type `U` (a reference to an indexable container of orderable values of the same type as the `key`.) Although `array` is defined as generic type `U`, which is constrained to be of type `AsRef`, the [`as_ref()`][asref] method is used to get the reference to the actual type. -Without it, the compiler would complain that "no method named `len` found for type parameter `U` in the current scope" and -"cannot index into a value of type `U`". +Without it, the compiler would complain that "no method named `len` found for type parameter `U` in the current scope" and "cannot index into a value of type `U`". If the `array` is empty, then [`None`][none] is returned. @@ -52,19 +43,14 @@ Since the element is a reference, the `key` must also be referenced. The [`match`][match] arms each use a value from the `Ordering` enum. -- If the midpoint element value equals the `key`, then the midpoint plus the offset is returned from the function wrapped in a [`Some`][some]. -- If the midpoint element value is less than the `key`, then `find_rec()` calls itself, - passing a slice of the `array` from the element to the right of the midpoint through the end of the `array`. - The offset is adjusted to be itself plus the midpoint plus `1`. -- If the midpoint element value is greater than the `key`, then `find_rec()` calls itself, +- If the midpoint element value equals the `key`, then the midpoint is returned from the function wrapped in a [`Some`][some]. +- If the midpoint element value is greater than the `key`, then `find()` calls itself, passing a slice of the `array` from the beginning up to but not including the midpoint element. - The offset remains as is. - -While the element value is not equal to the `key`, `find_rec()` keeps calling itself while halving the number of elements being searched, -until either the `key` is found, or, if it is not in the `array`, the `array` is whittled down to empty. +- If the midpoint element value is less than the `key`, then `find()` calls itself, + passing a slice of the `array` from the element to the right of the midpoint through the end of the `array`. + The return postion from the recursive call is the midpoint start from the new left(`mid + 1`), so we add `mid + 1` to the return postion. -The `find()` method returns the final result from calling the `find_rec()` method, passing in the `array`, `key`, and `0` for the initial -offset value. +While the element value is not equal to the `key`, `find()` keeps calling itself while halving the number of elements being searched, until either the `key` is found, or, if it is not in the `array`, the `array` is whittled down to empty. [ordering-enum]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html [asref]: https://doc.rust-lang.org/std/convert/trait.AsRef.html diff --git a/exercises/practice/binary-search/.approaches/recursion/snippet.txt b/exercises/practice/binary-search/.approaches/recursion/snippet.txt index 0c8dd0da7..9d8ef3bd5 100644 --- a/exercises/practice/binary-search/.approaches/recursion/snippet.txt +++ b/exercises/practice/binary-search/.approaches/recursion/snippet.txt @@ -1,7 +1,7 @@ let mid = array.len() / 2; match array[mid].cmp(&key) { - Ordering::Equal => Some(offset + mid), - Ordering::Less => find_rec(&array[mid + 1..], key, offset + mid + 1), - Ordering::Greater => find_rec(&array[..mid], key, offset), + Ordering::Equal => Some(mid), + Ordering::Greater => find(&array[..mid], key), + Ordering::Less => find(&array[mid + 1..], key).map(|p| p + mid + 1), }