Skip to content
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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Add 2. Add Two Numbers.md #5

wants to merge 3 commits into from

Conversation

t0hsumi
Copy link
Owner

@t0hsumi t0hsumi commented Nov 26, 2024

carry = value_sum // 10
node_sum.next = ListNode(val=digit)

node_sum = get_next(node_sum)

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の方が読みやすいでしょうか。好みの範囲?)

Copy link
Owner Author

Choose a reason for hiding this comment

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

コメントありがとうございます。
やっていることは変わらないので、好みの問題な気がしますが気持ちとしては、

  • ノードを一つ進める処理がまとまっていて、かつ、おんなじ書き方している方が読みやすそう。(なんで一個だけ違う書き方してるんだと、一瞬考える時間がなくなる)
  • この関数呼び出しがボトルネックにはならなさそう

くらいの考えでした。

Copy link

@thonda28 thonda28 Nov 26, 2024

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)`とかいうメソッドを追加したい。
Copy link

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 にメソッドを追加されると、これはシングルトンでプログラムのすべての箇所が共用で使っているものです。大規模な開発では大人数で触られると思わぬ事故が起こりそうですね。

Copy link
Owner Author

Choose a reason for hiding this comment

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

コメントありがとうございます。

None にメソッドを追加されると、これはシングルトンでプログラムのすべての箇所が共用で使っているものです。大規模な開発では大人数で触られると思わぬ事故が起こりそうですね。

確かに、気軽にやりたいと思えることではないですね。

一つ伺いたいのですが、「インスタンスにメソッドを足すことが可能」のような知識はどういう流れで身についていくのでしょうか?
リンク先にもある通り、私自身もインスタンスにメソッドを足すはいい慣習ではないと思いますし、今回の問題を解くに当たってやろうともやれるとも思っていませんでした。「メソッドを追加してやろうと思って調べる」なのか、「クラスに関するドキュメントを見ていたら気になったので調べる」なのか、どういうとっかかりでこういう知識がついていくのか気になりました。

Copy link

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

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 でよいのではないでしょうか。

Comment on lines +76 to +77
digit = value_sum % 10
carry = value_sum // 10
Copy link

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

@ichika0615 ichika0615 Nov 26, 2024

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

が一番しっくりくると思います。
また、合計を計算したりする前にノードを次に進めているのもわかりづらく感じました。

Comment on lines +12 to +22
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

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 がよい変数名かは微妙な気もしますが)

Suggested change
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)

Comment on lines +26 to +27
if carry == 1:
sum_node.next = ListNode(val=1)
Copy link

@thonda28 thonda28 Nov 26, 2024

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

@thonda28 thonda28 Nov 26, 2024

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箇所にまとまっていて個人的にはわかりやすいと感じました。(が、これは人によるのかもです)

Comment on lines +66 to +67
node1 = l1
node2 = l2
Copy link

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

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で置き換えられそこまで長くないので僕だったら関数にしません。
でも、それ以外はいいと思いました!

Copy link
Owner Author

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とかでもいいのではと思ってます。

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.

7 participants