More fun with roman numbers
This commit is contained in:
parent
accf0d0c2b
commit
5b55118373
@ -78,12 +78,12 @@ all = [
|
||||
|
||||
[tool.black]
|
||||
target-version = ["py37"]
|
||||
line-length = 120
|
||||
line-length = 90
|
||||
skip-string-normalization = true
|
||||
|
||||
[tool.ruff]
|
||||
target-version = "py37"
|
||||
line-length = 120
|
||||
line-length = 90
|
||||
select = [
|
||||
"A",
|
||||
"ARG",
|
||||
|
@ -36,7 +36,9 @@ def gen_sqrt_check(n: int) -> typing.Callable[[float], int]:
|
||||
return check
|
||||
|
||||
|
||||
def find_bisect(lower: float, upper: float, check: typing.Callable[[float], int]) -> float:
|
||||
def find_bisect(
|
||||
lower: float, upper: float, check: typing.Callable[[float], int]
|
||||
) -> float:
|
||||
mid: float = lower + ((upper - lower) / 2)
|
||||
|
||||
print(f"lower={lower} mid={mid} upper={upper}")
|
||||
@ -72,3 +74,64 @@ def cartesian_path(p0: tuple[int, int], p1: tuple[int, int]) -> list[tuple[int,
|
||||
|
||||
def gen_matrix(width: int, height: int) -> list[list[int]]:
|
||||
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:
|
||||
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
|
||||
|
@ -16,3 +16,15 @@ import stuff
|
||||
)
|
||||
def test_find_sqrt_ish(n: int, expected: int):
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user