Skip to content
Open
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
39 changes: 39 additions & 0 deletions data_structures/queues/design_hit_counter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from collections import deque


class HitCounter:
"""
A counter that records hits (events) and can return
the number of hits in the past 5 minutes (300 seconds).

>>> hc = HitCounter()
>>> hc.hit(1)
>>> hc.hit(2)
>>> hc.hit(300)
>>> hc.get_hits(300)
3
>>> hc.get_hits(301)
2
"""

def __init__(self) -> None:
self.hits: deque[int] = deque()

def hit(self, timestamp: int) -> None:
"""Record a hit at the given timestamp (in seconds)."""
self.hits.append(timestamp)

def get_hits(self, timestamp: int) -> int:
"""
Return the number of hits in the past 5 minutes
from the given timestamp.
"""
while self.hits and self.hits[0] <= timestamp - 300:
self.hits.popleft()
return len(self.hits)


if __name__ == "__main__":
import doctest

doctest.testmod()
42 changes: 42 additions & 0 deletions dynamic_programming/triangle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from __future__ import annotations


def minimum_total(triangle: list[list[int]]) -> int:
"""
Return the minimum path sum from top to bottom of a triangle.

Each step you may move to adjacent numbers on the row below.
The input must be a proper triangle: len(row i) == i + 1.

>>> minimum_total([[2],[3,4],[6,5,7],[4,1,8,3]])
11
>>> minimum_total([[-10]])
-10
>>> minimum_total([[1],[2,3]])
3
>>> minimum_total([]) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValueError: triangle must be non-empty and well-formed
>>> minimum_total([[1],[2]]) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValueError: triangle must be non-empty and well-formed
"""
# Basic validation: non-empty and proper "triangle" shape
if not triangle or any(len(row) != i + 1 for i, row in enumerate(triangle)):
raise ValueError("triangle must be non-empty and well-formed")

# Start from the last row and fold upwards. dp[j] stores the minimum path
# sum from row r to the bottom starting at column j.
dp = triangle[-1][:] # copy so we don't mutate the input

for r in range(len(triangle) - 2, -1, -1):
for c in range(r + 1):
dp[c] = triangle[r][c] + min(dp[c], dp[c + 1])

return dp[0]


if __name__ == "__main__":
import doctest

doctest.testmod()