Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Reference algorithms
on: [push, pull_request]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
cache: pip
- run: python -m pip install -r requirements-dev.txt
- run: make test
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
.PHONY: install test compile clean
.PHONY: install test compile clean

install:
python -m pip install --upgrade pip
python -m pip install -r requirements-dev.txt

test:
python -m unittest discover -s tests
python -m pytest

compile:
python -m compileall -q .
python -m compileall -q src

clean:
python -c "import shutil; from pathlib import Path; [shutil.rmtree(p, ignore_errors=True) for p in Path('.').rglob('__pycache__')]"
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,31 @@ docs/

## Clean Reference Implementations

Requires Python 3.11+. From the repository root:

```bash
pytest
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install -r requirements-dev.txt
python -m pytest
```

`make test` runs the same pytest suite. Collection is restricted to `tests/`:
original exercises may read stdin or run demonstrations on import.

The reference suite checks exhaustive small input combinations against Python's
built-in search/sort behavior, stable sorting with custom `__lt__` objects,
non-mutation, and stack/queue lifecycle errors. GitHub Actions exercises Python
3.11–3.13; AWS CodeBuild uses the same tests.

| Operation | Time | Extra space | Contract |
| --- | --- | --- | --- |
| Linear search | O(n) | O(1) | First matching index, or -1 |
| Binary search | O(log n) | O(1) | Ascending input; any matching index, or -1 |
| Merge sort | O(n log n) | O(n) | Stable new list; mutually orderable elements |
| Stack push / pop | O(1) amortized | O(n) storage | LIFO; empty pop/peek raises IndexError |
| Queue enqueue / dequeue | O(1) | O(n) storage | FIFO; empty dequeue raises IndexError |

Current reference modules:

- `src/dsa/searching.py`
Expand All @@ -47,4 +68,4 @@ For every topic:

This is the primary home for Python algorithm, DSA, and revision work.

Next upgrade: expand edge-case tests and add time/space complexity notes for each clean implementation in `src/dsa/`.
The archived exercises are historical learning material; the supported, CI-tested surface is `src/dsa/`.
8 changes: 6 additions & 2 deletions buildspec.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
version: 0.2

phases:
install:
runtime-versions:
python: 3.12
commands:
- python -m pip install -r requirements-dev.txt
build:
commands:
# - echo "Hello World"
- python -m pytest
53 changes: 14 additions & 39 deletions docs/engineering-runbook.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
# Engineering Runbook

## Repository Profile

- Repository: $repoName
- Classification: Python project
- Tracked files: 111
- Python files: 76
- JavaScript/TypeScript files: 0
- Notebooks: 0
- Terraform files: 0

## Setup

``bash
No package install step is required for the tracked source.
``

## Verification

``bash
python -m unittest discover -s tests
python -m compileall -q .
``

## Release Hygiene

- Keep generated outputs, caches, local datasets, virtual environments, and dependency folders out of git.
- Prefer deterministic commands over manual notebook or console-only steps.
- Document required secrets and environment variables instead of committing them.
- Keep Dockerfiles, CI workflows, and tests aligned with the actual project stack.
- Treat learning or reference material honestly as reference material; do not present it as production service code unless it has service-grade tests, deployment, and operations docs.

## Maintenance Checklist

- Review dependencies quarterly.
- Run tests before every push.
- Confirm git status --short is clean before packaging.
- Include .git only when an external submission explicitly requires repository history.
# Reference algorithm verification

```bash
python -m pip install -r requirements-dev.txt
make test
make compile
```

Pytest collection is limited to `tests/`; historical exercises can run input or
print operations on import. Add new maintained algorithms under `src/dsa/` and
cover empty inputs, duplicates, non-mutation, and declared ordering contracts.
Binary search assumes ascending data and may return any duplicate match.
Exhaustive small-domain tests compare search and sorting results to built-in
oracles; queue and stack tests exercise reuse and underflow.
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["."]
addopts = "-ra"
4 changes: 2 additions & 2 deletions src/dsa/sorting.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
def merge_sort(values):
"""Return a sorted copy of values using merge sort."""
"""Return a stable sorted copy; O(n log n) time and O(n) auxiliary space."""
if len(values) <= 1:
return list(values)

Expand All @@ -15,7 +15,7 @@ def _merge(left, right):
j = 0

while i < len(left) and j < len(right):
if left[i] <= right[j]:
if not right[j] < left[i]:
result.append(left[i])
i += 1
else:
Expand Down
62 changes: 62 additions & 0 deletions tests/test_invariants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from itertools import product

import pytest

from src.dsa.queue import Queue
from src.dsa.searching import binary_search, linear_search
from src.dsa.sorting import merge_sort
from src.dsa.stack import Stack


def test_sort_and_search_against_builtin_oracles():
for length in range(6):
for values in product((-1, 0, 1), repeat=length):
ordered = merge_sort(values)
assert ordered == sorted(values)
for target in (-2, -1, 0, 1, 2):
index = binary_search(ordered, target)
assert (index == -1) == (target not in ordered)
if index != -1:
assert ordered[index] == target
expected = values.index(target) if target in values else -1
assert linear_search(values, target) == expected


def test_merge_sort_preserves_equal_key_order_with_lt_only_objects():
class Record:
def __init__(self, key, name):
self.key, self.name = key, name

def __lt__(self, other):
return self.key < other.key

records = [Record(2, "a"), Record(1, "b"), Record(2, "c"), Record(1, "d")]
original = records[:]
assert [record.name for record in merge_sort(records)] == ["b", "d", "a", "c"]
assert records == original


def test_interleaved_queue_operations_and_reuse_after_empty():
queue = Queue()
queue.enqueue(None)
queue.enqueue("a")
assert queue.dequeue() is None
queue.enqueue("b")
assert [queue.dequeue(), queue.dequeue()] == ["a", "b"]
assert queue.is_empty() and len(queue) == 0
with pytest.raises(IndexError):
queue.dequeue()
queue.enqueue("reused")
assert queue.dequeue() == "reused"


def test_stack_peek_does_not_consume_and_empty_errors():
stack = Stack()
for operation in (stack.peek, stack.pop):
with pytest.raises(IndexError):
operation()
for value in (None, "a", "b"):
stack.push(value)
assert stack.peek() == "b" and len(stack) == 3
assert [stack.pop(), stack.pop(), stack.pop()] == ["b", "a", None]
assert stack.is_empty()
Loading