Conversation
| next_digit = sign * (ord(s[index]) - ord('0')) | ||
| if num > (MAX_INT - next_digit) // 10: | ||
| return MAX_INT | ||
| if num < (MIN_INT - next_digit) // 10 + 1: |
There was a problem hiding this comment.
if num <= (MIN_INT - next_digit) // 10:でも動きますかね?
There was a problem hiding this comment.
そうですね。ただ、自分の意図としては上と同じように超えた時に丸めるという意味合いが重要と思っているのでこうしてます
| ```python | ||
| class Solution: | ||
| def myAtoi(self, s: str) -> int: | ||
| index = 0 |
There was a problem hiding this comment.
if s is None:
return 0Noneの時の処理を入れたくなりました
| def ch_to_i(ch: str) -> int: | ||
| return ord(ch) - ord('0') | ||
|
|
||
| self.index = 0 |
There was a problem hiding this comment.
インスタンス変数を変更すると、複数のスレッドで同時にこの関数を読んだときに競合状態が起こると思います。現実的なコストで避けられる場合は、避けたほうが無難だと思います。
| def ch_to_i(ch: str) -> int: | ||
| return ord(ch) - ord('0') | ||
|
|
||
| self.index = 0 |
There was a problem hiding this comment.
ステートマシン風に書きたかったのかなと思いました。以下のような書き方もあります。
import enum
class State(enum.Enum):
WHITESPACE = 1
SIGN = 2
ZERO = 3
INT = 4
END = 5
MAX_INT = (1 << 31) - 1
MIN_INT = -(1 << 31)
class Solution:
def myAtoi(self, s: str) -> int:
def parse_whitespace(index: int) -> tuple[State, int]:
if s[index] == ' ':
return State.WHITESPACE, index + 1
return State.SIGN, index
def parse_sign(index: int) -> tuple[State, int, int]:
if s[index] == '+':
return State.ZERO, index + 1, 1
if s[index] == '-':
return State.ZERO, index + 1, -1
return State.ZERO, index, 1
def parse_zero(index) -> tuple[State, int]:
if s[index] == '0':
return State.ZERO, index + 1
if s[index] in string.digits:
return State.INT, index
return State.END, len(s)
def parse_int(index, sign, num) -> tuple[State, int, int]:
if s[index] not in string.digits:
return State.END, len(s), num
if num > (MAX_INT - ch_to_i(s[index])) // 10:
return State.END, len(s), MAX_INT
if num < (MIN_INT + ch_to_i(s[index])) // 10 + 1:
return State.END, len(s), MIN_INT
return State.INT, index + 1, num * 10 + sign * ch_to_i(s[index])
def ch_to_i(ch: str) -> int:
return ord(ch) - ord('0')
index = 0
state = State.WHITESPACE
sign = 1
num = 0
while index < len(s):
match state:
case State.WHITESPACE:
state, index = parse_whitespace(index)
case State.SIGN:
state, index, sign = parse_sign(index)
case State.ZERO:
state, index = parse_zero(index)
case State.INT:
state, index, num = parse_int(index, sign, num)
case State.END:
break
return numThere was a problem hiding this comment.
確かにこういう書き方もありですね。
参考になります
|
|
||
| while index < len(s): | ||
| if s[index] in NUMBERS: | ||
| if sign == POSITIVE and (MAX_INT - int(s[index])) // 10 - num < 0: |
There was a problem hiding this comment.
Python では int は多倍長整数で実装されているため、 32/64-bit のオーバーフローしません。そのため、計算してから範囲を超えたかどうかを判定しても大丈夫です。そのほうがコードがシンプルになると思います。
num = num * 10 + int(s[index])
if sign == POSITIVE and MAX_INT < num:
return MAX_INT
if sign == NEGATIVE and -num < MIN_INT:
return MIN_INT
index += 1
There was a problem hiding this comment.
もちろん承知の上ですが、その処理をして欲しい問題なのかなと思って書きました
(MAX_INTの定義で越えてるという話はありそうですが)
There was a problem hiding this comment.
他の(オーバーフローが)問題になるような言語だと、標準ライブラリーにそういう関数があることが多いというのも意識してもいいかもしれません。
まあ、要は自分で作らないべきものであるということです。
| index = 0 | ||
| while index < len(s): | ||
| if s[index] != ' ': | ||
| break |
There was a problem hiding this comment.
while index < len(s) and s[index] == ' ':としてもいいと思いました。
問題文:https://leetcode.com/problems/string-to-integer-atoi/description/