mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Merge pull request #4304 from kawaii-Code/linear_search_reverse
Add linear_search_reverse and linear_search_reverse_proc
This commit is contained in:
+125
-24
@@ -96,9 +96,37 @@ contains :: proc(array: $T/[]$E, value: E) -> bool where intrinsics.type_is_comp
|
|||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Searches the given slice for the given element in O(n) time.
|
||||||
|
|
||||||
|
If you need a custom search condition, see `linear_search_proc`
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- array: The slice to search in.
|
||||||
|
- key: The element to search for.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- index: The index `i`, such that `array[i]` is the first occurrence of `key` in `array`, or -1 if `key` is not present in `array`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
index: int
|
||||||
|
found: bool
|
||||||
|
|
||||||
|
a := []i32{10, 10, 10, 20}
|
||||||
|
|
||||||
|
index, found = linear_search_reverse(a, 10)
|
||||||
|
assert(index == 0 && found == true)
|
||||||
|
|
||||||
|
index, found = linear_search_reverse(a, 30)
|
||||||
|
assert(index == -1 && found == false)
|
||||||
|
|
||||||
|
// Note that `index == 1`, since it is relative to `a[2:]`
|
||||||
|
index, found = linear_search_reverse(a[2:], 20)
|
||||||
|
assert(index == 1 && found == true)
|
||||||
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
|
linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
|
||||||
where intrinsics.type_is_comparable(T) #no_bounds_check {
|
where intrinsics.type_is_comparable(T) {
|
||||||
for x, i in array {
|
for x, i in array {
|
||||||
if x == key {
|
if x == key {
|
||||||
return i, true
|
return i, true
|
||||||
@@ -107,8 +135,18 @@ linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
|
|||||||
return -1, false
|
return -1, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Searches the given slice for the first element satisfying predicate `f` in O(n) time.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- array: The slice to search in.
|
||||||
|
- f: The search condition.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- index: The index `i`, such that `array[i]` is the first `x` in `array` for which `f(x) == true`, or -1 if such `x` does not exist.
|
||||||
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) #no_bounds_check {
|
linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) {
|
||||||
for x, i in array {
|
for x, i in array {
|
||||||
if f(x) {
|
if f(x) {
|
||||||
return i, true
|
return i, true
|
||||||
@@ -118,22 +156,88 @@ linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, f
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Binary search searches the given slice for the given element.
|
Searches the given slice for the given element in O(n) time, starting from the
|
||||||
If the slice is not sorted, the returned index is unspecified and meaningless.
|
slice end.
|
||||||
|
|
||||||
If the value is found then the returned int is the index of the matching element.
|
If you need a custom search condition, see `linear_search_reverse_proc`
|
||||||
If there are multiple matches, then any one of the matches could be returned.
|
|
||||||
|
|
||||||
If the value is not found then the returned int is the index where a matching
|
Inputs:
|
||||||
element could be inserted while maintaining sorted order.
|
- array: The slice to search in.
|
||||||
|
- key: The element to search for.
|
||||||
|
|
||||||
# Examples
|
Returns:
|
||||||
|
- index: The index `i`, such that `array[i]` is the last occurrence of `key` in `array`, or -1 if `key` is not present in `array`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
index: int
|
||||||
|
found: bool
|
||||||
|
|
||||||
|
a := []i32{10, 10, 10, 20}
|
||||||
|
|
||||||
|
index, found = linear_search_reverse(a, 20)
|
||||||
|
assert(index == 3 && found == true)
|
||||||
|
|
||||||
|
index, found = linear_search_reverse(a, 10)
|
||||||
|
assert(index == 2 && found == true)
|
||||||
|
|
||||||
|
index, found = linear_search_reverse(a, 30)
|
||||||
|
assert(index == -1 && found == false)
|
||||||
|
|
||||||
|
// Note that `index == 1`, since it is relative to `a[2:]`
|
||||||
|
index, found = linear_search_reverse(a[2:], 20)
|
||||||
|
assert(index == 1 && found == true)
|
||||||
|
*/
|
||||||
|
@(require_results)
|
||||||
|
linear_search_reverse :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
|
||||||
|
where intrinsics.type_is_comparable(T) {
|
||||||
|
#reverse for x, i in array {
|
||||||
|
if x == key {
|
||||||
|
return i, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1, false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Searches the given slice for the last element satisfying predicate `f` in O(n)
|
||||||
|
time, starting from the slice end.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- array: The slice to search in.
|
||||||
|
- f: The search condition.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- index: The index `i`, such that `array[i]` is the last `x` in `array` for which `f(x) == true`, or -1 if such `x` does not exist.
|
||||||
|
*/
|
||||||
|
@(require_results)
|
||||||
|
linear_search_reverse_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) {
|
||||||
|
#reverse for x, i in array {
|
||||||
|
if f(x) {
|
||||||
|
return i, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1, false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Searches the given slice for the given element.
|
||||||
|
If the slice is not sorted, the returned index is unspecified and meaningless.
|
||||||
|
|
||||||
|
If the value is found then the returned int is the index of the matching element.
|
||||||
|
If there are multiple matches, then any one of the matches could be returned.
|
||||||
|
|
||||||
|
If the value is not found then the returned int is the index where a matching
|
||||||
|
element could be inserted while maintaining sorted order.
|
||||||
|
|
||||||
|
For slices of more complex types see: `binary_search_by`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
/*
|
||||||
Looks up a series of four elements. The first is found, with a
|
Looks up a series of four elements. The first is found, with a
|
||||||
uniquely determined position; the second and third are not
|
uniquely determined position; the second and third are not
|
||||||
found; the fourth could match any position in `[1, 4]`.
|
found; the fourth could match any position in `[1, 4]`.
|
||||||
|
*/
|
||||||
|
|
||||||
```
|
|
||||||
index: int
|
index: int
|
||||||
found: bool
|
found: bool
|
||||||
|
|
||||||
@@ -150,9 +254,6 @@ linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, f
|
|||||||
|
|
||||||
index, found = slice.binary_search(s, 1)
|
index, found = slice.binary_search(s, 1)
|
||||||
assert(index >= 1 && index <= 4 && found == true)
|
assert(index >= 1 && index <= 4 && found == true)
|
||||||
```
|
|
||||||
|
|
||||||
For slices of more complex types see: binary_search_by
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
|
binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
|
||||||
@@ -161,21 +262,21 @@ binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Binary search searches the given slice for the given element.
|
Searches the given slice for the given element.
|
||||||
If the slice is not sorted, the returned index is unspecified and meaningless.
|
If the slice is not sorted, the returned index is unspecified and meaningless.
|
||||||
|
|
||||||
If the value is found then the returned int is the index of the matching element.
|
If the value is found then the returned int is the index of the matching element.
|
||||||
If there are multiple matches, then any one of the matches could be returned.
|
If there are multiple matches, then any one of the matches could be returned.
|
||||||
|
|
||||||
If the value is not found then the returned int is the index where a matching
|
If the value is not found then the returned int is the index where a matching
|
||||||
element could be inserted while maintaining sorted order.
|
element could be inserted while maintaining sorted order.
|
||||||
|
|
||||||
The array elements and key may be different types. This allows the filter procedure
|
The array elements and key may be different types. This allows the filter procedure
|
||||||
to compare keys against a slice of structs, one struct value at a time.
|
to compare keys against a slice of structs, one struct value at a time.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
index: int
|
- index: int
|
||||||
found: bool
|
- found: bool
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
|
|||||||
@@ -306,3 +306,38 @@ test_compare_empty :: proc(t: ^testing.T) {
|
|||||||
testing.expectf(t, slice.equal(c[:], d[:]),
|
testing.expectf(t, slice.equal(c[:], d[:]),
|
||||||
"Expected two separate empty slices of two dynamic arrays to be equal")
|
"Expected two separate empty slices of two dynamic arrays to be equal")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test
|
||||||
|
test_linear_search_reverse :: proc(t: ^testing.T) {
|
||||||
|
index: int
|
||||||
|
found: bool
|
||||||
|
|
||||||
|
s := []i32{0, 50, 50, 100}
|
||||||
|
|
||||||
|
index, found = slice.linear_search_reverse(s, 100)
|
||||||
|
testing.expect(t, found)
|
||||||
|
testing.expect_value(t, index, len(s) - 1)
|
||||||
|
|
||||||
|
index, found = slice.linear_search_reverse(s[len(s) - 1:], 100)
|
||||||
|
testing.expect(t, found)
|
||||||
|
testing.expect_value(t, index, 0)
|
||||||
|
|
||||||
|
index, found = slice.linear_search_reverse(s, 50)
|
||||||
|
testing.expect(t, found)
|
||||||
|
testing.expect_value(t, index, 2)
|
||||||
|
|
||||||
|
index, found = slice.linear_search_reverse(s, 0)
|
||||||
|
testing.expect(t, found)
|
||||||
|
testing.expect_value(t, index, 0)
|
||||||
|
|
||||||
|
index, found = slice.linear_search_reverse(s, -1)
|
||||||
|
testing.expect(t, !found)
|
||||||
|
|
||||||
|
less_than_80 :: proc(x: i32) -> bool {
|
||||||
|
return x < 80
|
||||||
|
}
|
||||||
|
|
||||||
|
index, found = slice.linear_search_reverse_proc(s, less_than_80)
|
||||||
|
testing.expect(t, found)
|
||||||
|
testing.expect_value(t, index, 2)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user