Skip to content

Commit f174d0f

Browse files
authored
Merge branch 'master' into codex/fix-matrix-search-row-start
2 parents f4e7676 + deb9cfc commit f174d0f

7 files changed

Lines changed: 418 additions & 12 deletions

File tree

‎data_structures/heap/heap.py‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,15 @@
22

33
from abc import abstractmethod
44
from collections.abc import Iterable
5-
from typing import Protocol, TypeVar
5+
from typing import Protocol
66

77

88
class Comparable(Protocol):
99
@abstractmethod
10-
def __gt__(self: T, other: T, /) -> bool:
10+
def __gt__(self, other: object, /) -> bool:
1111
pass
1212

1313

14-
T = TypeVar("T", bound=Comparable)
15-
16-
1714
class Heap[T: Comparable]:
1815
"""A Max Heap Implementation
1916

‎data_structures/linked_list/print_reverse.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,14 @@ def make_linked_list(elements_list: Iterable[int]) -> LinkedList:
9898
abc
9999
>>> make_linked_list([7, 25])
100100
7 -> 25
101+
>>> make_linked_list(x for x in [7, 25])
102+
7 -> 25
103+
>>> make_linked_list(x for x in range(0))
104+
Traceback (most recent call last):
105+
...
106+
Exception: The Elements List is empty
101107
"""
108+
elements_list = list(elements_list)
102109
if not elements_list:
103110
raise Exception("The Elements List is empty")
104111

‎maths/keith_number.py‎

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
"""
2+
== Keith Number (Repfigit Number) ==
3+
A Keith number (also known as a repfigit number, short for "repetitive
4+
Fibonacci-like digit") is a natural number n with d >= 2 decimal digits
5+
such that when a sequence is formed starting with the d digits of n and each
6+
subsequent term is the sum of the preceding d terms, the number n itself
7+
appears in the sequence.
8+
9+
For example, 197 is a 3-digit number (d = 3):
10+
Initial terms: 1, 9, 7
11+
Next term: 1 + 9 + 7 = 17
12+
Next term: 9 + 7 + 17 = 33
13+
Next term: 7 + 17 + 33 = 57
14+
Next term: 17 + 33 + 57 = 107
15+
Next term: 33 + 57 + 107 = 197 (Matches 197! So 197 is a Keith number).
16+
17+
The first few Keith numbers are:
18+
14, 19, 28, 47, 61, 75, 197, 742, 1104, 1537, 2208, 2580, 3684, 4788, 7385...
19+
20+
References:
21+
- https://en.wikipedia.org/wiki/Keith_number
22+
- https://oeis.org/A007629
23+
"""
24+
25+
from collections import deque
26+
27+
28+
def is_keith_number(number: int) -> bool:
29+
"""
30+
Check if a given integer is a Keith number.
31+
32+
A Keith number is an integer greater than or equal to 10 that appears
33+
in the Fibonacci-like sequence generated by its digits. Single-digit
34+
numbers are excluded by mathematical convention.
35+
36+
Complexity Analysis:
37+
- Time Complexity: O(d * k) where d is the number of digits of number
38+
and k is the number of terms until the sequence reaches or exceeds
39+
the number. Since the terms grow exponentially, k = O(log(number)).
40+
- Space Complexity: O(d) auxiliary space to store the previous d terms.
41+
42+
Args:
43+
number: The integer to test.
44+
45+
Returns:
46+
True if number is a Keith number, False otherwise.
47+
48+
Raises:
49+
TypeError: If number is not an integer.
50+
51+
Examples:
52+
Known 2-digit Keith numbers:
53+
>>> is_keith_number(14)
54+
True
55+
>>> is_keith_number(19)
56+
True
57+
>>> is_keith_number(28)
58+
True
59+
>>> is_keith_number(47)
60+
True
61+
>>> is_keith_number(61)
62+
True
63+
>>> is_keith_number(75)
64+
True
65+
66+
Known 3-digit and 4-digit Keith numbers:
67+
>>> is_keith_number(197)
68+
True
69+
>>> is_keith_number(742)
70+
True
71+
>>> is_keith_number(1104)
72+
True
73+
>>> is_keith_number(1537)
74+
True
75+
76+
Non-Keith numbers:
77+
>>> is_keith_number(10)
78+
False
79+
>>> is_keith_number(12)
80+
False
81+
>>> is_keith_number(25)
82+
False
83+
>>> is_keith_number(100)
84+
False
85+
86+
Edge cases (single-digit and non-positive integers):
87+
>>> is_keith_number(9)
88+
False
89+
>>> is_keith_number(1)
90+
False
91+
>>> is_keith_number(0)
92+
False
93+
>>> is_keith_number(-14)
94+
False
95+
96+
Type validation:
97+
>>> is_keith_number(14.0)
98+
Traceback (most recent call last):
99+
...
100+
TypeError: number must be an integer
101+
>>> is_keith_number("14")
102+
Traceback (most recent call last):
103+
...
104+
TypeError: number must be an integer
105+
>>> is_keith_number(True)
106+
Traceback (most recent call last):
107+
...
108+
TypeError: number must be an integer
109+
>>> is_keith_number(None)
110+
Traceback (most recent call last):
111+
...
112+
TypeError: number must be an integer
113+
"""
114+
if not isinstance(number, int) or isinstance(number, bool):
115+
raise TypeError("number must be an integer")
116+
117+
if number < 10:
118+
return False
119+
120+
digits = [int(digit) for digit in str(number)]
121+
window = deque(digits)
122+
current_sum = sum(digits)
123+
124+
while current_sum < number:
125+
oldest = window.popleft()
126+
window.append(current_sum)
127+
# Update rolling sum in O(1)
128+
current_sum = 2 * current_sum - oldest
129+
130+
return current_sum == number
131+
132+
133+
def find_keith_numbers(limit: int) -> list[int]:
134+
"""
135+
Find and return all Keith numbers up to a specified limit.
136+
137+
Complexity Analysis:
138+
- Time Complexity: O(limit * log(limit))
139+
- Space Complexity: O(k) where k is the number of Keith numbers found.
140+
141+
Args:
142+
limit: The upper bound (inclusive) up to which to search for Keith numbers.
143+
144+
Returns:
145+
A list of Keith numbers less than or equal to limit.
146+
147+
Raises:
148+
TypeError: If limit is not an integer.
149+
ValueError: If limit is less than 10.
150+
151+
Examples:
152+
>>> find_keith_numbers(100)
153+
[14, 19, 28, 47, 61, 75]
154+
>>> find_keith_numbers(200)
155+
[14, 19, 28, 47, 61, 75, 197]
156+
>>> find_keith_numbers(10)
157+
[]
158+
159+
Type and value errors:
160+
>>> find_keith_numbers(9)
161+
Traceback (most recent call last):
162+
...
163+
ValueError: limit must be an integer greater than or equal to 10
164+
>>> find_keith_numbers(10.5)
165+
Traceback (most recent call last):
166+
...
167+
TypeError: limit must be an integer
168+
>>> find_keith_numbers(False)
169+
Traceback (most recent call last):
170+
...
171+
TypeError: limit must be an integer
172+
"""
173+
if not isinstance(limit, int) or isinstance(limit, bool):
174+
raise TypeError("limit must be an integer")
175+
if limit < 10:
176+
raise ValueError("limit must be an integer greater than or equal to 10")
177+
178+
return [num for num in range(10, limit + 1) if is_keith_number(num)]
179+
180+
181+
if __name__ == "__main__":
182+
import doctest
183+
184+
doctest.testmod()

‎maths/zellers_congruence.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import argparse
2-
import datetime
2+
from datetime import date
33

44

55
def zeller(date_input: str) -> str:
@@ -119,8 +119,8 @@ def zeller(date_input: str) -> str:
119119
"Year out of range. There has to be some sort of limit...right?"
120120
)
121121

122-
# Get datetime obj for validation
123-
dt_ck = datetime.date(int(y), int(m), int(d))
122+
# Get date obj for validation
123+
dt_ck = date(int(y), int(m), int(d))
124124

125125
# Start math
126126
if m <= 2:

0 commit comments

Comments
 (0)