Skip to content

Commit ef92b32

Browse files
authored
Merge pull request #152 from ikostan/main
Merge from master
2 parents 5aec993 + 536e11e commit ef92b32

File tree

6 files changed

+189
-13
lines changed

6 files changed

+189
-13
lines changed

all-your-base/all_your_base.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""
55

66

7-
def rebase(input_base: int, digits: list[int], output_base: int):
7+
def rebase(input_base: int, digits: list[int], output_base: int) -> list[int]:
88
"""
99
Convert a non-negative integer represented as digits in one base
1010
to digits in another base.
@@ -20,16 +20,41 @@ def rebase(input_base: int, digits: list[int], output_base: int):
2020
:raises ValueError: If ``input_base < 2``, if any digit violates
2121
``0 <= d < input_base``, or if ``output_base < 2``.
2222
"""
23-
24-
# for input.
23+
# Step 1: Validate the Inputs (Before Any Calculations)
24+
# Validate input_base >= 2
2525
if input_base < 2:
2626
raise ValueError("input base must be >= 2")
2727

28-
# another example for input.
28+
# Validate each digit is 0 <= d < input_base
2929
for d in digits:
3030
if not 0 <= d < input_base:
3131
raise ValueError("all digits must satisfy 0 <= d < input base")
3232

33-
# or, for output.
33+
# Validate output_base >= 2
3434
if output_base < 2:
3535
raise ValueError("output base must be >= 2")
36+
37+
# Step 2: Calculate the Intermediate Value Using input_base and digits
38+
# Start from the least significant number (from the right in original list)
39+
# -> hence reverse the list
40+
intermediate_val: int = sum(
41+
digit * (input_base**i) for i, digit in enumerate(digits[::-1])
42+
)
43+
44+
# Step 3: Convert the Intermediate Value to digits in output_base
45+
answer: list[int] = []
46+
while True:
47+
# Compute quotient (new intermediate_val)
48+
# and remainder (least significant digit)
49+
intermediate_val, remainder = (
50+
intermediate_val // output_base,
51+
intermediate_val % output_base,
52+
)
53+
# Add the next least significant number into a new list of digits
54+
# Start always from the right
55+
answer.insert(0, remainder)
56+
# Break the loop since reach zero, no more calculation needed
57+
if intermediate_val == 0:
58+
break
59+
60+
return answer
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""
2+
Convert a sequence of digits in one base, representing a number,
3+
into a sequence of digits in another base, representing the same number.
4+
"""
5+
6+
7+
def rebase(input_base: int, digits: list[int], output_base: int):
8+
"""
9+
Convert a non-negative integer represented as digits in one base to digits in another base.
10+
11+
:param int input_base: Base of the input digits; must be >= 2.
12+
:param list[int] digits: Sequence of digits where each d satisfies 0 <= d < input_base.
13+
Leading zeros are allowed; an empty list denotes 0.
14+
:param int output_base: Base for the output digits; must be >= 2.
15+
:returns: Digits of the same number in ``output_base``, without leading zeros
16+
(except ``[0]`` for zero).
17+
:rtype: list[int]
18+
:raises ValueError: If ``input_base < 2``, if any digit violates ``0 <= d < input_base``,
19+
or if ``output_base < 2``.
20+
"""
21+
22+
# for input.
23+
if input_base < 2:
24+
raise ValueError("input base must be >= 2")
25+
26+
# another example for input.
27+
for d in digits:
28+
if not 0 <= d < input_base:
29+
raise ValueError("all digits must satisfy 0 <= d < input base")
30+
31+
# or, for output.
32+
if output_base < 2:
33+
raise ValueError("output base must be >= 2")
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
Convert a sequence of digits in one base, representing a number,
3+
into a sequence of digits in another base, representing the same number.
4+
"""
5+
6+
7+
def rebase(input_base: int, digits: list[int], output_base: int) -> list[int]:
8+
"""
9+
Convert a non-negative integer represented as digits in one base
10+
to digits in another base.
11+
12+
:param int input_base: Base of the input digits; must be >= 2.
13+
:param list[int] digits: Sequence of digits where each d satisfies
14+
0 <= d < input_base. Leading zeros are allowed;
15+
an empty list denotes 0.
16+
:param int output_base: Base for the output digits; must be >= 2.
17+
:returns: Digits of the same number in ``output_base``, without leading
18+
zeros (except ``[0]`` for zero).
19+
:rtype: list[int]
20+
:raises ValueError: If ``input_base < 2``, if any digit violates
21+
``0 <= d < input_base``, or if ``output_base < 2``.
22+
"""
23+
# Step 1: Validate the Inputs (Before Any Calculations)
24+
# Validate input_base >= 2
25+
if input_base < 2:
26+
raise ValueError("input base must be >= 2")
27+
28+
# Validate each digit is 0 <= d < input_base
29+
for d in digits:
30+
if not 0 <= d < input_base:
31+
raise ValueError("all digits must satisfy 0 <= d < input base")
32+
33+
# Validate output_base >= 2
34+
if output_base < 2:
35+
raise ValueError("output base must be >= 2")
36+
37+
# Step 2: Calculate the Intermediate Value Using input_base and digits
38+
# Start from the least significant number (from the right)
39+
# -> hence reverse the list
40+
intermediate_val: int = sum(
41+
digit * (input_base**i) for i, digit in enumerate(reversed(digits))
42+
)
43+
44+
# Step 3: Convert the Intermediate Value to digits in output_base
45+
answer: list[int] = []
46+
while True:
47+
# Compute quotient (new intermediate_val)
48+
# and remainder (least significant digit)
49+
intermediate_val, remainder = (
50+
intermediate_val // output_base,
51+
intermediate_val % output_base,
52+
)
53+
# Add the least significant number into a new list of digits
54+
answer.append(remainder)
55+
# Break the loop since reach zero, no more calculation needed
56+
if intermediate_val == 0:
57+
break
58+
59+
# Reverse the list to place the most significant digit first (leftmost).
60+
return answer[::-1]
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
This exercise stub and the test suite contain several enumerated constants.
3+
4+
Enumerated constants can be done with a NAME assigned to an arbitrary,
5+
but unique value. An integer is traditionally used because it’s memory
6+
efficient.
7+
8+
It is a common practice to export both constants and functions that work with
9+
those constants (ex. the constants in the os, subprocess and re modules).
10+
11+
You can learn more here: https://en.wikipedia.org/wiki/Enumerated_type
12+
"""
13+
14+
# Possible sublist categories.
15+
# Change the values as you see fit.
16+
SUBLIST = 0
17+
SUPERLIST = 1
18+
EQUAL = 2
19+
UNEQUAL = 3
20+
21+
22+
def sublist(list_one: list, list_two: list) -> int:
23+
"""
24+
Classify the relationship between two lists.
25+
26+
Determines whether ``list_one`` and ``list_two`` are equal, or whether one
27+
is a contiguous sublist of the other, and returns the appropriate constant.
28+
29+
:param list_one: First list to compare.
30+
:type list_one: list
31+
:param list_two: Second list to compare.
32+
:type list_two: list
33+
:returns: One of ``EQUAL``, ``SUBLIST``, ``SUPERLIST``, or ``UNEQUAL``.
34+
:rtype: int
35+
"""
36+
37+
if len(list_one) == len(list_two):
38+
if list_one == list_two:
39+
return EQUAL
40+
return UNEQUAL
41+
42+
l1: str = ",".join(str(i) for i in list_one)
43+
l2: str = ",".join(str(i) for i in list_two)
44+
45+
if l2 in l1:
46+
return SUPERLIST
47+
48+
if l1 in l2:
49+
return SUBLIST
50+
51+
return UNEQUAL

sublist/sublist.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,19 @@ def sublist(list_one: list, list_two: list) -> int:
3333
:returns: One of ``EQUAL``, ``SUBLIST``, ``SUPERLIST``, or ``UNEQUAL``.
3434
:rtype: int
3535
"""
36-
37-
len1: int = len(list_one)
38-
len2: int = len(list_two)
39-
40-
if len1 == len2:
36+
# Step #1: test list with same length
37+
if len(list_one) == len(list_two):
4138
if list_one == list_two:
4239
return EQUAL
4340
return UNEQUAL
44-
41+
# Step #2: convert list to a string
4542
l1: str = ",".join(str(i) for i in list_one)
4643
l2: str = ",".join(str(i) for i in list_two)
47-
44+
# Step #3: check for substring
4845
if l2 in l1:
4946
return SUPERLIST
5047

5148
if l1 in l2:
5249
return SUBLIST
53-
50+
# Step #4: Return default
5451
return UNEQUAL

sublist/sublist_test.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,13 @@ def test_spread_sublist(self):
8989
self.assertEqual(
9090
sublist(list(range(3, 200, 3)), list(range(15, 200, 15))), UNEQUAL
9191
)
92+
93+
94+
if __name__ == '__main__':
95+
import time
96+
97+
start_time = time.time()
98+
unittest.main(verbosity=2) # Verbosity=2 for detailed output; adjust if needed
99+
end_time = time.time()
100+
duration = end_time - start_time
101+
print(f"\nAll tests completed in {duration:.4f} seconds.")

0 commit comments

Comments
 (0)