Move roman bits

This commit is contained in:
Dan Buch 2023-10-24 15:48:15 -04:00
parent ffb16efcdc
commit 8cc2e18965
Signed by: meatballhat
GPG Key ID: A12F782281063434
4 changed files with 72 additions and 76 deletions

57
leetcode/roman.py Normal file
View File

@ -0,0 +1,57 @@
SIMPLE = {
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000,
}
SIMPLE_REVERSE = {v: k for k, v in SIMPLE.items()}
COMPOUND = {
"IV": 4,
"IX": 9,
"XL": 40,
"XC": 90,
"CD": 400,
"CM": 900,
}
PREFIXES = {k[0] for k in COMPOUND.keys()}
COMPOUND_REVERSE = {v: k for k, v in COMPOUND.items()}
ALL = SIMPLE | COMPOUND
ALL_REVERSE = {v: k for k, v in ALL.items()}
def i2r(i: int) -> str:
if i > 100_000:
raise ValueError(f"{i} is too silly")
r: list[str] = []
for int_val, roman_val in sorted(ALL_REVERSE.items(), reverse=True):
remainder = i % int_val
r += [roman_val] * int((i - remainder) / int_val)
i = remainder
return "".join(r)
def r2i(r: str) -> int:
total = 0
offset = 0
for i in range(len(r)):
if i + offset > len(r) - 1:
break
c = r[i + offset]
if c in PREFIXES and (i + offset + 1) < len(r) and c + r[i + offset + 1] in ALL:
total += ALL[c + r[i + offset + 1]]
offset += 1
continue
total += ALL[c]
return total

View File

@ -79,70 +79,6 @@ def gen_matrix(width: int, height: int) -> list[list[int]]:
return [list(range(width)) for _ in range(height)] return [list(range(width)) for _ in range(height)]
class Roman:
SIMPLE = {
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000,
}
SIMPLE_REVERSE = {v: k for k, v in SIMPLE.items()}
COMPOUND = {
"IV": 4,
"IX": 9,
"XL": 40,
"XC": 90,
"CD": 400,
"CM": 900,
}
PREFIXES = {k[0] for k in COMPOUND.keys()}
COMPOUND_REVERSE = {v: k for k, v in COMPOUND.items()}
ALL = SIMPLE | COMPOUND
ALL_REVERSE = {v: k for k, v in ALL.items()}
@classmethod
def i2r(cls, i: int) -> str:
if i > 100_000:
raise ValueError(f"{i} is too silly")
r: list[str] = []
for int_val, roman_val in sorted(cls.ALL_REVERSE.items(), reverse=True):
remainder = i % int_val
r += [roman_val] * int((i - remainder) / int_val)
i = remainder
return "".join(r)
@classmethod
def r2i(cls, r: str) -> int:
total = 0
offset = 0
for i in range(len(r)):
if i + offset > len(r) - 1:
break
c = r[i + offset]
if (
c in cls.PREFIXES
and (i + offset + 1) < len(r)
and c + r[i + offset + 1] in cls.ALL
):
total += cls.ALL[c + r[i + offset + 1]]
offset += 1
continue
total += cls.ALL[c]
return total
class MinStack: class MinStack:
def __init__(self): def __init__(self):
self._v: list[int] = [] self._v: list[int] = []

15
leetcode/test_roman.py Normal file
View File

@ -0,0 +1,15 @@
import pytest
import roman
@pytest.mark.parametrize(
("n", "expected"),
[
(3, "III"),
(58, "LVIII"),
(1994, "MCMXCIV"),
],
)
def test_int_to_roman(n: int, expected: str):
assert roman.i2r(n) == expected

View File

@ -19,18 +19,6 @@ def test_find_sqrt_ish(n: int, expected: int):
assert stuff.find_sqrt_ish(n) == expected assert stuff.find_sqrt_ish(n) == expected
@pytest.mark.parametrize(
("n", "expected"),
[
(3, "III"),
(58, "LVIII"),
(1994, "MCMXCIV"),
],
)
def test_int_to_roman(n: int, expected: str):
assert stuff.Roman.i2r(n) == expected
@pytest.mark.parametrize( @pytest.mark.parametrize(
("ops", "expected"), ("ops", "expected"),
[ [