Skip to content

Commit 01138f3

Browse files
committed
8/19/23 - Clemson dropoff, trip up and back
- convert_base.py (solved recursively and iteratively)
1 parent d66a93c commit 01138f3

File tree

2 files changed

+75
-29
lines changed

2 files changed

+75
-29
lines changed

elements-of-programming-interviews/python/convert_base.py

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,45 +14,33 @@
1414
- Ex: convert "12345" to int 12345
1515
- add each digit, then multiply total by 10.
1616
"""
17+
import functools
18+
import string
1719

18-
# easier to read than ord()/chr()
19-
CHAR_AS_NUM = {str(i): i for i in range(10)} | {'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15}
2020
NUM_AS_CHAR = "0123456789ABCDEF"
2121

2222

23-
def to_new_base(num: int, b2: int) -> str:
24-
if num == 0:
25-
return "0"
26-
val = ""
27-
while num:
28-
remainder = num % b2
29-
val = NUM_AS_CHAR[remainder] + val # prepend the new digit
30-
num //= b2
31-
return val
32-
33-
34-
def to_base_ten(num_as_string: str, b1: int) -> int:
35-
total = 0
36-
place = 1
37-
for c in num_as_string[::-1]:
38-
total += (CHAR_AS_NUM[c] * place)
39-
place *= b1
40-
return total
41-
42-
4323
def convert_base(num_as_string: str, b1: int, b2: int) -> str:
44-
if not num_as_string:
45-
return ""
46-
neg = num_as_string[0] == '-'
47-
num_as_string = num_as_string[1:] if neg else num_as_string
24+
# Assuming 2 <= b1,b2 <= 16
25+
if num_as_string in ["", "0"]:
26+
return num_as_string
27+
neg = num_as_string[0] == "-"
28+
29+
num_as_int = functools.reduce(
30+
lambda x, c: x * b1 + string.hexdigits.index(c.lower()),
31+
num_as_string[neg:], 0)
4832

49-
num_base_10 = to_base_ten(num_as_string, b1)
50-
num_b2 = to_new_base(num_base_10, b2)
33+
def recurse(num_as_int, b2):
34+
if num_as_int == 0:
35+
return ""
36+
remainder = num_as_int % b2
37+
return recurse(num_as_int // b2, b2) + NUM_AS_CHAR[remainder]
5138

52-
return ("-" if neg else "") + num_b2
39+
return ("-" if neg else "") + recurse(num_as_int, b2)
5340

5441

5542
if __name__ == '__main__':
43+
print(convert_base("1234", 10, 5))
5644
exit(
5745
generic_test.generic_test_main('convert_base.py', 'convert_base.tsv',
5846
convert_base))
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from test_framework import generic_test
2+
3+
"""
4+
- Bases can be between 2 and 16
5+
- Can be empty?
6+
- Can exceed integer limits (not issue for python)
7+
- Negatives
8+
- num_as_string[0] is most sig fig
9+
- 0 and 1 are always valid; A = 10, ..., F = 15
10+
11+
Input: string representing num in b1
12+
Output: string representing num in b2
13+
14+
- Ex: convert "12345" to int 12345
15+
- add each digit, then multiply total by 10.
16+
"""
17+
18+
# easier to read than ord()/chr()
19+
CHAR_AS_NUM = {str(i): i for i in range(10)} | {'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15}
20+
NUM_AS_CHAR = "0123456789ABCDEF"
21+
22+
23+
def to_new_base(num: int, b2: int) -> str:
24+
if num == 0:
25+
return "0"
26+
val = ""
27+
while num:
28+
remainder = num % b2
29+
val = NUM_AS_CHAR[remainder] + val # prepend the new digit
30+
num //= b2
31+
return val
32+
33+
34+
def to_base_ten(num_as_string: str, b1: int) -> int:
35+
total = 0
36+
place = 1
37+
for c in num_as_string[::-1]:
38+
total += (CHAR_AS_NUM[c] * place)
39+
place *= b1
40+
return total
41+
42+
43+
def convert_base(num_as_string: str, b1: int, b2: int) -> str:
44+
if not num_as_string:
45+
return ""
46+
neg = num_as_string[0] == '-'
47+
num_as_string = num_as_string[1:] if neg else num_as_string
48+
49+
num_base_10 = to_base_ten(num_as_string, b1)
50+
num_b2 = to_new_base(num_base_10, b2)
51+
52+
return ("-" if neg else "") + num_b2
53+
54+
55+
if __name__ == '__main__':
56+
exit(
57+
generic_test.generic_test_main('convert_base.py', 'convert_base.tsv',
58+
convert_base))

0 commit comments

Comments
 (0)