From 2d3c619d2cf2af037550a8db8d8dc4bff01723f5 Mon Sep 17 00:00:00 2001 From: Cal Barkman Date: Fri, 17 Oct 2025 22:47:02 -0700 Subject: [PATCH 1/3] Problem 013 rough cut --- problem_013/solution.py | 83 ++++++++++++++++++++++++++++++++++++ problem_013/test_inputs.json | 17 ++++++++ 2 files changed, 100 insertions(+) create mode 100644 problem_013/solution.py create mode 100644 problem_013/test_inputs.json diff --git a/problem_013/solution.py b/problem_013/solution.py new file mode 100644 index 0000000..0b971c8 --- /dev/null +++ b/problem_013/solution.py @@ -0,0 +1,83 @@ +# Extra header to ensure that tests can run individually and as a suite +# ------------------------------------------------------------------- +import sys +from pathlib import Path +# Add the project root folder to the Python path +sys.path.append(str(Path(__file__).resolve().parents[1])) +# ------------------------------------------------------------------- + +# Now you can import your wrapper +from test_runner.wrapper import run_tests + +class Solution: + def romanToInt(self, s: str) -> int: + str_len = len(s) + retval = 0 + skip = False + temp_retval = 0 + for iter in range(0, str_len): + # When skip is true, we looked ahead one character and know to skip it next time + if(not skip): + if(iter + 1 == str_len): + # only look at one character + debug_str = s[iter] + temp_retval, skip = self.roman_lookup(debug_str + " ") + retval += temp_retval + else: + debug_str = s[iter:iter+2] + temp_retval, skip = self.roman_lookup(debug_str) + retval += temp_retval + else: + skip = False + + return retval + + def roman_lookup(self, char: str): + match char: + # Special I cases + case char if char.startswith("IV"): + return 4, True + case char if char.startswith("IX"): + return 9, True + # Special X cases + case char if char.startswith("XL"): + return 40, True + case char if char.startswith("XC"): + return 90, True + # Special C cases + case char if char.startswith("CD"): + return 400, True + case char if char.startswith("CM"): + return 900, True + # Normal Lookups + case char if char.startswith("I"): + return 1, False + case char if char.startswith("V"): + return 5, False + case char if char.startswith("X"): + return 10, False + case char if char.startswith("L"): + return 50, False + case char if char.startswith("C"): + return 100, False + case char if char.startswith("D"): + return 500, False + case char if char.startswith("M"): + return 1000, False + # Error case? + case _: + print("Somethig went wrong...") + + + + + +if __name__ == "__main__": + # Get the directory where this solution.py script lives + script_dir = Path(__file__).parent + + # Join the script's directory with the JSON filename to create a full path + # Make sure your file is actually named "test_inputs.json"! + test_file_path = script_dir / "test_inputs.json" + + run_tests(Solution, test_file_path) \ No newline at end of file diff --git a/problem_013/test_inputs.json b/problem_013/test_inputs.json new file mode 100644 index 0000000..415032c --- /dev/null +++ b/problem_013/test_inputs.json @@ -0,0 +1,17 @@ +{ + "method": "romanToInt", + "tests": [ + { + "Input": "III", + "Output": "3" + }, + { + "Input": "LVIII", + "Output": "58" + }, + { + "Input": "MCMXCIV", + "Output": "1994" + } + ] +} \ No newline at end of file From a110a8da09b9ce1427e4425fd7c419b4db371ca7 Mon Sep 17 00:00:00 2001 From: Cal Barkman Date: Fri, 17 Oct 2025 22:57:29 -0700 Subject: [PATCH 2/3] A "more pythonic" solution --- problem_013/solution.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/problem_013/solution.py b/problem_013/solution.py index 0b971c8..6cbd8cb 100644 --- a/problem_013/solution.py +++ b/problem_013/solution.py @@ -11,6 +11,10 @@ class Solution: def romanToInt(self, s: str) -> int: + return self.pythonic_solution(s) + return self.match_solution(s) + + def match_solution(self, s: str) -> int: str_len = len(s) retval = 0 skip = False @@ -29,7 +33,6 @@ def romanToInt(self, s: str) -> int: retval += temp_retval else: skip = False - return retval def roman_lookup(self, char: str): @@ -68,9 +71,28 @@ def roman_lookup(self, char: str): case _: print("Somethig went wrong...") + def pythonic_solution(self, s: str) -> int: + # Lookup map + roman_map = { + 'I': 1, + 'V': 5, + 'X': 10, + 'L': 50, + 'C': 100, + 'D': 500, + 'M': 1000 + } - + total = 0 + for iter in range(len(s)): + # Check that there is more than 1 character left AND + # make sure that the next character is not BIGGER than the current character. + if iter + 1 < len(s) and roman_map[s[iter]] < roman_map[s[iter+1]]: + total -= roman_map[s[iter]] + else: + total += roman_map[s[iter]] + return total if __name__ == "__main__": # Get the directory where this solution.py script lives From 0ddd7ca1673320a5de3659805417dedabb73d8b7 Mon Sep 17 00:00:00 2001 From: Cal Barkman Date: Fri, 17 Oct 2025 23:01:03 -0700 Subject: [PATCH 3/3] Add better comments. --- problem_013/solution.py | 1 + 1 file changed, 1 insertion(+) diff --git a/problem_013/solution.py b/problem_013/solution.py index 6cbd8cb..db9d265 100644 --- a/problem_013/solution.py +++ b/problem_013/solution.py @@ -88,6 +88,7 @@ def pythonic_solution(self, s: str) -> int: # Check that there is more than 1 character left AND # make sure that the next character is not BIGGER than the current character. if iter + 1 < len(s) and roman_map[s[iter]] < roman_map[s[iter+1]]: + # If this is a pre-pended character that needs special conversion (like IV) just subtract that number before moving to the next character and adding it. If we say x = IV it's the same as saying x = -1, x = x + 5 total -= roman_map[s[iter]] else: total += roman_map[s[iter]]