From 06932546bd3411b84e1d9de5b6045276ce1f3b93 Mon Sep 17 00:00:00 2001 From: tom4649 Date: Sat, 20 Jun 2026 06:56:24 +0900 Subject: [PATCH] step1,2,3 --- 0227.Basic-Calculator-II/memo.md | 39 ++++++++++++ 0227.Basic-Calculator-II/step1.py | 60 +++++++++++++++++++ 0227.Basic-Calculator-II/step2.py | 26 ++++++++ .../step2_error_handling.py | 36 +++++++++++ 0227.Basic-Calculator-II/step2_parsing.py | 47 +++++++++++++++ 0227.Basic-Calculator-II/step3_parsing.py | 47 +++++++++++++++ 6 files changed, 255 insertions(+) create mode 100644 0227.Basic-Calculator-II/memo.md create mode 100644 0227.Basic-Calculator-II/step1.py create mode 100644 0227.Basic-Calculator-II/step2.py create mode 100644 0227.Basic-Calculator-II/step2_error_handling.py create mode 100644 0227.Basic-Calculator-II/step2_parsing.py create mode 100644 0227.Basic-Calculator-II/step3_parsing.py diff --git a/0227.Basic-Calculator-II/memo.md b/0227.Basic-Calculator-II/memo.md new file mode 100644 index 0000000..3aec848 --- /dev/null +++ b/0227.Basic-Calculator-II/memo.md @@ -0,0 +1,39 @@ +# 227. Basic Calculator II + +## step1 +とりあえず答えを合わせるために書き上げたもの: step1。これでも文法ミスなどで25mほどかかった。 + +確認: // -> 常に小さい方向に丸める, int(・ / ・) -> 小数点以下を切り捨て + +## 他の人のコード + +https://leetcode.com/problems/basic-calculator-ii/solutions/7632696/a-simple-solution-by-santhanapandis-5vtt/ + +最後に番兵として "+" を足す + +https://github.com/potrue/leetcode/pull/64 + +## step2 + +無駄が多いので書き直す。一巡目で+-も処理できる。 + +さらに例外処理を追加。 + +再帰下構文解析で書く。 + +空ではかけず以下の自分の解法を見ながら書いた。 + +https://leetcode.com/problems/basic-calculator/description/ + + +以下の文法に従う + +``` +expr := term [ ('+' or '-') term ]* +term := factor [ ('*' or '/') factor ]* +factor := digit+ +``` + +## step3 + +再帰下構文解析を練習する diff --git a/0227.Basic-Calculator-II/step1.py b/0227.Basic-Calculator-II/step1.py new file mode 100644 index 0000000..17fed61 --- /dev/null +++ b/0227.Basic-Calculator-II/step1.py @@ -0,0 +1,60 @@ +class Solution: + def calculate(self, s: str) -> int: + def parse_number(left): + number = 0 + right = left + while right < len(s) and s[right].isdigit(): + right += 1 + + return s[left:right], right + + operator_to_func = { + "*": lambda ops: ops[0] * ops[1], + "/": lambda ops: ops[0] // ops[1], + } + + to_be_calculated = [] + i = 0 + result = 0 + sign = 1 + while i < len(s): + if s[i] == " ": + i += 1 + elif s[i].isdigit(): + number, i = parse_number(i) + to_be_calculated.append(number) + elif s[i] in ["*", "/"]: + operator = s[i] + op1 = to_be_calculated.pop() + i += 1 + while s[i] == " ": + i += 1 + assert s[i].isdigit(), s[i] + op2, i = parse_number(i) + number = operator_to_func[operator]((int(op1), int(op2))) + to_be_calculated.append(str(number)) + elif s[i] in ["+", "-"]: + to_be_calculated.append(s[i]) + i += 1 + else: + raise RuntimeError("invalid input") + + result = 0 + sign = 1 + number = 0 + i = 0 + print(to_be_calculated) + while i < len(to_be_calculated): + if to_be_calculated[i].isdigit(): + result += int(to_be_calculated[i]) * sign + i += 1 + elif to_be_calculated[i] == "+": + sign = 1 + i += 1 + elif to_be_calculated[i] == "-": + sign = -1 + i += 1 + else: + raise RuntimeError("invalid input") + + return result diff --git a/0227.Basic-Calculator-II/step2.py b/0227.Basic-Calculator-II/step2.py new file mode 100644 index 0000000..71a948c --- /dev/null +++ b/0227.Basic-Calculator-II/step2.py @@ -0,0 +1,26 @@ +class Solution: + def calculate(self, s: str) -> int: + stack = [] + number = 0 + op = "+" + + i = 0 + while i < len(s): + if s[i].isdigit(): + number = number * 10 + int(s[i]) + + if s[i] in ["+", "-", "*", "/"] or i == len(s): + if op == "+": + stack.append(number) + elif op == "-": + stack.append(-number) + elif op == "*": + stack.append(stack.pop() * number) + elif op == "/": + stack.append(int(stack.pop() / number)) + op = s[i] + number = 0 + + i += 1 + + return sum(stack) diff --git a/0227.Basic-Calculator-II/step2_error_handling.py b/0227.Basic-Calculator-II/step2_error_handling.py new file mode 100644 index 0000000..9e0fb60 --- /dev/null +++ b/0227.Basic-Calculator-II/step2_error_handling.py @@ -0,0 +1,36 @@ +class Solution: + def calculate(self, s: str) -> int: + stack = [] + number = 0 + op = "+" + + i = 0 + expect_number = True + + while i < len(s): + if i != len(s) - 1 and s[i] == " ": + i += 1 + continue + elif s[i].isdigit(): + number = number * 10 + int(s[i]) + expect_number = False + elif expect_number or s[i] not in ["+", "-", "*", "/", " "]: + raise ValueError(f"invalid input: {s[i]}") + + if s[i] in ["+", "-", "*", "/"] or i == len(s) - 1: + if op == "+": + stack.append(number) + elif op == "-": + stack.append(-number) + elif op == "*": + stack.append(stack.pop() * number) + elif op == "/": + if number == 0: + raise ZeroDivisionError("Division by zero") + stack.append(int(stack.pop() / number)) + op = s[i] + number = 0 + expect_number = True + i += 1 + + return sum(stack) diff --git a/0227.Basic-Calculator-II/step2_parsing.py b/0227.Basic-Calculator-II/step2_parsing.py new file mode 100644 index 0000000..48461ea --- /dev/null +++ b/0227.Basic-Calculator-II/step2_parsing.py @@ -0,0 +1,47 @@ +""" +expr := term [ ('+' or '-') term ]* +term := factor [ ('*' or '/') factor ]* +factor := digit+ +""" + + +class Solution: + def calculate(self, s: str) -> int: + s = s.replace(" ", "") + index = 0 + + def expr(): + nonlocal index + result = term() + while index < len(s) and s[index] in ["+", "-"]: + op = s[index] + index += 1 + if op == "+": + result += term() + else: + result -= term() + + return result + + def term(): + nonlocal index + result = factor() + while index < len(s) and s[index] in ["*", "/"]: + op = s[index] + index += 1 + if op == "*": + result *= factor() + else: + result = int(result / factor()) + + return result + + def factor(): + nonlocal index + result = 0 + while index < len(s) and s[index].isdigit(): + result = result * 10 + int(s[index]) + index += 1 + return result + + return expr() diff --git a/0227.Basic-Calculator-II/step3_parsing.py b/0227.Basic-Calculator-II/step3_parsing.py new file mode 100644 index 0000000..e898e1f --- /dev/null +++ b/0227.Basic-Calculator-II/step3_parsing.py @@ -0,0 +1,47 @@ +""" +expr := term [ ('+' or '-') term ]* +term := factor [ ('*' or '/') factor ]* +factor := digit+ +""" + + +class Solution: + def calculate(self, s: str) -> int: + s = s.replace(" ", "") + index = 0 + + def expr(): + nonlocal index + result = term() + while index < len(s) and s[index] in ("+", "-"): + op = s[index] + index += 1 + if op == "+": + result += term() + else: + result -= term() + + return result + + def term(): + nonlocal index + result = factor() + while index < len(s) and s[index] in ("*", "/"): + op = s[index] + index += 1 + if op == "*": + result *= factor() + else: + result = int(result / factor()) + + return result + + def factor(): + nonlocal index + result = 0 + while index < len(s) and s[index].isdigit(): + result = result * 10 + int(s[index]) + index += 1 + return result + + return expr()