oldratlee/dynamic-programming-study

dynamic programming study

★ 0Forks 0PythonGitHub ↗Compare

Project website ↗

dynamic-programmingidaaidaa3estudy

README

Dynamic Programming Study

Build CI Codecov License GitHub repo size gitpod: Ready to Code

Personal notes and implementations for dynamic programming, drawn from LeetCode, CLRS (4th ed.), and Levitin Introduction to the Design and Analysis of Algorithms (3rd ed.). Python 3.12+.

The point of this repo is to compare DP strategies on the same problem. A second implementation (space-optimized, top-down memo, brute force, …) is more useful than a new abstraction.

Practices

Keep solvers small and comparable. One spec, several implementations; tests run all of them. When adding a problem, follow this loop.

  • Readability counts.
    • Docstring: module, function, statement, source, examples, constraints.
    • Each public function: the state, the recurrence, then Time / Space with the symbols defined.
    • Comment the DP transition and any non-obvious cost.
  • Keep the logic simple and clean.
    • Write the recurrence as one expression when it fits.
    • Public API is functions; classes only for data structures.
    • Prefer a dummy / index sentinel or an early return over a special-case branch.
    • Return int | None when the result is impossible or absent; do not use a magic value like inf.
    • No unused helpers or shared framework.
  • Strategy over abstraction.
    • Prefer another solver of the same spec over a shared framework.
    • Keep problem variants separate from algorithm variants. Encode problem variants in the type.
  • Reliability.
    • Types as contracts, collections.abc.Sequence for read-only inputs.
    • PEP 695 generics when a structure needs them.
    • assert preconditions.
  • Constant factors count.
    • Avoid an intermediate slice when a cheaper equivalent exists.
    • Rolling state and index-based recursion are first-class variants.
  • One test body.
    • Parametrize impl over every solver of a spec.
    • Empty and edge cases first, then book or LeetCode samples.

Setup and commands

poetry sync                     # env + dependencies from pyproject.toml

poetry run pytest               # unit tests (benchmarks off)
poetry run pytest -m benchmark  # perf only
poetry run pytest -m ""         # everything, as in CI

poetry run flake8 src tests     # style lint
poetry run isort src tests      # sort imports
poetry run mypy src             # type check

./scripts/run.sh                # pytest + flake8 + isort + mypy

Default pytest skips @pytest.mark.benchmark cases (-m "not benchmark"). Benchmark inputs stay small enough that brute-force variants can still run.

Problems from Chapter 8 of Levitin IDAA 3e

Problems from CLRS 4e

LeetCode

Contributors

oldratleedependabot[bot]

Issues