Skip to content

Conversation

@Satorien
Copy link
Owner

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:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if num <= (MIN_INT - next_digit) // 10:

でも動きますかね?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうですね。ただ、自分の意図としては上と同じように超えた時に丸めるという意味合いが重要と思っているのでこうしてます

```python
class Solution:
def myAtoi(self, s: str) -> int:
index = 0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if s is None:
        return 0

Noneの時の処理を入れたくなりました

def ch_to_i(ch: str) -> int:
return ord(ch) - ord('0')

self.index = 0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

インスタンス変数を変更すると、複数のスレッドで同時にこの関数を読んだときに競合状態が起こると思います。現実的なコストで避けられる場合は、避けたほうが無難だと思います。

def ch_to_i(ch: str) -> int:
return ord(ch) - ord('0')

self.index = 0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ステートマシン風に書きたかったのかなと思いました。以下のような書き方もあります。

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 num

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確かにこういう書き方もありですね。
参考になります


while index < len(s):
if s[index] in NUMBERS:
if sign == POSITIVE and (MAX_INT - int(s[index])) // 10 - num < 0:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

もちろん承知の上ですが、その処理をして欲しい問題なのかなと思って書きました
(MAX_INTの定義で越えてるという話はありそうですが)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

他の(オーバーフローが)問題になるような言語だと、標準ライブラリーにそういう関数があることが多いというのも意識してもいいかもしれません。
まあ、要は自分で作らないべきものであるということです。

index = 0
while index < len(s):
if s[index] != ' ':
break
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while index < len(s) and s[index] == ' ':としてもいいと思いました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants