質問: n * x } return n } func getPasswordCandidate(ss string, count int) string { char := "abcde" if count < len(char) { // 終了条件 return ss + string(char[count]) } for i := 0; ; i++ { //★★★ if pow(len(char), i) > count { return getPasswordCandidate(ss+string(char[count/len(char)-1]), count-pow(len(char), i-1)) } } } func main() { for i := 0; i <= 16; i++ { fmt.Println(getPasswordCandidate("", i)) } } ``` ### 上記コードの実行結果 ``` a b c d e aa ab ac ad ae baa bab bac bad bae cbaa cbab ```
回答: 注意:文章がぶっきらぼうですが丁寧に書く能力がないだけですので気にしないでくださいね。 いろいろ間違っています。 とりあえず、main関数を見て見ましょう。 問題点 ==== main関数 ``` func main() { for i := 0; i <= 16; i++ { fmt.Println(getPasswordCandidate("", i)) } } ``` iが0から16になるまで繰り返していますね。 iの値に応じて`fmt.Println`を呼び出していますが、ソースコード全体を見ても、`fmt.Println`を呼び出しているのはここだけです。 つまり、このループを見るだけで、このプログラムはたかだか17行しか出力しないことがわかります。 この時点で、すべての組み合わせを出力できないことになります。 pow? おそらく組み合わせの個数を求めるためにpow関数があるのでしょうが、そもそもpowがある時点で間違いです。 いくつの組み合わせがあるかは結果でしかありません。求める解がいくつあるかを考えて、それを終了条件にしている(?)時点で本末転倒です。 powは削除しましょう。 修正案 ==== では、どうしたらよいでしょう? あるべきmain関数 main関数から考えていきます。 main関数の仕事は、何個の文字を組み合わせるかを指定してgetPasswordCandidateを呼び出すことです。 main関数では出力する必要なありません。というか出来ません。 となると、main関数はシンプルに ``` func main() { for i := 0; i <= 16; i++ { getPasswordCandidate("", i) } } ``` だけになるでしょう。 getPasswordCandidate getPasswordCandidateのアルゴリズムはどうなるでしょうか。 ### 終了条件 まず終了条件から考えて行きます。 getPasswordCandidateの終了条件は、”引数countが0の時”になります。 この時、引数ssに、元になる文字"abcde"それぞれを追加した文字列を出力すれば良いです。 出力するのは、ここだけになります。 ``` func getPasswordCandidate(ss string, count int) { chars := "abcde" if count == 0 { // 終了条件 for i := 0; i < len(chars); i++ { fmt.Println(ss + string(chars[i])) } return } /* 省略 */ } ``` ### 再帰 では、残りの再帰部分を考えて行きます。 元になる文字"abcde"から1文字取り出してgetPasswordCandidateを呼び出せばよいでしょう。 この時、引数countには、元のcountから1引いた数を渡してやります。 ``` for i := 0; i < len(chars); i++ { getPasswordCandidate(ss+string(chars[i]), count-1) } ``` これで動作すると思います。 ちなみに、main関数のループを16まで指定していると、時間がかかりすぎて全然反応が返ってこないので注意してください。 リファクタリング ========= そもそも元になる文字"abcde"は引数で渡せばいいと思われます。 そこまではやらないので、気になったらご自分で修正してみてください。