【JavaScript】組み合わせのパターンを作成する関数の実装方法

このQ&Aのポイント
  • JavaScriptで組み合わせのパターンを作成する関数を作成したいと思っています。
  • 引数として材料となる文字の配列と作成する文字列の数を受け取り、組み合わせた文字列の配列を返します。
  • 既存の実装では、総パターン数を計算し、ループで全ての組み合わせを生成する方法を使用していますが、他の実装やより効率的な方法があるのか知りたいです。
回答を見る
  • ベストアンサー

組み合わせのパターンを作成する関数

組み合わせのパターンを作成する関数を作成したいと思っています。 仕様は以下のような感じです。 引数 ・list:材料となる文字の配列 ・len:作成する文字列の数(2以上) 戻り値 ・組合わせた文字列の配列 例 (["a", "b", "c"], 2)→["aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"] (["a", "b"], 3)→["aaa", "aab", "aba", "abb", "baa", "bab", "bba", "bbb"] 私はとりあえず作成する総パターン数(Math.pow(list.length, len))回ループでまわし、indexをtoStrungでn進数にし(ゼロパディングし)、最後に数字と対応する文字を置換するという方法で実装しました。とりあえず動いています。 しかし他にもいろいろなアルゴリズムが考えられそうなので、他の実装・よりよい方法を知りたいと思いまして質問させていただくことにしました。 できれば具体的なコードを教えていただきたいです。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

ひょうじゅんとは? var result = []; var x = ['a', 'b', 'c']; var len = x.length; for (var i = 0, I = len; i < I; i++)  for (var j = 0, J = len; j < J; j++)   result.push (x[i] + x[j]); alert (result.join ('\n')); -- var result = []; var x = ['a', 'b']; var len = x.length; for (var i = 0, I = len; i < I; i++)  for (var j = 0, J = len; j < J; j++)   for (var k = 0, K = len; k < K; k++)    result.push (x[i] + x[j] + x[k]); alert (result.join ('\n')); -- if(!Array.prototype.reduce)Array.prototype.reduce=function(d){var c=this.length;if(typeof d!="function")throw new TypeError;if(c==0&&arguments.length==1)throw new TypeError;var a=0;if(arguments.length>=2)var b=arguments[1];else{do{if(a in this){b=this[a++];break}if(++a>=c)throw new TypeError;}while(1)}for(;a<c;a++)a in this&&(b=d.call(null,b,this[a],a,this));return b}; var rcombination =  function (memo, count) {   return function (r, m, _, a) {    return (count > 1)     ? a.reduce (rcombination (memo.concat (m), count - 1), r)     : r.concat ([ memo.concat (m) ]);   }; }; alert (['a', 'b', 'c'].reduce (rcombination ([ ], 2), [ ]).join("\n")); alert (['a', 'b'].reduce (rcombination ([ ], 3), [ ]).join("\n"));

pringlez
質問者

お礼

saisyonofutatsuwa hikisuugahenkasurutabini kodowokakikaenakerebanaranai nodesuyone? tatoeba kumiawasenomojiga juudattararupumojuuni hyakudattarahyakunorupuwo kakunodesuyone. moushiwakearimasenga watashinokonomidewaarimasen. ...koremo... wakarinikukattadesu. shikashi sankouninarimashita. arigatougozaimashita.

その他の回答 (12)

回答No.13

ついき2! もうひとつみっけ! list.length が10をこえると、おきかえがへんになる Nshinnsuu にへんかんしないと

pringlez
質問者

お礼

naruhodo. korehaookinamondaidesune... sankouninarimashita. goshiteki arigatougozaimashita.

回答No.12

ついき 0でうめるときに tmp にくわえるのは、list[0] でそくどあっぷ。 ひごろ、ひりきなましんでうごかす「身」としては、きになる。

pringlez
質問者

お礼

arigatougozaimashita.

回答No.11

#Array.push を、つかっているじてんで、そくどのことをとやかくいえるものでもないのですが、るーぷのなかにせいきひょうげんでおきかえですか? list のなかにすうじがあったらそれがおきかえされてしまいませんか?(ためしていませんが)

pringlez
質問者

お礼

watashino tousyonosouteideha mondainakattanodesuga hannyouseiwo kouryosurutodamedesune. arigatougozaimashita.

回答No.10

しつもんしゃのあるごりずむをさんこうにしてかいてみる。こんなかんじ? function RepeatedCombination (ary, n) {  var len = ary.length;  var max = Math.pow (len, n);  var index = 0;  var i;  var j, J;  var result = [];  var zero = Array (n).join ('0');  var hash = {};  var str;  var chs;    if (36 < len)   throw new Error;    for (i = 0; i < len; i++)   hash[i.toString (len)] = ary[i];    for (i = 0; i < max; i++) {   chs = (zero + i.toString (len)).slice (-n).split ('');   for (j = 0, str = []; J = chs[j++]; )    str.push (hash[J]);   result.push (str.join (''));  }    return result; } var result = RepeatedCombination (['a', 'b', 'c'], 2); alert (result.join ('\n')); var result = RepeatedCombination (['a', 'b'], 3); alert (result.join ('\n'));

pringlez
質問者

お礼

# var zero = Array (n).join ('0'); kore, omoshiroidesune. sankouninarimashita. arigatougozaimashita.

pringlez
質問者

補足

watashigakakuto, konnnakanjidesu. function createCcombinations(list, len) { var max = Math.pow(list.length, len); var results = []; for (var i = 0; max > i; i++) { for (var tmp = i.toString(list.length); tmp.length < len; tmp = "0" + tmp); for (var j = 0; list.length > j; j++) tmp = tmp.replace(new RegExp(j, "g"), list[j]); results[i] = tmp; } return results; } alert (createCcombinations(['a', 'b'], 3)); alert (createCcombinations(['a', 'b', 'c'], 2));

回答No.9

ていせいです。もうしわけない。 function RepeatedCombination (ary, n) {  var len = ary.length;  var count = 0;  var max = Math.pow (len, n);  var i, o, r;    for (; count < max; count += 1) {   r = [];   o = count;   for (i = 0; i < n; i++) {    r.push (ary[o % len]);    o = Math.floor (o / len);   }   yield r.reverse ().join ('');  } }

pringlez
質問者

お礼

arigatougozaimashita.

回答No.8

れんとうでもうしわけないね。 しょしん(No1)にかえって、ふぁいあーふぉっくすならば、yield がつかえるので、いちいち return もふようで、るーぷがすっきりになりました! <!DOCTYPE html> <title></title> <body> <script type="application/javascript; version=1.8"> function RepeatedCombination (ary, n) {  var len = ary.length;  var count = 0;  var max = Math.pow (len, n);  var m, o, r;    for (var count = 0; count < max; count += 1) {   r = [];   o = count;   m = o % len;   for (var i = 0; i < n; i++) {    m = o % len;    r.push (ary[m]);    o = Math.floor (o / len);   }   yield r.reverse ().join ('');  } } var result = []; var next = RepeatedCombination (['a', 'b', 'c'], 2); for (var i in next)  result.push (i); alert (result.join ('\n')); // 1ぎょうなら! alert ([i for (i in RepeatedCombination (['a', 'b'], 3))].join ('\n')); </script>

pringlez
質問者

お礼

arigatougozaimashita.

回答No.7

あっ!いわゆるくろーじゃーにすれば、かんそにかけますね function RepeatedCombination (ary, n) {  var len = ary.length;  var count = 0;  var max = Math.pow (len, n);    return function () {   var m;   var o = count;   var r = [];      for (var i = 0; i < n; i++) {    m = o % len;    r.push (ary[m]);    o = Math.floor (o / len);   }   count += 1;   return (max < count) ? null: r.reverse ().join ('');  }; } var next = RepeatedCombination (['a', 'b', 'c'], 2); for (var result = [], tmp; tmp = next (); result.push (tmp)); alert (result.join ('\n')); var next = RepeatedCombination (['a', 'b'], 3); for (var result = [], tmp; tmp = next (); result.push (tmp)); alert (result.join ('\n'));

pringlez
質問者

お礼

sukoshikireini narimashitane. arigatougozaimashita.

回答No.6

さらにやっぱりおきにめさなかったのか・・・ざんねん。 たしかにこれまでのこーどは、はいれつがおおきくて、れつすうがおおいと、すくりぷとがとちゅうでとめられてしまうときがありますね。 こんどは、そこをくふうしました。 くみあわせは、なんとおりかをけいさんでもとめることができます。 そのはんいでばんごうをしていすれば、ならびをけいさんできました! function RepeatedCombination (ary, n) {  var len = ary.length;  return function (count) {   var m;   var r = [];      for (var i = 0; i < n; i++) {    m = count % len;    r.push (ary[m]);    count = Math.floor (count / len);   }   return r.reverse ().join ('');  }; } var x = 2; var ary = ['a', 'b', 'c']; var len = ary.length; var max = Math.pow (len, x); var result = []; var getter = RepeatedCombination (ary, x); for (var i = 0; i < max; i++)  result.push (getter (i)); alert (result.join ('\n')); //-- var x = 3; var ary = ['a', 'b']; var len = ary.length; var max = Math.pow (len, x); var result = []; var getter = RepeatedCombination (ary, x); for (var i = 0; i < max; i++)  result.push (getter (i)); alert (result.join ('\n'));

pringlez
質問者

お礼

Nshinsuuto toraerukangaekatadesune. watashiga shitsumonnno boutounikaita kangaekatato houkouseiga onajidesune. arigatougozaimashita.

回答No.5

おきにめさなかったのか・・・ざんねん。 ほんのごくいちぶには、うける? <!DOCTYPE html> <title></title> <body> <script> function rcombination (ary, n) {  var s1 = [    'var r = []',    'var len = ary.length',   ];  var s2 = [];  var code;  var i, I;    while (n--) {   i = 'i' + n;   I = 'I' + n;   s1.push ('for (var ' + i + ' = 0, I'+ n + ' = len; ' + i + ' < ' + I + '; ' + i + '++)');   s2.push ('ary[' + i + ']');  }  code = '{' + s1.join ('\n') + ' r.push (' + s2.join ('+') + ');' + 'return r;}';  return (new Function ('ary', 'n', code))(ary, n); } alert(rcombination(['a', 'b'], 3).join("\n")); alert(rcombination(['a', 'b', 'c'], 2).join("\n")); </script>

pringlez
質問者

お礼

rupuwofuyashiteiku rojikkuno hattenbandesukane. kangaekataga omoshiroidesune. arigatougozaimashita.

回答No.4

なんとなく、おもいだしてきた。 <!DOCTYPE html> <title></title> <body> <script> function rcombination (a, n, m) {  var r = [];  var l = a.length;  var i;    if (1 < n)   for (i = 0; i < l; i++)    r = r.concat (rcombination (a, n -1, m.concat (a[i])));  else   for (i = 0; i < l; i++)    r.push (m.concat (a[i]));    return r; } alert(rcombination(['a', 'b', 'c'], 2, []).join("\n")); alert(rcombination(['a', 'b'], 3, []).join("\n")); //-- // もし、#Array.map がつかえないのなら if(!Array.prototype.map)Array.prototype.map=function(b,e){var c=this.length;if(typeof b!="function")throw new TypeError;for(var d=Array(c),a=0;a<c;a++)a in this&&(d[a]=b.call(e,this[a],a,this));return d}; alert(rcombination(['a', 'b', 'c'], 2, []).map (function (a) { return a.join(''); }).join("\n")); alert(rcombination(['a', 'b'], 3, []).map (function (a) { return a.join(''); }).join("\n")); </script>

pringlez
質問者

お礼

iroirogoteijishite itadakimasitaga, koregaichiban wakariyasukattadesu. toiuka #3wo kaisekishinagara watashigakaitakodoga koretohoboonajininarimashita. (saikinanode else noatonorupuha iranaitoomoimasuga...) arigatougozaimashita.

関連するQ&A

  • トリペプチドの構造

    A,Bというアミノ酸を使ってトリペプチドをつくる場合、考えられる構造は何種類になるのでしょうか? 基礎的なところですが、納得のいく回答がなかなか得られなかったので、詳しい方はご回答ください。 私の考えでは、AAB,ABB,ABA,BBA,BAA,BABの6種類だと考えてます。 この際、AAB,BAAは構造異性体で別のものと考えても問題ないでしょうか? 宜しくお願いします。

  • アルファベットn文字の組み合わせ一覧を生成するサブルーチン

    「アルファベットを格納した配列」と「文字列長」を引数として与えると、全ての組み合せの文字列を返してくれるサブルーチンを定義するにはどうすればよろしいでしょうか? 「文字列長」が2や3の場合には以下のようにforeach文を入れ子にしていますが、「文字列長」の変化に対応できるようなサブルーチンを定義したいと考えます。 @cc = qw(a b c d); # アルファベットを格納した配列 「文字列長」が2の場合、 foreach my $c1 (@cc){ foreach my $c2 (@cc){ push(@str, $c1.$c2); } } aa ab ac ad ba bb bc bd ca cb cc cd da db dc dd 「文字列長」が3の場合、 foreach my $c1 (@cc){ foreach my $c2 (@cc){ foreach my $c3 (@cc){ push(@str, $c1.$c2.$c3); } } } aaa aab aac aad aba abb abc abd aca acb acc acd ada adb adc add baa bab bac bad bba bbb bbc bbd bca bcb bcc bcd bda bdb bdc bdd caa cab cac cad cba cbb cbc cbd cca ccb ccc ccd cda cdb cdc cdd daa dab dac dad dba dbb dbc dbd dca dcb dcc dcd dda ddb ddc ddd アドバイスをよろしくお願いします。

    • ベストアンサー
    • Perl
  • パターンマッチで・・・

    正規表現で、例えば以下の文字列とパターンがあった場合 <top>book<bottom><top>radio<bottom><top>table<bottom> (…以下同じようなパターンが続く) パターン→<top>文字列<bottom> この文字列中のパターン数が未定という条件でマッチした文字列を順に配列に格納するにはどのようなコードにしたらよいのでしょうか? お手数ですがご教授お願いします。

    • ベストアンサー
    • PHP
  • index関数で複数個抜き出す

    $str="りんご・みかん・もも・りんご"; $len=index($str,"りんご"); こんな記述があったとして、 「$len」に「0」だけを返すのではなく文字列に含まれる全ての「りんご」の場所を配列に代入したいのですが、どうすればいいのでしょうか。 こんな感じです。 @len=(0,22); よろしくお願いします。

    • ベストアンサー
    • Perl
  • 文字列を返すVCで作成したDLL関数をVBで呼ぶと...

    VC++で文字列を返すDLL関数を作成しました。 LPCSTR GetVcString(void) これをVBでStringとして受け取り、MsgBoxで表示すると正常に取得できているようなのですが、Lenで文字数を取得すると変な値が返ってきます。 1. Dim Ret As String 2. Ret=GetVcString() 3. MsgBox(Ret) ← VCで返された文字列は正常に表示されている 4. MsgBox(Str(Len(Ret))) ← 実際の文字数とはかけ離れた数値になる 2行目と3行目の間に、 Ret=Left(Ret,InStr(Ret,vbNullChar)-1) を噛ませれば文字数は正常な値になるのですが、このような処理をしなくても正常に文字数を取得する方法があれば教えてください。

  • 行列の問題(固有値)についてです

    こんにちは。行列の問題で分からないものがあります。 B= |000abb| |000bab| |000bba| |abb000| |bab000| |bba000| の固有値と固有ベクトルを求めよという問題です。(みえにくいですが、6×6行列です) 以下、自分が現時点で分かっていることを書きたいと思います。 この問題の導入としてまず A= |abb| |bab| |bba| の固有値と固有ベクトルを求めよ という問題がありました。こちらは定義にしたがい解くと 固有値a+2b 固有ベクトル(1,1,1)^t 固有値a-b(重解)、固有ベクトル(-1,0,1)^t,(0,-1,1)^tと出ました。 問題となる行列Bについて固有方程式としてT=λE-Bを考え、さらに U= |100| |010| |001| と置けば λE-B= |λU -A| |-A λU| という形になり、ここで |BA| |AB|=|B-A||A-B| となることを利用すれば |T|=|λE+A||λE-A|と整理されるので、|λEーA|と|λE+A|が0になる場合をそれぞれ考えれば、結局|T|=0の場合を考えていることになるので、前の問題と比較して 固有値±(a+2b),±(a-b)となりました。(これがあっているのかも自信ないです。) 固有値に関しては上手くできたつもりなのですが、固有ベクトルに関してはどのようにやればいいのかが分かりません。それぞれの固有値について6×6行列に入れて行列を計算していく方法しかないのでしょうか。 Bの行列に規則性があるので気がつけば簡単に求めらるのかもしれないのでしょうが、私は思いつきません。 最後まで読んでいただきありがとうございました。回答よろしくお願いいたします。

  • 良い考え方を知りたいです。(パターン照合について)

    良い考え方を知りたいです。  良い…処理が早い。  考え方…アルゴリズム(と言うのでしょうか) 与えられた部品のリストをマスターと照合し、完成させるタイプ(パターン)を判別したいと考えています。状況の例としては、 ○与えられる部品リスト   A,C,E,G,I,K,L,N,P… (アルファベットには8文字程度の文字列が入ります) ○マスター保持している例  パターン1:A,B,D,E,G,J,K…  パターン2:B,D,E,G,J,M…  パターン3:J,S,T,V,W,X,Z…  パターン4:A,B,D,Y,Z… パターン5:A,C,E,G,I,K,L,N,P…  (各タイプに保持されているマスタデータは順不同、且つ不特定数です) こんな感じで、データベース(MS AccessやSQLサーバー等)に保持されている各タイプと照合し、 与えられた部品リストがどのタイプ(パターン)に合致するか(一番近いか)を 判別するプログラムを作成したいのですが、 どんな考え方が適しているか、ご教示頂けないでしょうか? 照合するパターンはおよそ200弱、リストで渡される部品数は50前後です。 プログラミング自体は素人ですが、 ・適当なアルゴリズム ・サンプルソース(言語は何でも結構です) ・参考資料の探し方、検索場所 いずれかでご回答お願い申し上げます。

  • CASLIIの穴埋め問題について。

    CASLIIの勉強をしているのですが穴埋めの問題がどうしても解けません。 参考書の例題やサイトで公開されてるサンプルなどと比較して考えて 自分なりに答えは出してみたのですがシュミレータを試してみた所間違ってました。 この問題を考え始めてからもう一週間になりますが 解答がないので未だに解けず時間ばかりが過ぎて困っています。 解答と解説を教えて頂けないでしょうか? 問題 図1のプログラムは、3種の文字「a」、「b」、「c」を組み合わせた、 長さが3の全ての文字列を、図2の順に出力する。 図1の(1)~(10)の空欄に適切なオペランドを入れてください。 図1 REP2 START LD (1) LAD GR1,0 LP1 CPA GR1,GR7 JZE (2) LD GR0,CHAR,GR1 ST (3) LAD GR2,0 LP2 CPA GR2,GR7 JZE (4) LD GR0,CHAR,GR2 ST (5) LAD GR3,0 LP3 CPA GR3,GR7 JZE (6) LD GR0,CHAR,GR3 ST (7) OUT (8) LAD GR3,1,GR3 JUMP LP3 BRK3 LAD GR2,1,GR2 JUMP LP2 BRK2 LAD GR1,1,GR1 JUMP LP1 BRK RET FIRST DS 1 SECOND DS 1 THIRD DS 1 CHAR DC (9) LEN DC (10) END 図2 aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cab cac cba cbb cbc cca ccb ccc

  • 配列

    String型の配列の中の文字列の文字数を数える方法で困っています。 問題は、int型の変数lenで与えられた数字よりも大きい文字数の文字列はいくつあるか調べます。 例) stringsLongerThan({"a","ab","abc"}, 0) 3つ全ての文字列の文字数は0より大きいので3を返す stringsLongerThan({"a","ab","abc"}, 2) "abc"の文字数が2より大きいので1を返す stringsLongerThan({"a","ab","abc","abcd","abcde","abcdef","abcdefg"}, 3) "abcd","abcde","abcdef","abcdefg"の4つが文字数3より大きいので4を返す 途中まで組んだのですが、配列array[]の中の文字列の文字数を数えるにはどうしたらよいのでしょうか? public int stringsLongerthan(String[] array, int len){       int result=0;      for(int i=0;i<array.length;i++){        //ここで配列array[i]の文字列の文字数を数える       int count=文字数;       if(cont>len)        result++;     }      return result; } 宜しくお願いします。

    • ベストアンサー
    • Java
  • 「○○通りのパターンがある」の計算のしかた

    よくこの組み合わせは全部で1万通りのパターンが存在するというようなことを聞きますが、 あれの方程式などはあるのでしょうか。 以下の例で説明をお願いします。 1. [a,b,c]の3つだけの文字列を作った時のパターン数 2. 英数字のみのパスワード4桁のパターン数 3. [a,b,c,d,e,f,g]の中から4文字をつかった文字列のパターン数。

専門家に質問してみよう