Skip to content

Conversation

hroc135
Copy link
Owner

@hroc135 hroc135 commented Apr 20, 2025

- おお!感動
- 問題の分解の仕方を変えるだけでこんなにすっきり書けてしまうとは
- https://sentry.io/answers/concatenating-strings-in-go/
- strings.Builder で用意したバッファに WriteString で書き込むとコピーせずに string を結合できるらしい
Copy link

Choose a reason for hiding this comment

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

strings.Builder でコピーがされないので速いというのは一般論としては正しいです。
ただ、a, b ももう string になっているので、もうコピーされているわけですね。

そうすると、高階関数を使うことになるでしょう。
そこで DeepSeek に書かせました。

Copy link

@oda oda Apr 21, 2025

Choose a reason for hiding this comment

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

func generateFunctionsToAppendParenthesis(n int) []func(*strings.Builder) {
	if n == 0 {
		return []func(*strings.Builder){func(sb *strings.Builder) {}}
	}
	result := []func(*strings.Builder){}
	for i := 0; i < n; i++ {
		aFuncs := generateFunctionsToAppendParenthesis(i)
		bFuncs := generateFunctionsToAppendParenthesis(n - i - 1)
		for _, a := range aFuncs {
			for _, b := range bFuncs {
				aCopy := a
				bCopy := b
				fn := func(sb *strings.Builder) {
					sb.WriteString("(")
					aCopy(sb)
					sb.WriteString(")")
					bCopy(sb)
				}
				result = append(result, fn)
			}
		}
	}
	return result
}

func executeFunctions(funcs []func(*strings.Builder)) []string {
	result := make([]string, 0, len(funcs))
	for _, f := range funcs {
		var sb strings.Builder
		f(&sb)
		result = append(result, sb.String())
	}
	return result
}

func generateParenthesis(n int) []string {
	funcs := generateFunctionsToAppendParenthesis(n)
	results := executeFunctions(funcs)
	return results
}

Copy link
Owner Author

Choose a reason for hiding this comment

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

元のコードだと、for _, a := range generateParenthesis(i) で a に string がアサインされているので、コピーが生じてしまうということですね。
高階関数解読中です。

if n == 0 {
return []string{}
}
if n == 1 {
Copy link

Choose a reason for hiding this comment

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

一応n == 1の処理はなくても動きますね

Copy link
Owner Author

Choose a reason for hiding this comment

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

n == 0 のときに空の配列を返しているため、n == 1 の処理がないと for _, p := range previousParenthesis のループが一度も回らないです。n == 0 のときに return []string{""} を返せば n==1 の処理がなくても動きます。

Copy link

Choose a reason for hiding this comment

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

確かにそうですね(まだ脳内シミュレーション能力が足りない、、)
どっちが自然かというと、微妙ですね

nextParenthesis[newParenthesis] = struct{}{}
for j := range len(p) {
if p[j] == '(' {
newParenthesis = p[:j+1] + "()" + p[j+1:]
Copy link

Choose a reason for hiding this comment

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

L27、28とL35、36をなくす代わりに、forループの範囲を伸ばして、最初か最後、もしくはp[j] = '('なら'()'を挿入する、というのを考えましたが、今の実装の方がむしろ簡潔そうですね。

- 手でやることをコードで再現したらできた。嬉しい。成長を感じる
- 手でやったところ、n=i で生成された parenthesis を基に n=i+1 のものを生成するが、
どうしても重複なく生成する方法を思いつかなかったので、map に格納していくことにした
- "(())" を基に次の parenthesis を生成するなら、頭と末尾に "()" を付けたやつ("()(())", "(())()")と、
Copy link

Choose a reason for hiding this comment

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

自分のメモ代わりに書いている文章にコメントするのも変ですが、これ最初のカッコと最後のカッコは、(A, B)でペアという意味のカッコですね(やや混乱しました)

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.

3 participants