Algorithms

Find a value in a sorted list by halving the search range at every step — O(log n).

Version 1.5.0 · current Versions: 1.5.0 1.4.0 1.3.0 1.2.0 1.1.0 1.0.0

Implementations

Sign in to open in IDE Sign in with your Zerethon account to create your own copy of this sample.

Files

README.md
# Binary Search

Zerethon Official Sample `binary-search`, version 1.5.0, Python 3.12.

- `binary_search.py` — the algorithm (`binary_search`, and `binary_search_steps` to trace it)
- `main.py` — entry file: searches a few values and prints the steps
- `test_binary_search.py` — checks; set it as the entry file to run them

This project is your own copy. Changing it never changes the official sample.
See the algorithm animated: https://tools.zerethon.com/binary-search-visualizer
binary_search.py
"""Binary search over a sorted list (Zerethon Official Sample: binary-search 1.5.0)."""


def binary_search(a, target):
    """Return the index of target in a (sorted ascending), or -1 if it is absent."""
    lo, hi = 0, len(a) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if a[mid] == target:
            return mid
        if a[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1


def binary_search_steps(a, target):
    """Yield (lo, mid, hi) for every comparison binary_search makes."""
    lo, hi = 0, len(a) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        yield lo, mid, hi
        if a[mid] == target:
            return
        if a[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
main.py entry
from binary_search import binary_search, binary_search_steps

numbers = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
print("Sorted list:", numbers)
print()

for target in (23, 2, 91, 7):
    index = binary_search(numbers, target)
    result = f"found at index {index}" if index != -1 else "not found"
    print(f"search {target:>2}: {result}")

print()
print("Steps for 23 (lo, mid, hi):")
for lo, mid, hi in binary_search_steps(numbers, 23):
    print(f"  lo={lo} mid={mid} hi={hi} -> a[mid]={numbers[mid]}")
test_binary_search.py
# Checks for binary_search. To run them, set this file as the entry file
# (the ▶ button next to it in Files) and press Run.
from binary_search import binary_search

cases = [
    ([], 1, -1),
    ([4], 4, 0),
    ([4], 5, -1),
    ([1, 3, 5, 7, 9], 1, 0),
    ([1, 3, 5, 7, 9], 9, 4),
    ([1, 3, 5, 7, 9], 6, -1),
    (list(range(0, 1000, 2)), 998, 499),
]

for a, target, expected in cases:
    got = binary_search(a, target)
    assert got == expected, f"binary_search({a[:5]}..., {target}) = {got}, expected {expected}"

print(f"All {len(cases)} checks passed.")

Source: Zerethon Official Sample. Algorithm as shown in the Zerethon Tools Binary Search Visualizer.