The bisect module can only find the index to insert an element. I created a simple class based on the bisect module for precise searching and covered all the edge cases that came to mind with tests. Could you please check the correctness of the tests for the binary search extension module? I want to make sure that the tests match the function documentation (docstrings). Well, maybe more you could review the code, or suggest optimizations?
My code:
from bisect import bisect_left, bisect_right class BisectFinder: ''' This class contains some convenient binary search functions for an element in a list ''' @staticmethod def find_left_lt(a, x, lo=0, hi=None, key=None): '''Finds the index of the leftmost (among duplicates) element that is strictly less than X. A[index] < X A[index] == a2 [ a1{<x}, a1{<x}, A[index], a2{<x}, a2{<x}, a3{<=x}, a3{<=x}, a4{<=x}, a4{<=x}, a5{==x}, a5{==x}, a7{>=x}, a7{>=x}, a8{>=x}, a8{>=x}, a9{>x}, a9{>x}, a10{>x}, a10{>x} ] ''' index = bisect_left(a, x, lo=lo, hi=hi, key=key) if len(a) > 0 and index < len(a) + 1 and a[index - 1] < x: return bisect_left(a, a[index - 1], lo=lo, hi=index-1, key=key) raise ValueError("No elements less than x found.") @staticmethod def find_left_le(a, x, lo=0, hi=None, key=None): '''Finds the index of the leftmost (among duplicates) element that is less than or equal to X. A[index] <= X A[index] == a4 [ a1{<x}, a1{<x}, a2{<x}, a2{<x}, a3{<=x}, a3{<=x}, A[index], a4{<=x}, a4{<=x}, a5{==x}, a5{==x}, a7{>=x}, a7{>=x}, a8{>=x}, a8{>=x}, a9{>x}, a9{>x}, a10{>x}, a10{>x} ] ''' index = bisect_right(a, x, lo=lo, hi=hi, key=key) if len(a) > 0 and index < len(a) + 1 and a[index - 1] <= x: return bisect_left(a, a[index - 1], lo=lo, hi=index-1, key=key) raise ValueError("No elements less than or equal to x found.") @staticmethod def find_left_eq(a, x, lo=0, hi=None, key=None): '''Finds the index of the leftmost (among duplicates) element that is equal to X. A[index] == X A[index] == a5 [ a1{<x}, a1{<x}, a2{<x}, a2{<x}, a3{<=x}, a3{<=x}, a4{<=x}, a4{<=x}, A[index], a5{==x}, a5{==x}, a7{>=x}, a7{>=x}, a8{>=x}, a8{>=x}, a9{>x}, a9{>x}, a10{>x}, a10{>x} ] ''' index = bisect_left(a, x, lo=lo, hi=hi, key=key) if index != len(a) and a[index] == x: return index raise ValueError("No elements equal to x found.") @staticmethod def find_left_ge(a, x, lo=0, hi=None, key=None): '''Finds the index of the leftmost (among duplicates) element that is greater than or equal to X. A[index] >= X A[index] == a7 [ a1{<x}, a1{<x}, a2{<x}, a2{<x}, a3{<=x}, a3{<=x}, a4{<=x}, a4{<=x}, a5{==x}, a5{==x}, A[index], a7{>=x}, a7{>=x}, a8{>=x}, a8{>=x}, a9{>x}, a9{>x}, a10{>x}, a10{>x} ] ''' index = bisect_left(a, x, lo=lo, hi=hi, key=key) if index != len(a): return index raise ValueError("No elements greater than or equal to x found.") @staticmethod def find_left_gt(a, x, lo=0, hi=None, key=None): '''Finds the index of the leftmost (among duplicates) element that is strictly greater than X. A[index] > X A[index] == a9 [ a1{<x}, a1{<x}, a2{<x}, a2{<x}, a3{<=x}, a3{<=x}, a4{<=x}, a4{<=x}, a5{==x}, a5{==x}, a7{>=x}, a7{>=x}, a8{>=x}, a8{>=x}, A[index], a9{>x}, a9{>x}, a10{>x}, a10{>x} ] ''' index = bisect_right(a, x, lo=lo, hi=hi, key=key) if index != len(a): return index raise ValueError("No elements greater than x found.") @staticmethod def find_right_lt(a, x, lo=0, hi=None, key=None): '''Finds the index of the rightmost (among duplicates) element that is strictly less than X. A[index] < X A[index] == a2 [ a1{<x}, a1{<x}, a2{<x}, a2{<x}, A[index], a3{<=x}, a3{<=x}, a4{<=x}, a4{<=x}, a5{==x}, a5{==x}, a7{>=x}, a7{>=x}, a8{>=x}, a8{>=x}, a9{>x}, a9{>x}, a10{>x}, a10{>x} ] ''' index = bisect_left(a, x, lo=lo, hi=hi, key=key) if index: return index-1 raise ValueError("No elements less than x found.") @staticmethod def find_right_le(a, x, lo=0, hi=None, key=None): '''Finds the index of the rightmost (among duplicates) element that is less than or equal to X. A[index] <= X A[index] == a4 [ a1{<x}, a1{<x}, a2{<x}, a2{<x}, a3{<=x}, a3{<=x}, a4{<=x}, a4{<=x}, A[index], a5{==x}, a5{==x}, a7{>=x}, a7{>=x}, a8{>=x}, a8{>=x}, a9{>x}, a9{>x}, a10{>x}, a10{>x} ] ''' index = bisect_right(a, x, lo=lo, hi=hi, key=key) if index: return index-1 raise ValueError("No elements less than or equal to x found.") @staticmethod def find_right_eq(a, x, lo=0, hi=None, key=None): '''Finds the index of the rightmost (among duplicates) element that is equal to X. A[index] == X A[index] == a5 [ a1{<x}, a1{<x}, a2{<x}, a2{<x}, a3{<=x}, a3{<=x}, a4{<=x}, a4{<=x}, a5{==x}, a5{==x}, A[index], a7{>=x}, a7{>=x}, a8{>=x}, a8{>=x}, a9{>x}, a9{>x}, a10{>x}, a10{>x} ] ''' index = bisect_left(a, x, lo=lo, hi=hi, key=key) if index != len(a) and a[index] == x: return bisect_right(a, a[index], lo=index, hi=hi, key=key) - 1 raise ValueError("No elements equal to x found.") @staticmethod def find_right_ge(a, x, lo=0, hi=None, key=None): '''Finds the index of the rightmost (among duplicates) element that is greater than or equal to X. A[index] >= X A[index] == a7 [ a1{<x}, a1{<x}, a2{<x}, a2{<x}, a3{<=x}, a3{<=x}, a4{<=x}, a4{<=x}, a5{==x}, a5{==x}, a7{>=x}, a7{>=x}, A[index], a8{>=x}, a8{>=x}, a9{>x}, a9{>x}, a10{>x}, a10{>x} ] ''' index = bisect_left(a, x, lo=lo, hi=hi, key=key) if index != len(a): return bisect_right(a, a[index], lo=index, hi=hi, key=key) - 1 raise ValueError("No elements greater than or equal to x found.") @staticmethod def find_right_gt(a, x, lo=0, hi=None, key=None): '''Finds the index of the rightmost (among duplicates) element that is strictly greater than X. A[index] > X A[index] == a9 [ a1{<x}, a1{<x}, a2{<x}, a2{<x}, a3{<=x}, a3{<=x}, a4{<=x}, a4{<=x}, a5{==x}, a5{==x}, a7{>=x}, a7{>=x}, a8{>=x}, a8{>=x}, a9{>x}, a9{>x}, A[index], a10{>x}, a10{>x} ] ''' index = bisect_right(a, x, lo=lo, hi=hi, key=key) if index != len(a): return bisect_right(a, a[index], lo=index, hi=hi, key=key) - 1 raise ValueError("No elements greater than x found.")
My tests:
import unittest from unittest import TestCase from implements import BisectFinder class TestBisectFinder(TestCase): def setUp(self): self.empty_list = [] # 10 self.one_element_list = [5] # 2, 5, 7 self.two_element_list = [3, 8] # 2, 3, 6, 8, 9 self.three_element_list = [2, 7, 7] # 1, 2, 4, 7, 8 self.four_element_list = [2, 2, 2, 5] # 1, 2, 4, 5, 6 self.five_element_list = [1, 5, 5, 5, 9] # 0, 1, 2, 5, 7, 9, 10 # Tests for the find_left_lt function def test_find_left_lt_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_left_lt, self.empty_list, 10) def test_find_left_lt_one_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_lt, self.one_element_list, 2) self.assertRaises(ValueError, BisectFinder.find_left_lt, self.one_element_list, 5) self.assertEqual(BisectFinder.find_left_lt(self.one_element_list, 7), 0) def test_find_left_lt_two_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_lt, self.two_element_list, 2) self.assertRaises(ValueError, BisectFinder.find_left_lt, self.two_element_list, 3) self.assertEqual(BisectFinder.find_left_lt(self.two_element_list, 6), 0) self.assertEqual(BisectFinder.find_left_lt(self.two_element_list, 8), 0) self.assertEqual(BisectFinder.find_left_lt(self.two_element_list, 9), 1) def test_find_left_lt_three_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_lt, self.three_element_list, 1) self.assertRaises(ValueError, BisectFinder.find_left_lt, self.three_element_list, 2) self.assertEqual(BisectFinder.find_left_lt(self.three_element_list, 4), 0) self.assertEqual(BisectFinder.find_left_lt(self.three_element_list, 7), 0) self.assertEqual(BisectFinder.find_left_lt(self.three_element_list, 8), 1) def test_find_left_lt_four_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_lt, self.four_element_list, 1) self.assertRaises(ValueError, BisectFinder.find_left_lt, self.four_element_list, 2) self.assertEqual(BisectFinder.find_left_lt(self.four_element_list, 4), 0) self.assertEqual(BisectFinder.find_left_lt(self.four_element_list, 5), 0) self.assertEqual(BisectFinder.find_left_lt(self.four_element_list, 6), 3) def test_find_left_lt_five_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_lt, self.five_element_list, 0) self.assertRaises(ValueError, BisectFinder.find_left_lt, self.five_element_list, 1) self.assertEqual(BisectFinder.find_left_lt(self.five_element_list, 2), 0) self.assertEqual(BisectFinder.find_left_lt(self.five_element_list, 5), 0) self.assertEqual(BisectFinder.find_left_lt(self.five_element_list, 7), 1) self.assertEqual(BisectFinder.find_left_lt(self.five_element_list, 9), 1) self.assertEqual(BisectFinder.find_left_lt(self.five_element_list, 10), 4) # Tests for the find_left_le function def test_find_left_le_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_left_le, self.empty_list, 10) def test_find_left_le_one_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_le, self.one_element_list, 2) self.assertEqual(BisectFinder.find_left_le(self.one_element_list, 5), 0) self.assertEqual(BisectFinder.find_left_le(self.one_element_list, 7), 0) def test_find_left_le_two_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_le, self.two_element_list, 2) self.assertEqual(BisectFinder.find_left_le(self.two_element_list, 3), 0) self.assertEqual(BisectFinder.find_left_le(self.two_element_list, 6), 0) self.assertEqual(BisectFinder.find_left_le(self.two_element_list, 8), 1) self.assertEqual(BisectFinder.find_left_le(self.two_element_list, 9), 1) def test_find_left_le_three_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_le, self.three_element_list, 1) self.assertEqual(BisectFinder.find_left_le(self.three_element_list, 2), 0) self.assertEqual(BisectFinder.find_left_le(self.three_element_list, 4), 0) self.assertEqual(BisectFinder.find_left_le(self.three_element_list, 7), 1) self.assertEqual(BisectFinder.find_left_le(self.three_element_list, 8), 1) def test_find_left_le_four_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_le, self.four_element_list, 1) self.assertEqual(BisectFinder.find_left_le(self.four_element_list, 2), 0) self.assertEqual(BisectFinder.find_left_le(self.four_element_list, 4), 0) self.assertEqual(BisectFinder.find_left_le(self.four_element_list, 5), 3) self.assertEqual(BisectFinder.find_left_le(self.four_element_list, 6), 3) def test_find_left_le_five_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_le, self.five_element_list, 0) self.assertEqual(BisectFinder.find_left_le(self.five_element_list, 1), 0) self.assertEqual(BisectFinder.find_left_le(self.five_element_list, 2), 0) self.assertEqual(BisectFinder.find_left_le(self.five_element_list, 5), 1) self.assertEqual(BisectFinder.find_left_le(self.five_element_list, 7), 1) self.assertEqual(BisectFinder.find_left_le(self.five_element_list, 9), 4) self.assertEqual(BisectFinder.find_left_le(self.five_element_list, 10), 4) # Tests for the find_left_eq function def test_find_left_eq_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_left_eq, self.empty_list, 10) def test_find_left_eq_one_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_eq, self.one_element_list, 2) self.assertEqual(BisectFinder.find_left_eq(self.one_element_list, 5), 0) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.one_element_list, 7) def test_find_left_eq_two_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_eq, self.two_element_list, 2) self.assertEqual(BisectFinder.find_left_eq(self.two_element_list, 3), 0) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.two_element_list, 6) self.assertEqual(BisectFinder.find_left_eq(self.two_element_list, 8), 1) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.two_element_list, 9) def test_find_left_eq_three_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_eq, self.three_element_list, 1) self.assertEqual(BisectFinder.find_left_eq(self.three_element_list, 2), 0) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.three_element_list, 4) self.assertEqual(BisectFinder.find_left_eq(self.three_element_list, 7), 1) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.three_element_list, 8) def test_find_left_eq_four_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_eq, self.four_element_list, 1) self.assertEqual(BisectFinder.find_left_eq(self.four_element_list, 2), 0) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.four_element_list, 4) self.assertEqual(BisectFinder.find_left_eq(self.four_element_list, 5), 3) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.four_element_list, 6) def test_find_left_eq_five_element_list(self): self.assertRaises(ValueError, BisectFinder.find_left_eq, self.five_element_list, 0) self.assertEqual(BisectFinder.find_left_eq(self.five_element_list, 1), 0) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.five_element_list, 2) self.assertEqual(BisectFinder.find_left_eq(self.five_element_list, 5), 1) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.five_element_list, 7) self.assertEqual(BisectFinder.find_left_eq(self.five_element_list, 9), 4) self.assertRaises(ValueError, BisectFinder.find_left_eq, self.five_element_list, 10) # Tests for the find_left_ge function def test_find_left_ge_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_left_ge, self.empty_list, 10) def test_find_left_ge_one_element_list(self): self.assertEqual(BisectFinder.find_left_ge(self.one_element_list, 2), 0) self.assertEqual(BisectFinder.find_left_ge(self.one_element_list, 5), 0) self.assertRaises(ValueError, BisectFinder.find_left_ge, self.one_element_list, 7) def test_find_left_ge_two_element_list(self): self.assertEqual(BisectFinder.find_left_ge(self.two_element_list, 2), 0) self.assertEqual(BisectFinder.find_left_ge(self.two_element_list, 3), 0) self.assertEqual(BisectFinder.find_left_ge(self.two_element_list, 6), 1) self.assertEqual(BisectFinder.find_left_ge(self.two_element_list, 8), 1) self.assertRaises(ValueError, BisectFinder.find_left_ge, self.two_element_list, 9) def test_find_left_ge_three_element_list(self): self.assertEqual(BisectFinder.find_left_ge(self.three_element_list, 1), 0) self.assertEqual(BisectFinder.find_left_ge(self.three_element_list, 2), 0) self.assertEqual(BisectFinder.find_left_ge(self.three_element_list, 4), 1) self.assertEqual(BisectFinder.find_left_ge(self.three_element_list, 7), 1) self.assertRaises(ValueError, BisectFinder.find_left_ge, self.three_element_list, 8) def test_find_left_ge_four_element_list(self): self.assertEqual(BisectFinder.find_left_ge(self.four_element_list, 1), 0) self.assertEqual(BisectFinder.find_left_ge(self.four_element_list, 2), 0) self.assertEqual(BisectFinder.find_left_ge(self.four_element_list, 4), 3) self.assertEqual(BisectFinder.find_left_ge(self.four_element_list, 5), 3) self.assertRaises(ValueError, BisectFinder.find_left_ge, self.four_element_list, 6) def test_find_left_ge_five_element_list(self): self.assertEqual(BisectFinder.find_left_ge(self.five_element_list, 0), 0) self.assertEqual(BisectFinder.find_left_ge(self.five_element_list, 1), 0) self.assertEqual(BisectFinder.find_left_ge(self.five_element_list, 2), 1) self.assertEqual(BisectFinder.find_left_ge(self.five_element_list, 5), 1) self.assertEqual(BisectFinder.find_left_ge(self.five_element_list, 7), 4) self.assertEqual(BisectFinder.find_left_ge(self.five_element_list, 9), 4) self.assertRaises(ValueError, BisectFinder.find_left_ge, self.five_element_list, 10) # Tests for the find_left_gt function def test_find_left_gt_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_left_gt, self.empty_list, 10) def test_find_left_gt_one_element_list(self): self.assertEqual(BisectFinder.find_left_gt(self.one_element_list, 2), 0) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.one_element_list, 5) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.one_element_list, 7) def test_find_left_gt_two_element_list(self): self.assertEqual(BisectFinder.find_left_gt(self.two_element_list, 2), 0) self.assertEqual(BisectFinder.find_left_gt(self.two_element_list, 3), 1) self.assertEqual(BisectFinder.find_left_gt(self.two_element_list, 6), 1) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.two_element_list, 8) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.two_element_list, 9) def test_find_left_gt_three_element_list(self): self.assertEqual(BisectFinder.find_left_gt(self.three_element_list, 1), 0) self.assertEqual(BisectFinder.find_left_gt(self.three_element_list, 2), 1) self.assertEqual(BisectFinder.find_left_gt(self.three_element_list, 4), 1) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.three_element_list, 7) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.three_element_list, 8) def test_find_left_gt_four_element_list(self): self.assertEqual(BisectFinder.find_left_gt(self.four_element_list, 1), 0) self.assertEqual(BisectFinder.find_left_gt(self.four_element_list, 2), 3) self.assertEqual(BisectFinder.find_left_gt(self.four_element_list, 4), 3) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.four_element_list, 5) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.four_element_list, 6) def test_find_left_gt_five_element_list(self): self.assertEqual(BisectFinder.find_left_gt(self.five_element_list, 0), 0) self.assertEqual(BisectFinder.find_left_gt(self.five_element_list, 1), 1) self.assertEqual(BisectFinder.find_left_gt(self.five_element_list, 2), 1) self.assertEqual(BisectFinder.find_left_gt(self.five_element_list, 5), 4) self.assertEqual(BisectFinder.find_left_gt(self.five_element_list, 7), 4) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.five_element_list, 9) self.assertRaises(ValueError, BisectFinder.find_left_gt, self.five_element_list, 10) # Tests for the find_right_lt function def test_find_right_lt_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_right_lt, self.empty_list, 10) def test_find_right_lt_one_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_lt, self.one_element_list, 2) self.assertRaises(ValueError, BisectFinder.find_right_lt, self.one_element_list, 5) self.assertEqual(BisectFinder.find_right_lt(self.one_element_list, 7), 0) def test_find_right_lt_two_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_lt, self.two_element_list, 2) self.assertRaises(ValueError, BisectFinder.find_right_lt, self.two_element_list, 3) self.assertEqual(BisectFinder.find_right_lt(self.two_element_list, 6), 0) self.assertEqual(BisectFinder.find_right_lt(self.two_element_list, 8), 0) self.assertEqual(BisectFinder.find_right_lt(self.two_element_list, 9), 1) def test_find_right_lt_three_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_lt, self.three_element_list, 1) self.assertRaises(ValueError, BisectFinder.find_right_lt, self.three_element_list, 2) self.assertEqual(BisectFinder.find_right_lt(self.three_element_list, 4), 0) self.assertEqual(BisectFinder.find_right_lt(self.three_element_list, 7), 0) self.assertEqual(BisectFinder.find_right_lt(self.three_element_list, 8), 2) def test_find_right_lt_four_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_lt, self.four_element_list, 1) self.assertRaises(ValueError, BisectFinder.find_right_lt, self.four_element_list, 2) self.assertEqual(BisectFinder.find_right_lt(self.four_element_list, 4), 2) self.assertEqual(BisectFinder.find_right_lt(self.four_element_list, 5), 2) self.assertEqual(BisectFinder.find_right_lt(self.four_element_list, 6), 3) def test_find_right_lt_five_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_lt, self.five_element_list, 0) self.assertRaises(ValueError, BisectFinder.find_right_lt, self.five_element_list, 1) self.assertEqual(BisectFinder.find_right_lt(self.five_element_list, 2), 0) self.assertEqual(BisectFinder.find_right_lt(self.five_element_list, 5), 0) self.assertEqual(BisectFinder.find_right_lt(self.five_element_list, 7), 3) self.assertEqual(BisectFinder.find_right_lt(self.five_element_list, 9), 3) self.assertEqual(BisectFinder.find_right_lt(self.five_element_list, 10), 4) # Tests for the find_right_le function def test_find_right_le_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_right_le, self.empty_list, 10) def test_find_right_le_one_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_le, self.one_element_list, 2) self.assertEqual(BisectFinder.find_right_le(self.one_element_list, 5), 0) self.assertEqual(BisectFinder.find_right_le(self.one_element_list, 7), 0) def test_find_right_le_two_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_le, self.two_element_list, 2) self.assertEqual(BisectFinder.find_right_le(self.two_element_list, 3), 0) self.assertEqual(BisectFinder.find_right_le(self.two_element_list, 6), 0) self.assertEqual(BisectFinder.find_right_le(self.two_element_list, 8), 1) self.assertEqual(BisectFinder.find_right_le(self.two_element_list, 9), 1) def test_find_right_le_three_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_le, self.three_element_list, 1) self.assertEqual(BisectFinder.find_right_le(self.three_element_list, 2), 0) self.assertEqual(BisectFinder.find_right_le(self.three_element_list, 4), 0) self.assertEqual(BisectFinder.find_right_le(self.three_element_list, 7), 2) self.assertEqual(BisectFinder.find_right_le(self.three_element_list, 8), 2) def test_find_right_le_four_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_le, self.four_element_list, 1) self.assertEqual(BisectFinder.find_right_le(self.four_element_list, 2), 2) self.assertEqual(BisectFinder.find_right_le(self.four_element_list, 4), 2) self.assertEqual(BisectFinder.find_right_le(self.four_element_list, 5), 3) self.assertEqual(BisectFinder.find_right_le(self.four_element_list, 6), 3) def test_find_right_le_five_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_le, self.five_element_list, 0) self.assertEqual(BisectFinder.find_right_le(self.five_element_list, 1), 0) self.assertEqual(BisectFinder.find_right_le(self.five_element_list, 2), 0) self.assertEqual(BisectFinder.find_right_le(self.five_element_list, 5), 3) self.assertEqual(BisectFinder.find_right_le(self.five_element_list, 7), 3) self.assertEqual(BisectFinder.find_right_le(self.five_element_list, 9), 4) self.assertEqual(BisectFinder.find_right_le(self.five_element_list, 10), 4) # Tests for the find_right_eq function def test_find_right_eq_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_right_eq, self.empty_list, 10) def test_find_right_eq_one_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_eq, self.one_element_list, 2) self.assertEqual(BisectFinder.find_right_eq(self.one_element_list, 5), 0) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.one_element_list, 7) def test_find_right_eq_two_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_eq, self.two_element_list, 2) self.assertEqual(BisectFinder.find_right_eq(self.two_element_list, 3), 0) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.two_element_list, 6) self.assertEqual(BisectFinder.find_right_eq(self.two_element_list, 8), 1) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.two_element_list, 9) def test_find_right_eq_three_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_eq, self.three_element_list, 1) self.assertEqual(BisectFinder.find_right_eq(self.three_element_list, 2), 0) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.three_element_list, 4) self.assertEqual(BisectFinder.find_right_eq(self.three_element_list, 7), 2) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.three_element_list, 8) def test_find_right_eq_four_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_eq, self.four_element_list, 1) self.assertEqual(BisectFinder.find_right_eq(self.four_element_list, 2), 2) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.four_element_list, 4) self.assertEqual(BisectFinder.find_right_eq(self.four_element_list, 5), 3) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.four_element_list, 6) def test_find_right_eq_five_element_list(self): self.assertRaises(ValueError, BisectFinder.find_right_eq, self.five_element_list, 0) self.assertEqual(BisectFinder.find_right_eq(self.five_element_list, 1), 0) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.five_element_list, 2) self.assertEqual(BisectFinder.find_right_eq(self.five_element_list, 5), 3) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.five_element_list, 7) self.assertEqual(BisectFinder.find_right_eq(self.five_element_list, 9), 4) self.assertRaises(ValueError, BisectFinder.find_right_eq, self.five_element_list, 10) # Tests for the find_right_ge function def test_find_right_ge_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_right_ge, self.empty_list, 10) def test_find_right_ge_one_element_list(self): self.assertEqual(BisectFinder.find_right_ge(self.one_element_list, 2), 0) self.assertEqual(BisectFinder.find_right_ge(self.one_element_list, 5), 0) self.assertRaises(ValueError, BisectFinder.find_right_ge, self.one_element_list, 7) def test_find_right_ge_two_element_list(self): self.assertEqual(BisectFinder.find_right_ge(self.two_element_list, 2), 0) self.assertEqual(BisectFinder.find_right_ge(self.two_element_list, 3), 0) self.assertEqual(BisectFinder.find_right_ge(self.two_element_list, 6), 1) self.assertEqual(BisectFinder.find_right_ge(self.two_element_list, 8), 1) self.assertRaises(ValueError, BisectFinder.find_right_ge, self.two_element_list, 9) def test_find_right_ge_three_element_list(self): self.assertEqual(BisectFinder.find_right_ge(self.three_element_list, 1), 0) self.assertEqual(BisectFinder.find_right_ge(self.three_element_list, 2), 0) self.assertEqual(BisectFinder.find_right_ge(self.three_element_list, 4), 2) self.assertEqual(BisectFinder.find_right_ge(self.three_element_list, 7), 2) self.assertRaises(ValueError, BisectFinder.find_right_ge, self.three_element_list, 8) def test_find_right_ge_four_element_list(self): self.assertEqual(BisectFinder.find_right_ge(self.four_element_list, 1), 2) self.assertEqual(BisectFinder.find_right_ge(self.four_element_list, 2), 2) self.assertEqual(BisectFinder.find_right_ge(self.four_element_list, 4), 3) self.assertEqual(BisectFinder.find_right_ge(self.four_element_list, 5), 3) self.assertRaises(ValueError, BisectFinder.find_right_ge, self.four_element_list, 6) def test_find_right_ge_five_element_list(self): self.assertEqual(BisectFinder.find_right_ge(self.five_element_list, 0), 0) self.assertEqual(BisectFinder.find_right_ge(self.five_element_list, 1), 0) self.assertEqual(BisectFinder.find_right_ge(self.five_element_list, 2), 3) self.assertEqual(BisectFinder.find_right_ge(self.five_element_list, 5), 3) self.assertEqual(BisectFinder.find_right_ge(self.five_element_list, 7), 4) self.assertEqual(BisectFinder.find_right_ge(self.five_element_list, 9), 4) self.assertRaises(ValueError, BisectFinder.find_right_ge, self.five_element_list, 10) # Tests for the find_right_gt function def test_find_right_gt_empty_list(self): self.assertRaises(ValueError, BisectFinder.find_right_gt, self.empty_list, 10) def test_find_right_gt_one_element_list(self): self.assertEqual(BisectFinder.find_right_gt(self.one_element_list, 2), 0) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.one_element_list, 5) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.one_element_list, 7) def test_find_right_gt_two_element_list(self): self.assertEqual(BisectFinder.find_right_gt(self.two_element_list, 2), 0) self.assertEqual(BisectFinder.find_right_gt(self.two_element_list, 3), 1) self.assertEqual(BisectFinder.find_right_gt(self.two_element_list, 6), 1) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.two_element_list, 8) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.two_element_list, 9) def test_find_right_gt_three_element_list(self): self.assertEqual(BisectFinder.find_right_gt(self.three_element_list, 1), 0) self.assertEqual(BisectFinder.find_right_gt(self.three_element_list, 2), 2) self.assertEqual(BisectFinder.find_right_gt(self.three_element_list, 4), 2) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.three_element_list, 7) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.three_element_list, 8) def test_find_right_gt_four_element_list(self): self.assertEqual(BisectFinder.find_right_gt(self.four_element_list, 1), 2) self.assertEqual(BisectFinder.find_right_gt(self.four_element_list, 2), 3) self.assertEqual(BisectFinder.find_right_gt(self.four_element_list, 4), 3) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.four_element_list, 5) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.four_element_list, 6) def test_find_right_gt_five_element_list(self): self.assertEqual(BisectFinder.find_right_gt(self.five_element_list, 0), 0) self.assertEqual(BisectFinder.find_right_gt(self.five_element_list, 1), 3) self.assertEqual(BisectFinder.find_right_gt(self.five_element_list, 2), 3) self.assertEqual(BisectFinder.find_right_gt(self.five_element_list, 5), 4) self.assertEqual(BisectFinder.find_right_gt(self.five_element_list, 7), 4) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.five_element_list, 9) self.assertRaises(ValueError, BisectFinder.find_right_gt, self.five_element_list, 10) if __name__ == '__main__': unittest.main()
find_left_le([1, 1, 2, 3, 3, 3, 4, 5], 4) == 0
? Because here,1
is a duplicate.\$\endgroup\$lt
,le
, the leftmost one forge
,gt
) and, if there are several answers, then find the leftmost one. This is true for allleft_...
functions.\$\endgroup\$