-
Notifications
You must be signed in to change notification settings - Fork 0
Atoi #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: arai60
Are you sure you want to change the base?
Atoi #5
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| INT_MAX = 2 ** 31 -1 | ||
| INT_MIN = - 2 ** 31 | ||
| # 仮に数字の場合文字列の最初に来うるのは符号か数字のみ | ||
| # 符号が来た場合も次の文字が数字じゃなければならない | ||
| # is_number -> extract_number(integer部分を抜き取る) -> 数字化処理 | ||
|
|
||
| def char_is_number(char: str)->bool: | ||
| if ord(char) >= ord("0") and ord("9") >= ord(char): | ||
| return True | ||
| return False | ||
|
|
||
| def is_number(s: str)->bool: | ||
| for index, char in enumerate(s): | ||
| if char == " ": | ||
| continue | ||
| elif char == "-" or char == "+": | ||
| if index == len(s) - 1: | ||
| #符号が終端の場合 | ||
| return False | ||
| else: | ||
| #次の文字が数字かどうかで判断 | ||
| return char_is_number(s[index+1]) | ||
| elif char_is_number(char): | ||
| return True | ||
| else: | ||
| return False | ||
| return False | ||
|
|
||
| def search_start_index(s: str)->int: | ||
| for index, char in enumerate(s): | ||
| if char == "+" or char == "-": | ||
| return index | ||
| elif char_is_number(char): | ||
| return index | ||
|
|
||
| def extract_number(s: str)->str: | ||
| start_index = search_start_index(s) | ||
| end_index = len(s) | ||
| for index in range(start_index+1, len(s)): | ||
| if not char_is_number(s[index]): | ||
| end_index = index | ||
| break | ||
| return s[start_index:end_index] | ||
|
|
||
| def string_to_integer(s: str)->int: | ||
| if not is_number(s): | ||
| return 0 | ||
|
|
||
| extracted_number_string = extract_number(s) | ||
| sign = 1 | ||
| if extracted_number_string[0] == "-": | ||
| sign = -1 | ||
| extracted_number_string = extracted_number_string[1:] | ||
| elif extracted_number_string[0] == "+": | ||
| extracted_number_string = extracted_number_string[1:] | ||
|
|
||
| after_atoi_number = 0 | ||
| for index, char in enumerate(extracted_number_string): | ||
| digit = len(extracted_number_string) - index - 1 | ||
| after_atoi_number += (ord(char)-ord("0")) * 10 ** digit | ||
|
|
||
| return after_atoi_number * sign | ||
|
|
||
|
|
||
|
|
||
| def clamp(number: int) -> int: | ||
| if number > INT_MAX: | ||
| return INT_MAX | ||
| elif number < INT_MIN: | ||
| return INT_MIN | ||
| return number | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # https://github.com/cheeseNA/leetcode/pull/5/files | ||
| # まず空白に関してカーソルを動かす, そのあと符号に関してカーソルを動かし, 数字が続く限りwhileで処理をしていた。 | ||
| # 僕のphase1の解答と違いif文に関しての複雑な制御がいらなくて賢かった。(でもatoiを作れという課題なのにpythonのintを使ってるのはどうなんだろう) | ||
|
|
||
| # https://github.com/usatie/leetcode/commit/9b4ea58330b31c3c1371fe242bc02ab1a9012329 | ||
| # 上のほぼC++版, 上もだがオーバーフローは最後に確認ではなく逐次確認の方が良いのだと思った | ||
| # 最後に確認する方法だと下手したらオーバーフローが二周してくる場合とかもあるなと思った | ||
|
|
||
| INT_MAX = 2 ** 31 -1 | ||
| INT_MIN = - 2 ** 31 | ||
|
|
||
| def char_is_number(char: str)->bool: | ||
| if ord(char) >= ord("0") and ord("9") >= ord(char): | ||
| return True | ||
| return False | ||
|
|
||
| def string_to_integer(s: str)->int: | ||
| if len(s) == 0: | ||
| return 0 | ||
|
|
||
| current_pointer = 0 | ||
| while current_pointer < len(s): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| # 空白に関して処理をする | ||
| if s[current_pointer] != " ": | ||
| break | ||
| current_pointer += 1 | ||
| if current_pointer == len(s): | ||
| return 0 | ||
|
|
||
| sign = 1 | ||
| #符号処理 | ||
| if s[current_pointer] == "+": | ||
| current_pointer += 1 | ||
| elif s[current_pointer] == "-": | ||
| sign = -1 | ||
| current_pointer += 1 | ||
|
|
||
| abs_value = 0 | ||
| while current_pointer < len(s) and char_is_number(s[current_pointer]): | ||
| abs_value *= 10 | ||
| abs_value += ord(s[current_pointer]) - ord("0") | ||
| if abs_value * sign > INT_MAX: | ||
| return INT_MAX | ||
| elif abs_value * sign < INT_MIN: | ||
| return INT_MIN | ||
| current_pointer += 1 | ||
|
|
||
| return abs_value * sign | ||
|
|
||
|
|
||
| class Solution: | ||
| def myAtoi(self, s: str) -> int: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. myAtoi() は実質 string_to_integer() のラッパーになっているように思います。あえてラップする意味はないと思います。 string_to_integer() の中身をここに書いてしまったほうが良いと思います。 |
||
| after_atoi_number = string_to_integer(s) | ||
| return after_atoi_number | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| INT_MAX = 2 ** 31 - 1 | ||
| INT_MIN = - 2 ** 31 | ||
| def char_is_number(char: str)->int: | ||
| if ord(char) >= ord("0") and ord("9") >= ord(char): | ||
| return True | ||
| return False | ||
|
|
||
| def string_to_integer(s: str)->int: | ||
| if len(s) == 0: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. このチェックは不要そうです。 |
||
| return 0 | ||
|
|
||
| current_pointer = 0 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| while current_pointer < len(s): | ||
| if s[current_pointer] != " ": | ||
| break | ||
| current_pointer += 1 | ||
|
|
||
| if current_pointer == len(s): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. while-else が一応ありますか?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. while-else文知らなかったです... |
||
| return 0 | ||
|
|
||
| sign = 1 | ||
| # 符号処理 | ||
| if s[current_pointer] == "+": | ||
| current_pointer += 1 | ||
| elif s[current_pointer] == "-": | ||
| sign = -1 | ||
| current_pointer += 1 | ||
|
|
||
| abs_value = 0 | ||
| while current_pointer < len(s) and char_is_number(s[current_pointer]): | ||
| abs_value *= 10 | ||
| abs_value += ord(s[current_pointer]) - ord("0") | ||
| if abs_value * sign > INT_MAX: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. もし32-bitのintしか使えない状況だったら、どうやって判定するかも考えてみてもいいかもしれません。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 計算前のabs_valueの値を取っておいて, 計算後に符号が変わっていたらオーバーフローしているので, signに従ってINT_MAXかINT_MINを出力という感じでしょうか There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. signed intのオーバフーローは、C++ではundefined behaviorみたいです。unsigned intを使えば簡単に確認できますが、もしintしか使えないという制約のもとでは、10倍して次の数字を足す前に確認できそうです。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ちょうど今C++でも書いていたんですが, runの時点panicを引き起こしました
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rustなどだとオーバーフロー制御があるので書きやすいので, そちらでも時間があったら書いてみます |
||
| return INT_MAX | ||
| elif abs_value * sign < INT_MIN: | ||
| return INT_MIN | ||
| current_pointer += 1 | ||
|
|
||
| return abs_value * sign | ||
|
|
||
| class Solution: | ||
| def myAtoi(self, s: str) -> int: | ||
| after_atoi_number = string_to_integer(s) | ||
| return after_atoi_number | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| INT_MAX = 2 ** 31 - 1 | ||
| INT_MIN = - 2 ** 31 | ||
|
|
||
| def char_is_number(c: str)->bool: | ||
| return ord("0") <= ord(c) <= ord("9") | ||
|
|
||
| class Solution: | ||
| def myAtoi(self, s: str) -> int: | ||
| index = 0 | ||
| while index < len(s) and s[index] == " ": | ||
| index += 1 | ||
|
|
||
| if index == len(s): | ||
| return 0 | ||
|
|
||
| sign = 1 | ||
| if s[index] == "+": | ||
| index += 1 | ||
| elif s[index] == "-": | ||
| sign = -1 | ||
| index += 1 | ||
|
|
||
| absolute_value = 0 | ||
| while index < len(s) and char_is_number(s[index]): | ||
| absolute_value *= 10 | ||
| absolute_value += ord(s[index]) - ord("0") | ||
| if absolute_value * sign > INT_MAX: | ||
| return INT_MAX | ||
| elif absolute_value * sign < INT_MIN: | ||
| return INT_MIN | ||
| index += 1 | ||
|
|
||
| return absolute_value * sign | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
直後に return True/False を行っています。この場合、 if 文の条件式をそのまま返したほうがシンプルになると思います。
また、不等号の向きは
等の流派があります。複数の書き方で書けるようにして置き、チーム内でよく書かれる書き方で書けるようにしておくとよいと思います。
今回の場合は、
return ord("0") <= ord(char) and ord(char) <= ord("9")あたりが良いと思います。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pythonなら
return ord("0") <= ord(char) <= ord("9")もできますね。この問題だと、isdigitを使ってもいいです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
一応, ここでの会話(cheeseNA/leetcode#5 (comment)) を見てisdigitは使わない方向にしてみました。