Browse Source

Add linear_search_reverse and linear_search_reverse_proc

Nia 11 months ago
parent
commit
3337d6b264
2 changed files with 104 additions and 0 deletions
  1. 69 0
      core/slice/slice.odin
  2. 35 0
      tests/core/slice/test_core_slice.odin

+ 69 - 0
core/slice/slice.odin

@@ -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.

+ 35 - 0
tests/core/slice/test_core_slice.odin

@@ -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)
+}