- ベストアンサー
全組み合わせの出力プログラム
$kana1[0][0] = "a"; $kana1[0][1] = "u"; $kana1[1][0] = "n"; $kana1[1][1] = "m"; という二次元配列があったときに an am un um と出力するようなプログラムのアルゴリズム(?)を教えてほしいです。 簡単なようでforループでやるとうまくいかずwhileを使ってフラグ変数とか作ってやってみましたがどうも駄目です。 ヒントでも何でもいいのでよろしくお願いします! むしろ二次元配列を使うのがダメなら言って下さるとありがたいです。 よろしくお願いします。 最終的には二次元配列の縦も横も任意の数のときにすべての組み合わせを出力できるようにならなければなりません。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
#1 で書いたものにちょこっと手を入れれば終わりのはずなんだけどなぁ. my @words = (''); for my $array (@kana1) { my @newwords; for my $word (@words) { push @newwords, map {"$word$_" } @$array; } @words = @newwords; } でダメかな? なんかデジャヴなんだけど....
その他の回答 (4)
- kumoz
- ベストアンサー率64% (120/185)
再帰呼び出しを使って、全部の組み合わせを生成しています。 use strict; my @kana1 = (['a', 'u'], ['n', 'm'], ['ko', 'co']); my @work =(); comb(0); sub comb { my $i = shift; foreach my $str (@{$kana1[$i]}) { push @work, $str; if ($i == $#kana1) { print join('', @work), "\n"; } else { comb($i + 1); } pop @work; } }
- Tacosan
- ベストアンサー率23% (3656/15482)
「すべての組み合わせ」というのがあいまいなので確認したいのですが, $kana1[0][0] = "a"; $kana1[0][1] = "u"; $kana1[1][0] = "n"; $kana1[1][1] = "m"; $kana1[2][0] = "ko"; $kana1[2][1] = "co"; のときにはどのような結果が欲しいのでしょうか?
補足
anko anco amko amco unko unco umko umco の8種類です。 現状では $kana1[0][0] = "a"; $kana1[0][1] = "u"; $kana1[1][0] = "n"; $kana1[1][1] = "m"; $kana1[2][0] = "ko"; $kana1[2][1] = "co"; my @newwords; my @words; my $word; my $i; my $j; my $k; @words = @{$kana1[0]}; #print "$words[0][0]"; $k = 0; for $j (0..1) { #print "words = @words\n"; for $i (0..$#words){ push @{$newwords[$i]}, map {"$words[$i]$_" } @{$kana1[$j+1]}; } for $k (0..$#newwords){ print "@{$newwords[$k]}\n"; @words[$k] = @{$newwords[$k]}; print "k = $k\nwords = @words\n\n"; } } for $i (0..$#newwords){ print "*@{$newwords[$i]}\n"; } となっています。現状の出力は an am k = 0 words = an u un um k = 1 words = an un an am anko anco k = 0 words = an un un um unko unco k = 1 words = an un *an am anko anco *un um unko unco です。 あと少しのようですがリファレンスが使いこなせないので苦しいです。 個人的ボトルネックはpush関数は二次元配列に使えない push @newwords[$i], map {"$words[$i]$_" } @{$kana1[$j+1]}; ができないことですね。リファレンスにするとなんとかなったのですが中で何が起こってるのか現在解析中です。 なにか申し訳ありません・・・。
- jjon-com
- ベストアンサー率61% (1599/2592)
Perlの特徴的なコーディングは使わず,多くのプログラム言語でも通用するだろうコードの概略がどうなるかを知りたいというならこんな感じ。 @kana1 = ( ['A', 'B', 'C', 'D'] , ['a', 'b', 'c', 'd'] , ['1', '2', '3', '4'] ); for ($i = 0; $i < 4; $i++) { for ($j = 0; $j < 4; $j++) { for ($k = 0; $k < 4; $k++) { print $kana1[0][$i], $kana1[1][$j], $kana1[2][$k], "\t"; } } } >最終的には二次元配列の縦も横も任意の数 ということで,その数があまりにも大きく多段forループをいちいち書いていられないというなら,次の手を考えましょうか。
お礼
これが概念ですね!ありがとうございます!! printのところは特にわかっているようであいまいだったのでなんだかすっきりしました!
補足
二次元配列が●行●列とわかっているならこれでできるのですが それがわからない場合。forループの数が変わるのでその場でプログラムがソースコードを書くことはできないし・・・ printのところも行の数によって変わってくるし。 なんだかできそうでできないです。
- Tacosan
- ベストアンサー率23% (3656/15482)
え? for で簡単にできると思うんだけど.... どんなふうにやってみたんでしょうか? 例えば my @words; @words = @{$kana1[0]}; my @newwords; for my $word (@words) { push @newwords, map {"$word$_" } @{$kana1[1]}; } @words = @newwords; で @words に全ての組合せが入ってる... かな?
お礼
ありがとうございます! map関数とリファレンスの概念を全く知らなかったので理解するのに時間がかかりました。 map関数は非常に強力ですね! これは使わない手はないです!! ありがとうございます!!
補足
$kana1[0][0] = "a"; $kana1[0][1] = "u"; $kana1[1][0] = "n"; $kana1[1][1] = "m"; $kana1[2][0] = "ko"; $kana1[2][1] = "co"; になるともちろんこのコードでは無理で改造が必要です。 そしていろいろやったのですが。 an am un um nko mco の出力で沈黙です・・。 @newwordsの内容を$wordの位置に持ってきてさらにつなげていくのが理想だと思うのですが。そうすると@wordが永遠に増え続け無限ループに・・・。 もう少し頑張ってみますがずっと返信しないのは失礼なので現状報告させてもらいました。 また何かヒントがあれば教えて下さい。 よろしくお願いします。
お礼
すいません!なんとか自力でやりました! でもTacosanさんのソースとほとんど変わらないものになりましたのでとてもうれしいです。費やした時間はかなり違うと思いますが(笑) @newwordを初期化すること(Tacosanさんは宣言することで初期化していらっしゃいますが)に気がつかずゴミが残る事態となってました。 本当にありがとうございます。まだまだ未熟なんでこれからもがんばりたいと思います。 ありがとうございまいした!!