From f2d1bc24b93e307f26fc2973fe01c0a6e0ab4cdd Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 2 Apr 2024 00:34:52 +0900 Subject: [PATCH 1/9] Create 8. String to Integer (atoi).md --- 8. String to Integer (atoi).md | 1 + 1 file changed, 1 insertion(+) create mode 100644 8. String to Integer (atoi).md diff --git a/8. String to Integer (atoi).md b/8. String to Integer (atoi).md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/8. String to Integer (atoi).md @@ -0,0 +1 @@ + From 6e33c001dfbd4b5e91d1c4ba798004bc515ccd10 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 2 Apr 2024 12:19:53 +0900 Subject: [PATCH 2/9] Update 8. String to Integer (atoi).md --- 8. String to Integer (atoi).md | 60 ++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/8. String to Integer (atoi).md b/8. String to Integer (atoi).md index 8b13789..7ef0d12 100644 --- a/8. String to Integer (atoi).md +++ b/8. String to Integer (atoi).md @@ -1 +1,61 @@ +文字を1文字ずつ読み進めれば良い。フェーズとしては以下の3つ +- 空白を無視して読み進める。 +- 符号を判定する +- 数値を読んでいく +INT_MAX, INT_MINを超えたらそこで終了する。Pythonのintは理論上は上限がないので途中のオーバーフローなどは考えなくて良い。 +CやC++で実装する場合でも32bitより大きい型(long)を確保してあげれば考えなくて良くなる。32bitでやる場合は、桁上りの計算をする前にオーバーフローするかどうかを判定する必要がある。 + +> Integers have unlimited precision. +https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex + +1st + +isdigitの実装は https://github.com/python/cpython/blob/2305ca51448552542b2414186252123a8dc87db7/Lib/curses/ascii.py#L59 +空白の判定には、`str.isspace()`も使用できる。LeetCodeの要件的には`' '`との比較だけで良い。 + +```python +class Solution: + def myAtoi(self, s: str) -> int: + def skip_white_spaces(): + index = 0 + while index < len(s) and s[index] == ' ': + index += 1 + return index + + def get_sign(begin): + index = begin + if index == len(s): + return index, 1 + if s[index] == '-': + return index + 1, -1 + if s[index] == '+': + return index + 1, 1 + return index, 1 + + index = skip_white_spaces() + index, sign = get_sign(index) + + INT_MAX = (1 << 31) - 1 + INT_MIN = - INT_MAX - 1 + + number = 0 + while index < len(s) and s[index].isdigit(): + digit = ord(s[index]) - ord('0') + number = number * 10 + sign * digit + if number >= INT_MAX: + return INT_MAX + if number <= INT_MIN: + return INT_MIN + index += 1 + return number +``` + +2nd +```python +``` + + +3rd +```python +``` From a87b9c895114b8d223c0e0c68325d3c3cd841720 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 2 Apr 2024 12:21:08 +0900 Subject: [PATCH 3/9] Update 8. String to Integer (atoi).md --- 8. String to Integer (atoi).md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/8. String to Integer (atoi).md b/8. String to Integer (atoi).md index 7ef0d12..7762c61 100644 --- a/8. String to Integer (atoi).md +++ b/8. String to Integer (atoi).md @@ -4,9 +4,10 @@ - 数値を読んでいく INT_MAX, INT_MINを超えたらそこで終了する。Pythonのintは理論上は上限がないので途中のオーバーフローなどは考えなくて良い。 -CやC++で実装する場合でも32bitより大きい型(long)を確保してあげれば考えなくて良くなる。32bitでやる場合は、桁上りの計算をする前にオーバーフローするかどうかを判定する必要がある。 +CやC++で実装する場合でも32bitより大きい型(long)を確保してあげれば考えなくて良くなる。← ただlongの場合のオーバーフローの考慮などどこかではちゃんと考慮しないといけない。その場合は、桁上りの計算をする前にオーバーフローするかどうかを判定すれば良い。 > Integers have unlimited precision. + https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex 1st From 6b8e4890f6dc631506a383da66b40509f54f54d8 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 2 Apr 2024 12:33:36 +0900 Subject: [PATCH 4/9] Update 8. String to Integer (atoi).md --- 8. String to Integer (atoi).md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/8. String to Integer (atoi).md b/8. String to Integer (atoi).md index 7762c61..adc6c76 100644 --- a/8. String to Integer (atoi).md +++ b/8. String to Integer (atoi).md @@ -12,7 +12,7 @@ https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex 1st -isdigitの実装は https://github.com/python/cpython/blob/2305ca51448552542b2414186252123a8dc87db7/Lib/curses/ascii.py#L59 +isdigitの実装は https://github.com/python/cpython/blob/2305ca51448552542b2414186252123a8dc87db7/Objects/bytes_methods.c#L154 空白の判定には、`str.isspace()`も使用できる。LeetCodeの要件的には`' '`との比較だけで良い。 ```python From 6ef0062584768f319591e1f0a0d4e3510ebd58d7 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 2 Apr 2024 21:10:33 +0900 Subject: [PATCH 5/9] Update 8. String to Integer (atoi).md --- 8. String to Integer (atoi).md | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/8. String to Integer (atoi).md b/8. String to Integer (atoi).md index adc6c76..a7c2176 100644 --- a/8. String to Integer (atoi).md +++ b/8. String to Integer (atoi).md @@ -53,7 +53,45 @@ class Solution: ``` 2nd + +桁上りの掛け算をする前にオーバーフローの判定をする版。あと関数に切り出さずに書いた。処理が素直に上から下に流れるので関数に切り出さなくても大丈夫かも。 +むしろposを取り回している分切り出すと逆に分かりづらいかもしれない。 + ```python +class Solution: + def myAtoi(self, s: str) -> int: + pos = 0 + # 空白をskipする + while pos < len(s) and s[pos].isspace(): + pos += 1 + if pos == len(s): + return 0 + # 符号の判定 + sign = 1 + if s[pos] == '+' or s[pos] == '-': + if s[pos] == '-': + sign = -1 + pos += 1 + INT_MAX = (1 << 31) - 1 + INT_MIN = - (1 << 31) + + cutoff = INT_MAX // 10 + cutlim = INT_MAX % 10 + if sign == -1: + cutlim = -INT_MIN % 10 + + num = 0 + while pos < len(s) and s[pos].isdigit(): + digit = ord(s[pos]) - ord('0') + if num > cutoff or (num == cutoff and digit > cutlim): + if sign == 1: + return INT_MAX + else: + return INT_MIN + num = num * 10 + digit + pos += 1 + + return num * sign ``` From 14c45b2765209bbdef669eeb244228a6abbd2d76 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 2 Apr 2024 21:34:28 +0900 Subject: [PATCH 6/9] Update 8. String to Integer (atoi).md --- 8. String to Integer (atoi).md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/8. String to Integer (atoi).md b/8. String to Integer (atoi).md index a7c2176..5f3efaf 100644 --- a/8. String to Integer (atoi).md +++ b/8. String to Integer (atoi).md @@ -97,4 +97,36 @@ class Solution: 3rd ```python +class Solution: + def myAtoi(self, s: str) -> int: + pos = 0 + # ignore white spaces + while pos < len(s) and s[pos].isspace(): + pos += 1 + if pos == len(s): + return 0 + + # get sign + sign = 1 + if s[pos] == '+' or s[pos] == '-': + if s[pos] == '-': + sign = -1 + pos += 1 + if pos == len(s): + return 0 + + # convert to number + INT_MAX = (1 << 31) - 1 + INT_MIN = - (1 << 31) + + num = 0 + while pos < len(s) and s[pos].isdigit(): + digit = ord(s[pos]) - ord('0') + num = num * 10 + sign * digit + if num > INT_MAX: + return INT_MAX + if num < INT_MIN: + return INT_MIN + pos += 1 + return num ``` From fc06dc3dcdd04a24163c478f7af6013f35845efb Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 30 Apr 2024 19:39:42 +0900 Subject: [PATCH 7/9] Update 8. String to Integer (atoi).md --- 8. String to Integer (atoi).md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/8. String to Integer (atoi).md b/8. String to Integer (atoi).md index 5f3efaf..b21afaf 100644 --- a/8. String to Integer (atoi).md +++ b/8. String to Integer (atoi).md @@ -52,6 +52,8 @@ class Solution: return number ``` +> 32-bits環境だと(1 << 31)をした時点でオーバーフローする + 2nd 桁上りの掛け算をする前にオーバーフローの判定をする版。あと関数に切り出さずに書いた。処理が素直に上から下に流れるので関数に切り出さなくても大丈夫かも。 @@ -94,6 +96,8 @@ class Solution: return num * sign ``` +> 最後にsignを掛けているのでINT_MINのときに途中でオーバーフローしている気がする。たぶんそう。`digit >= cutlim`に変えてあげれば問題ないが、通常の範囲でのINT_MINなのかオーバーフローしてのINT_MINなのかを判別することができなくなる + 3rd ```python From 4580d6809a2c2a8ec5a29548cf95ffcfe408cd81 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 30 Apr 2024 21:41:40 +0900 Subject: [PATCH 8/9] Update 8. String to Integer (atoi).md --- 8. String to Integer (atoi).md | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/8. String to Integer (atoi).md b/8. String to Integer (atoi).md index b21afaf..7fd24be 100644 --- a/8. String to Integer (atoi).md +++ b/8. String to Integer (atoi).md @@ -134,3 +134,46 @@ class Solution: pos += 1 return num ``` + +4th + +floor divisionとmoduloの挙動: https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations + +```python +class Solution: + def myAtoi(self, s: str) -> int: + index = 0 + + # skip white spaces + while index < len(s) and s[index] == ' ': + index += 1 + if index == len(s): + return 0 + + # determine sign + sign = 1 + if s[index] == '+' or s[index] == '-': + if s[index] == '-': + sign = -1 + index += 1 + if index == len(s): + return 0 + + # convert to integer + INT_MAX = (1 << 31) - 1 + INT_MIN = -INT_MAX - 1 + num = 0 + cutoff = INT_MAX // 10 + cutlim = INT_MAX % 10 + if sign == -1: + # 2の補数表現によりマイナスの場合は1を足せば良い&2のべき乗-1が9になることはない + # マイナスの場合もmoduloを取っても良いが、結果がsecond operandの符合と一致する言語仕様で処理が冗長になる + cutlim += 1 + while index < len(s) and s[index].isdigit(): + digit = ord(s[index]) - ord('0') + if abs(num) > cutoff or (abs(num) == cutoff and digit > cutlim): + return INT_MAX if sign == 1 else INT_MIN + num = num * 10 + digit * sign + index += 1 + return num +``` From aa33437ea7e37de21db2888c4206e9a37f5f6853 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Fri, 10 May 2024 10:22:26 +0900 Subject: [PATCH 9/9] Update 8. String to Integer (atoi).md --- 8. String to Integer (atoi).md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/8. String to Integer (atoi).md b/8. String to Integer (atoi).md index 7fd24be..47cecca 100644 --- a/8. String to Integer (atoi).md +++ b/8. String to Integer (atoi).md @@ -135,6 +135,8 @@ class Solution: return num ``` +> `ord(s[pos]) - ord('0')`の代わりに`int(s[pos])`とかも選択肢としてあり。とはいえこれをするんだったら`int(s[index:])`みたいにやっていいじゃんという気持ちにもなるので、この問題的にはint使わない方が空気が読めてそう。 + 4th floor divisionとmoduloの挙動: https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations @@ -177,3 +179,12 @@ class Solution: index += 1 return num ``` + +ifのところはindex += 1が冗長になるがフラットに以下でも良いかも。 + +> sign = 1 +if s[index] == '+': + index += 1 +elif s[index] == '-': + index += 1 + sign = -1