例えばABCDEFGというワードがあった時、
下記のようにドット1つ挿入して文字列を生成することはできたのですが、
A.B.CDEFG
A.BC.DEFG
のようにドット2つ以上使ってさらに可能な限り文字列を生成するよい方法はないでしょうか。
最大で文字数-1個のドットを使う形になります。
var text = 'ABCDEFG'; let gens_arr = []; for( let i=1; i<text.length; i++ ){ let gen = text.slice(0, i) + '.' + text.slice(i) //重複は除外 if( -1 === gens_arr.indexOf(gen) ){ gens_arr.push(gen); } } console.log(gens_arr);
ログ
A.BCDEFG
AB.CDEFG
ABC.DEFG
ABCD.EFG
ABCDE.FG
ABCDEF.G
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
まずは、全パターンがどれだけあるか数学的に考えてみましょう。
入れるべき箇所は文字の間の6箇所、それぞれに「入れる」「入れない」の2通りがあるので、全体のパターン数は2の6乗、64通りです(1つも入れないのを除けば63通り)。
あとは、0~63を2進数で表して、1の来る位置にピリオドを入れる、というようにすればいいでしょう。
投稿2021/08/25 09:09
総合スコア145930
0
ベストアンサー
面白い問題やね。
こんなん考えたで。
まずは理屈からいくわ。
'ABCDEFG'
という7文字の文字列が与えられたときに、たとえばB
、D
、G
の前にピリオドを挿入する操作は、それぞれの文字が文字列'ABCDEFG'
のどこの位置にあるかのインデクスの集合で表すことができる。
- つまり、
'ABCDEFG'
から'A.BC.DEF.G'
を作る操作を、 集合{ 1, 3, 6 }
で表すことにする。
- このようにピリオドを挿入する位置を表すことにすると、ピリオドを挿入する位置は 1 以上 6(=与えられた文字列の長さ - 1)以下の整数なので、これらの整数の集合を
X = { 1, 2, 3, 4, 5, 6 }
とする。
- このようにピリオドを入れる位置の集合
X
を定めると、'ABCDEFG'
の文字間に、連続しないドットを挿入する、すべての操作の集合P(X)
は、(ひとつもピリオドを挿入しないこともひとつの操作と扱って、) X のべき集合 で表すことができる。すなわち
P(X) = { A | A ⊆ X } = { ∅, {1}, {2}, {3}, ・・・ {1, 2}, {1, 3}, ・・・ , { 1, 2, 3, 4, 5, 6 } }
次にコードやねんけど。
X
は配列[1, 2, 3, 4, 5, 6 ]
で実装するで。
javascript
1function powerset(ary) { 2 var ps = [[]]; 3 for (var i=0; i < ary.length; i++) { 4 for (var j = 0, len = ps.length; j < len; j++) { 5 ps.push(ps[j].concat(ary[i])); 6 } 7 } 8 return ps; 9}
を使うで。
- それと、元の文字列と、ピリオドを挿入する位置を表す配列を受け取って、ピリオドを挿入した文字列を返す関数を作っとくで。とりま、こんなやつ
javascript
1function insertPeriods(str, positions) { 2 const chunks = [...positions, str.length].map((pos, i, ary) => { 3 const start = i > 0 ? ary[i-1] : 0 4 return str.substring(start, pos); 5 }); 6 7 return chunks.join('.'); 8}
でええのんちゃうか。
- ここまで準備しとけば、あとは、
javascript
1// 与えられる文字列 2const text = 'ABCDEFG'; 3 4// ピリオドを挿入する位置の集合Xを表す配列 5const X = [...Array(text.length - 1)].map((_, i) => i + 1); 6 7// X のべき集合 P(X) を表す配列 (※空集合を表す空配列も含まれる) 8const PX = powerset(X); 9 10// PXに含まれるすべてのピリオド挿入位置をtext に適用した文字列を出力 11for (const periodPositions of PX) { 12 console.log(insertPeriods(text, periodPositions)); 13} 14
で、ピリオド入りの文字列の全パターンが出力されますわ ➡ サンプル
**補足: ** X
のべき集合を、数学で書くとき、「2のX乗」みたいに書くこともあってん。意味するところとして、X
の要素の数を |X|
と書くとすると、X
のべき集合の要素の数は 2の|X|乗になるねん。今回の例だと、X = {1, 2, 3, 4, 5, 6}
で、要素の数は 6 個やから、そのべき集合の要素数は 2の6乗の64やねん。これは、'ABCDEFG'
から作られるピリオド入れた文字列のパターン数に一致するゆうこっちゃ。ただし、64パターンの中には、0個のピリオドを入れる、つまりピリオドを入れないという操作で得られる、元の文字列と同じ文字列も含まれんで。(なぜゆうたら、べき集合には必ず空集合∅が含まれとるからやねん)
さらに追伸: 要素n個の集合のべき集合を、再帰と、0以上(2のn乗-1)以下の整数に対するビット操作の2通りで作ろうゆう人がおったわ➡ Power Set Algorithm with Recursion or Bits
ビット操作でやるのやったら、こちらさんが書いたコード
javascript
1var powerSet = function (str) { 2 const results = []; 3 for (let i = 0; i < 1 << str.length; i++) { 4 let subset = ""; 5 for (let j = 0; j < str.length; j++) { 6 if (i & (1 << j)) { 7 subset += str[j]; 8 } 9 } 10 results.push(subset); 11 } 12 return results; 13};
の、 if (i & (1 << j)) {
でやってる &
や <<
だったりが参考になるやもしれんね〜
投稿2021/08/25 16:13
編集2021/08/26 00:50退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/08/26 02:15
退会済みユーザー
2021/08/26 14:42
2021/08/27 00:21
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/08/25 23:52