-
Notifications
You must be signed in to change notification settings - Fork 0
46. Permutations #47
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: main
Are you sure you want to change the base?
46. Permutations #47
Conversation
| そうしてしまうと内部で別の標準ライブラリ関数の `slices.Grow` を呼び出す時に | ||
| slices が変数名の方で認識されてしまうので `ss` という命名になった(ご容赦) | ||
| - make の代わりに slices.Grow が使われている理由がよくわからなかった。 | ||
| やっていることは `newSlice := make([]E, 0, size)` と同じではないか?と思った |
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.
make([]E, 0, size) は第2引数が長さで第3引数がキャパシティなので初期化はせずメモリーの確保だけしているという認識でした。slices.Grow[S](nil, size) の方も空のスライスに対して size 分だけメモリーを確保しているので両者の違いが分かりませんでした。
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.
ところが make ではなく Grow を使うようにと明記されていて混乱しています。
https://cs.opensource.google/go/go/+/refs/tags/go1.24.2:src/slices/slices.go;l=487
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.
手元で動かしていたら違いが分かってきました。
ss := [][]int{{0, 1, 2, 3, 4, 5}, {6, 7, 8}}
size := 0
for _, s := range ss {
size += len(s)
}
nums1 := make([]int, 0, size)
fmt.Printf("nums1 value: %v, len: %d, cap: %d\n", nums1, len(nums1), cap(nums1)) // nums1 value: [], len: 0, cap: 9
nums2 := slices.Grow[[]int](nil, size)
fmt.Printf("nums2 value: %v, len: %d, cap: %d\n", nums2, len(nums2), cap(nums2)) // nums2 value: [], len: 0, cap: 10注目すべきは nums1 と nums2 のキャパシティの違いで、nums1 の方は size きっかりのキャパシティが割り当てられているのに対し、nums2 は余分に与えられています。これは nums2 の slices.Grow 内部で nums2 := append([]int{}, make([]int, size)...)[:0] のようなことが起きていて、append の際に size class というものに従ってメモリ領域が割り当てられているようです。この size class はスライスの長さに応じて割り当てられるべきキャパシティの対応関係と理解していて、append が起きた後に更に append される際にキャパシティが足りなくて新しくメモリ領域を確保する必要をなくせるようにするという意図があるようです。
なので、Concat の内部実装で Grow が使われているのは後から更に要素が追加される場合に備えているからみたいです。
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.
面白いですね。ありがとうございます。
|
|
||
| ### Step 2 | ||
| #### 2a | ||
| - slices.Concat を使えば二つのスライスを繋げて新しいスライスを作ってくれるので、 |
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.
私も確認したのでマニュアルへのリンクを貼っておきますね。
https://pkg.go.dev/slices#Concat
| } | ||
| ``` | ||
|
|
||
| - 書いてるうちに一般的な場合の方針が立つかなと思ったが、全然思いつかなかったのでほかの方のコードを見てみることに |
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.
自然言語での説明を試みましたが、なんか抽象的ですね、、
- 前から n-1 個の要素の順番を固定し、残り1個の要素の並び替えのパターンをすべて挙げる(1パターン)。
- 前から n-2 個の要素の順番を固定し、残り2個の要素の並び替えのパターンをすべて挙げる(2パターン)。
...
k. 前から n-k 個の要素の順番を固定し、残りk個の要素の並び替えのパターンをすべて挙げる(k!パターン)。残りk個の並び替えは、k-1個固定し、残り1個の並び替え + k-2個固定し、残り2個の並び替え + ...
再帰が使えそうなことが分かる
| - これを読んでなんとなくわかった気になるが、問題の形が変わったときに自力で | ||
| 実装できる自信はあまりない |
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.
バックトラックは、毎度お片付けしながら分類の網羅をしている、というイメージを個人的には持っています。
olsen-blue/Arai60#54 (comment)
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.
ざっくりとしたこと言ってしまっててすみません。
大きく2つある気がしています。
今回のような、今いる地点で分類の網羅をしているケースでは、すでに試した選択肢を撤回して片付けて、次の新しい選択肢絵を試すというイメージでした。
もう一つは、少なくともPythonにおいては、リストのようなミュータブルを引き連れてDFSの探索をすると、1つのリスト(<- 複数の再帰呼び出しの間で共有される)を深いところの探索まで連れてきて更新しまうので、深いところの探索が終了して浅いところに戻る際にも、現在地ですでに試した選択肢を撤回して片付ける必要がある、というイメージでした。
https://github.com/olsen-blue/Arai60/pull/52/files#diff-ddd8c09ee41837c8d5bde978403f850a0b08217fb8ec8eac6d0f2ae10e369d04R56-R57
https://github.com/olsen-blue/Arai60/pull/52/files#diff-ddd8c09ee41837c8d5bde978403f850a0b08217fb8ec8eac6d0f2ae10e369d04R83
https://github.com/olsen-blue/Arai60/pull/53/files#r2021976335
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.
意図が分かりました。ありがとうございます。
| #### 2c | ||
| - 再帰でやったならスタックに直すべし | ||
| - https://github.com/olsen-blue/Arai60/pull/51/files#diff-0d3699b3287447f54faf602faea01d8030e9339f00ffb22c5cc830676711ef22R188 | ||
| - 構造体の名前でいつも悩む。 |
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.
ちょっと良い例かどうか微妙ですが、私は最近は悩んだらheapとかstackみたいな構造体そのままの時もありますね。
1要素が、複数要素まとめたタプルの時とか、全記述しようとすると長くて冗長になるので迷った結果、いっそstackにしてしまえ、となることも少なくないです。(本当はもっと考えるべきなのかもしれないです...)
(Pythonでは) pop() 時に中身が列挙されるのでこの時わかる、というのもあるかもですね。
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.
例えば、このヒープ構造の命名迷った記憶がありますね。
強いて付けるならcandidatesとかにするかもですが、heapの方が意外とわかりやすいのかもしれないです。迷いますね。
https://leetcode.com/problems/find-k-pairs-with-smallest-sums/description/
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.
ありがとうございます。今回のように関数内でしか使われず、スコープの狭いものに関してはそのように stack のような名前を使うのもありですね。
https://leetcode.com/problems/permutations/description/