単語の大文字小文字の入れ替えをすべて含むリストを作成したいと思います。それは大文字の転記
とても幸せ、私は戻って
{、幸せ、幸せ、幸せ、幸せ、幸せ...幸せな、幸せの配列を取得する必要があり、私は「幸せ」で置くと言うだろう、HAPPY}
最初の文字を大文字にする機能はたくさんありますが、どのようにして単語に任意の文字を入力できますか?
単語の大文字小文字の入れ替えをすべて含むリストを作成したいと思います。それは大文字の転記
とても幸せ、私は戻って
{、幸せ、幸せ、幸せ、幸せ、幸せ...幸せな、幸せの配列を取得する必要があり、私は「幸せ」で置くと言うだろう、HAPPY}
最初の文字を大文字にする機能はたくさんありますが、どのようにして単語に任意の文字を入力できますか?
文字列をcharの配列に変換すると、個々の文字を変更できます。このような何かが、トリックを行う必要があります...
public static List<string> Permute(string s)
{
List<string> listPermutations = new List<string>();
char[] array = s.ToLower().ToCharArray();
int iterations = (1 << array.Length) - 1;
for(int i = 0; i <= iterations; i++)
{
for(int j = 0; j < array.Length; j++)
array[j] = (i & (1<<j)) != 0
? char.ToUpper(array[j])
: char.ToLower(array[j]);
listPermutations.Add(new string(array));
}
return listPermutations;
}
ループの前にlistPermutatuions.Addを追加しましたあなたが完全に動作する以外は、完全に小文字のバージョンを保存します。 –
これはすべてを返すことはありません。たとえば、「haPpY」です。実際、上記のコードではn(n + 1)/ 2 + 1しか生成しませんが、2^n個の合計が必要です。 – newacct
そして、これがあなたのコードを常にテストしなければならない理由と、なぜオープンソースがうまく機能するのかです。ありがとうnewacct。私は実際に今回の実装をテストする時間を取っていました...そして、実際にはすべて2^nの置換を生成します。 – LBushkin
大まかに言って、以下のようなものです。私は自分の範囲を1つずつ持っているかもしれませんが、そのアイデアは健全です。
def cap_n(in_str, pos):
leading = in_str.substr(0, pos-1)
trailing = in_str.substr(pos+1) # no second arg implies to end of string
chr = in_str[pos].to_uppercase()
return leading + chr + trailing
ビット単位の操作を使用します。長さNの単語に対して、Nビットで表される整数型が必要です。単語が長い場合は、それを分割します。 0から2の値を反復してN -1とし、各ビットを0からN-1まで調べます。ビットが1 - アップケース(Char.ToUpper()
)の場合、そのビットに対応する文字。
このアプローチは、長い単語にスタックオーバーフローが発生しないため、再帰アルゴリズムより優れています。
許容される回答は、任意の文字を大文字にする最も簡単な方法ですが、大文字と小文字を同じ文字列(たとえば「幸せ」で32倍、指数関数的に増加する文字列)文字列をchar []に変換し、適切な文字を設定し、配列から文字列を構築する方が効率的です。
私は、2次元配列を作成した場合、索引0は小文字の単語、索引1は大文字の単語(char配列)としてどうでしょうか?その後、0から2 ^(word_length-1)までの繰り返しができ、整数のビットを使って各文字を取得する配列を教えてくれます。これがいいアイデアかどうかは本当に分かりません。私がこれを読んだとき、ちょうど私に来ました。 –
概念的には私はちょうどそのことをしましたが(ビットテスト部分)、私はその場所で単一の配列を修正しました。グレーコードを使用して、2 ^(word_length)-1の "case flips"で配列全体を生成できるようにするのが良い方法です。 – DocMax
グレーコードを提案するのに+1 –
はと仮定:
1)あなたは、これはO(N * 2^n)があることを...私はもののあまり気にしません好奇心が強い:このタイプの問題のための最良の漸近実行時間は何ですか?
2)あなたの入力はすべて小文字です。
3)入力は<で、長さは32文字です。 (転置カウンタの使用可能なビット数、i)
List<string> permutate(string word)
{
List<string> ret = new List<string>();
// MAGIC HAPPENS HERE
Dictionary<char,char> toUppers = new Dictionary<char,char>(26);
toUppers.Add('a', 'A');
toUppers.Add('b', 'B');
toUppers.Add('c', 'C');
toUppers.Add('d', 'D');
toUppers.Add('e', 'E');
toUppers.Add('f', 'F');
toUppers.Add('g', 'G');
toUppers.Add('h', 'H');
toUppers.Add('i', 'I');
toUppers.Add('j', 'J');
toUppers.Add('k', 'K');
toUppers.Add('l', 'L');
toUppers.Add('m', 'M');
toUppers.Add('n', 'N');
toUppers.Add('o', 'O');
toUppers.Add('p', 'P');
toUppers.Add('q', 'Q');
toUppers.Add('r', 'R');
toUppers.Add('s', 'S');
toUppers.Add('t', 'T');
toUppers.Add('u', 'U');
toUppers.Add('v', 'V');
toUppers.Add('w', 'W');
toUppers.Add('x', 'X');
toUppers.Add('y', 'Y');
toUppers.Add('z', 'Z');
char[] wordChars = word.ToCharArray();
int len = wordChars.Length;
// iterate the number of permutations
for(int i = 0; i < 2^len; i++) {
char[] newWord = new char[len]();
// apply "i" as a bitmask to each original char
for(int n = 0; n < newWord.Length; n++) {
if((1 << n) & i != 0) {
newWord[n] = toUppers[wordChars[n]]; // or skip the dictionary and just call Char.ToUpper(wordChars[n])
} else {
newWord[n] = wordChars[n];
}
}
ret.Add(new String(newWord));
}
return ret;
}
注:このコードをコンパイルまたはテストしていません。これは、上で提案したsharptoothのビット単位の比較も実装しています。
あなたの文字列を "並べ替える"ためには(技術的には、何の順序も変えていないので、これは順列ではありませんが、私は* l-retentive :-)と見なされたくありません。再帰的アプローチを使用します。再帰的アプローチは、文字列から最初の文字を差し引いた文字列を基本的に「置換」し、その文字の上位および下位のバリエーションにそれらを付加します。
ような何か(あなたはそれを変換する必要がありますので、Cには、私のC#はパーまで本当にありません):
:"permute Pax1"
リターンとしてこれを実行する
#include <stdio.h>
#include <string.h>
static void permute (char *prefix, char *str) {
char *newPrefix;
/* End of string, print and return. */
if (*str == '\0') {
printf ("%s\n", prefix);
return;
}
/* Allocate space for new prefix. */
if ((newPrefix = malloc (strlen (prefix) + 2)) == NULL) {
printf ("ERROR: Cannot allocate memory.\n");
return;
}
/* Do lowercase/sole version and upper version if needed. */
sprintf (newPrefix, "%s%c", prefix, *str);
permute (newPrefix, &(str[1]));
if (islower (*str) {
sprintf (newPrefix, "%s%c", prefix, toupper(*str));
permute (newPrefix, &(str[1]));
}
/* Free prefix and return. */
free (newPrefix);
}
int main (int argc, char *argv[]) {
char *str, *strPtr;
/* Check and get arguments. */
if (argc < 2) {
printf ("Usage: permute <string to permute>\n");
return 1;
}
if ((str = malloc (strlen (argv[1]) + 1)) == NULL) {
printf ("ERROR: Cannot allocate memory.\n");
return 1;
}
strcpy (str, argv[1]);
/* Convert to lowercase. */
for (strPtr = s; *strPtr != '\0'; strPtr++)
*strPtr = toupper (*strPtr);
/* Start recursion with empty prefix. */
permute ("", str);
/* Free and exit. */
free (str);
return 0;
}
pax1
paX1
pAx1
pAX1
Pax1
PaX1
PAx1
PAX1
これが何であるかは不思議ではありません。それが何らかの比較目的であれば、おそらく問題に近づくのは間違った方法でしょう。 –
これは辞書攻撃の可能性があります。 – sharptooth
実際には、パスワードをファイルに忘れてしまったので、大文字ではなく単語を知っています。 私の計画は、すべての可能性のあるものを計算し、それを辞書クラッカーにフィードすることです。 –