-
Notifications
You must be signed in to change notification settings - Fork 0
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
Add 2. Add Two Numbers.md #5
base: main
Are you sure you want to change the base?
Conversation
carry = value_sum // 10 | ||
node_sum.next = ListNode(val=digit) | ||
|
||
node_sum = get_next(node_sum) |
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.
node_sum = node_sum.next
でいいような気がしてるんですが、いかがでしょう。
今回のケースでいうとnode_sumがNoneになることはないと思いました。
(get_nextの方が読みやすいでしょうか。好みの範囲?)
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.
コメントありがとうございます。
やっていることは変わらないので、好みの問題な気がしますが気持ちとしては、
- ノードを一つ進める処理がまとまっていて、かつ、おんなじ書き方している方が読みやすそう。(なんで一個だけ違う書き方してるんだと、一瞬考える時間がなくなる)
- この関数呼び出しがボトルネックにはならなさそう
くらいの考えでした。
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.
僕も node_sum = node_sum.next
で十分かなと思いました。(get_value()
もかえって複雑なのではと感じました)
また Step1 では「値を読み取ったらすぐに次のノードに動かす」という実装で、Step3 では「値の読み取り」と「ノードの次に進める」という処理を分離する実装になっていますが、Step 1 のほうが着目しているノードに対する処理が1箇所にまとまっていて個人的にはわかりやすいと感じました。(が、これは人によるのかもです)
# step 3 | ||
ノードから値を取る処理、次のノードを取る処理は分けられたので分けることにした。 | ||
|
||
可能ならListNodeをいじって、`node.get_value(default=0)`とかいうメソッドを追加したい。 |
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 は ListNode を後からいじること自体は可能です。(この投稿の前後を見ておいてください。)
https://discord.com/channels/1084280443945353267/1225849404037009609/1228375055717765190
インスタンスに足すことも可能です。
types.MethodType
https://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance-in-python
ただ、None のときにも欲しいんですよね。
Python は None へのメソッドの追加が確かできなかったと思いますが、それはさておき、たとえば Ruby では相当する物である nil への追加ができますので、できたとしましょう。
そうだとしても None にメソッドを追加されると、これはシングルトンでプログラムのすべての箇所が共用で使っているものです。大規模な開発では大人数で触られると思わぬ事故が起こりそうですね。
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.
コメントありがとうございます。
None にメソッドを追加されると、これはシングルトンでプログラムのすべての箇所が共用で使っているものです。大規模な開発では大人数で触られると思わぬ事故が起こりそうですね。
確かに、気軽にやりたいと思えることではないですね。
一つ伺いたいのですが、「インスタンスにメソッドを足すことが可能」のような知識はどういう流れで身についていくのでしょうか?
リンク先にもある通り、私自身もインスタンスにメソッドを足すはいい慣習ではないと思いますし、今回の問題を解くに当たってやろうともやれるとも思っていませんでした。「メソッドを追加してやろうと思って調べる」なのか、「クラスに関するドキュメントを見ていたら気になったので調べる」なのか、どういうとっかかりでこういう知識がついていくのか気になりました。
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 がどういう動きをしているかから導いています。新しい言語を学ぶときに初期に気になるのがこのあたりです。そして、だいたいマニュアルに書いてあります。
https://discord.com/channels/1084280443945353267/1196472827457589338/1200081854301225011
これも同じかと思います。
carry = value_sum // 10 | ||
node_sum.next = ListNode(val=digit) | ||
|
||
node_sum = get_next(node_sum) |
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.
これは、直前で作っているので None ということはないので、単純に node_sum = node_sum.next
でよいのではないでしょうか。
digit = value_sum % 10 | ||
carry = value_sum // 10 |
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.
divmod
というこういう場面でしか使い道のない Built-in function があります。
https://docs.python.org/3/library/functions.html#divmod
node1 = node1.next | ||
if node2 is not None: | ||
value2 = node2.val | ||
node2 = node2.next |
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.
この部分がわかりづらく思いました。所与の連結リストを走査していき、ノードがあるならvalue1
ないしはvalue2
にその数字を格納して、ノードがすでに終わっているなら加算するものがないから0を代入する、というロジックかと思います。
if node1 is not None:
value1 = node1.val
else:
value1 = 0
が一番しっくりくると思います。
また、合計を計算したりする前にノードを次に進めているのもわかりづらく感じました。
value1 = 0 | ||
value2 = 0 | ||
if node1 is not None: | ||
value1 = node1.val | ||
node1 = node1.next | ||
if node2 is not None: | ||
value2 = node2.val | ||
node2 = node2.next | ||
|
||
sum_value = (value1 + value2 + carry) % 10 | ||
carry = (value1 + value2 + carry) // 10 |
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.
value1
, value2
はともに一時変数だと思うので carry
も含めて1つの変数で扱うのがわかりやすいのでは、と思いました。結局興味があるのは value1 + value2 + carry
なので。(tmp_val
がよい変数名かは微妙な気もしますが)
value1 = 0 | |
value2 = 0 | |
if node1 is not None: | |
value1 = node1.val | |
node1 = node1.next | |
if node2 is not None: | |
value2 = node2.val | |
node2 = node2.next | |
sum_value = (value1 + value2 + carry) % 10 | |
carry = (value1 + value2 + carry) // 10 | |
tmp_val = carry | |
if node1 is not None: | |
tmp_val += node1.val | |
node1 = node1.next | |
if node2 is not None: | |
tmp_val += node2.val | |
node2 = node2.next | |
carry, digit = divmod(tmp_val, 10) |
if carry == 1: | ||
sum_node.next = ListNode(val=1) |
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.
この問題において carry
には 0 または 1 しか入りませんが、ここで気にしていることは carry
があるかないか(0 かそうでないか)かと思うので、if carry:
または if carry > 0:
という条件のほうが意図が伝わる気がします。
またこの問題では2つのノードですが、後からやっぱり3つのノードも扱えるよう拡張したりすると、(新たに2が入りうるため)この部分で予期せぬバグが生まれたりもしそうです。(実務だとそういった後からの拡張もありえそうです)
carry = value_sum // 10 | ||
node_sum.next = ListNode(val=digit) | ||
|
||
node_sum = get_next(node_sum) |
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.
僕も node_sum = node_sum.next
で十分かなと思いました。(get_value()
もかえって複雑なのではと感じました)
また Step1 では「値を読み取ったらすぐに次のノードに動かす」という実装で、Step3 では「値の読み取り」と「ノードの次に進める」という処理を分離する実装になっていますが、Step 1 のほうが着目しているノードに対する処理が1箇所にまとまっていて個人的にはわかりやすいと感じました。(が、これは人によるのかもです)
node1 = l1 | ||
node2 = l2 |
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.
今回のようにノードのvalを順に見ていくだけで変更しないなら、l1,l2を別の変数に移さずに使うのもありだと思います。
Pythonでポインタとかどうなっているのか詳しくないので、間違っていたらすみません🙇♂️
while node1 is not None or node2 is not None or carry > 0: | ||
value1 = get_value(node1) | ||
value2 = get_value(node2) | ||
value_sum = value1 + value2 + carry |
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.
こちら、valueにあまり意味がないと思うので、単にsumでもよいと思います。
※valueはListNode.valueということだと思いますが、単にvalueからそれは思いつきにくいと思います。
連続した2行で使われている変数なので、そこまで変数名にこだわる必要はないかと。
ついでにいうと、get_valueやget_nextはnode.next if node else Noneで置き換えられそこまで長くないので僕だったら関数にしません。
でも、それ以外はいいと思いました!
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.
sumだとbuiltin functionと被るんですよね。
ただ、value1, value2
自体はそれほど注目しているわけではないので、sum_value = get_value(node1) + get_value(node2) + carry
とかでもいいのではと思ってます。
問題
https://leetcode.com/problems/add-two-numbers/description/
次に解く問題
https://leetcode.com/problems/valid-parentheses/description/