Add linear_search_reverse and linear_search_reverse_proc

This commit is contained in:
Nia
2024-09-25 16:41:55 +03:00
parent 791b05b14f
commit 3337d6b264
2 changed files with 104 additions and 0 deletions

View File

@@ -96,6 +96,14 @@ contains :: proc(array: $T/[]$E, value: E) -> bool where intrinsics.type_is_comp
return found
}
/*
Searches the given element in the given slice in O(n) time.
Returns the first index at which the given element can be found in the slice,
or -1 if it is not present.
If you need a custom compare procedure, see `linear_search_proc`
*/
@(require_results)
linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
where intrinsics.type_is_comparable(T) #no_bounds_check {
@@ -107,6 +115,12 @@ linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
return -1, false
}
/*
Searches the given element in the given slice in O(n) time, using the given predicate.
Returns the first index at which the given element can be found in the slice,
or -1 if it is not present.
*/
@(require_results)
linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) #no_bounds_check {
for x, i in array {
@@ -117,6 +131,61 @@ linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, f
return -1, false
}
/*
Reverse linear search searches the given element in the given slice in O(n) time,
starting from the slice end.
Returns the last index at which the given element can be found in the slice,
or -1 if it is not present
# Examples
```
index: int
found: bool
a := []i32{1, 1, 1, 2}
index, found = linear_search_reverse(a, 2)
assert(index == 3 && found == true)
index, found = linear_search_reverse(a, 1)
assert(index == 2 && found == true)
index, found = linear_search_reverse(a, 0)
assert(index == -1 && found == false)
```
If you need a custom compare procedure, see `linear_search_reverse_proc`
*/
@(require_results)
linear_search_reverse :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
where intrinsics.type_is_comparable(T) #no_bounds_check {
#reverse for x, i in array {
if x == key {
return i, true
}
}
return -1, false
}
/*
Searches the given element in the given slice in O(n) time, starting from the end of
the slice and using the given predicate.
Returns the last index at which the given element can be found in the slice,
or -1 if it is not present
*/
@(require_results)
linear_search_reverse_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) #no_bounds_check {
#reverse for x, i in array {
if f(x) {
return i, true
}
}
return -1, false
}
/*
Binary search searches the given slice for the given element.
If the slice is not sorted, the returned index is unspecified and meaningless.

View File

@@ -306,3 +306,38 @@ test_compare_empty :: proc(t: ^testing.T) {
testing.expectf(t, slice.equal(c[:], d[:]),
"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)
}