2

ランダム化されたアルファベットのすべての文字の文字列が必要です。現在、26 文字の変更可能な配列を作成し、exchangeObjectAtIndex: メソッドでそれらをシャッフルしてから、返す文字列に各文字を追加しています。

これを行うためのより良い方法が必要です。これが私のコードです:

- (NSString *)shuffledAlphabet {
    NSMutableArray * shuffledAlphabet = [NSMutableArray arrayWithArray:@[@"A",@"B",@"C",@"D",@"E",@"F",@"G",@"H",@"I",@"J",@"K",@"L",@"M",@"N",@"O",@"P",@"Q",@"R",@"S",@"T",@"U",@"V",@"W",@"X",@"Y",@"Z"]];

    for (NSUInteger i = 0; i < [shuffledAlphabet count]; ++i) {
        // Select a random element between i and end of array to swap with.
        int nElements = [shuffledAlphabet count] - i;
        int n = (random() % nElements) + i;
        [shuffledAlphabet exchangeObjectAtIndex:i withObjectAtIndex:n];
    }

    NSString *string = [[NSString alloc] init];
    for (NSString *letter in shuffledAlphabet) {
        string = [NSString stringWithFormat:@"%@%@",string,letter];
    }

    return string;
}
4

4 に答える 4

7

これは、ユースケースに合わせた効率的なFisher-Yates shuffleです。

- (NSString *)shuffledAlphabet {
    NSString *alphabet = @"ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    // Get the characters into a C array for efficient shuffling
    NSUInteger numberOfCharacters = [alphabet length];
    unichar *characters = calloc(numberOfCharacters, sizeof(unichar));
    [alphabet getCharacters:characters range:NSMakeRange(0, numberOfCharacters)];

    // Perform a Fisher-Yates shuffle
    for (NSUInteger i = 0; i < numberOfCharacters; ++i) {
        NSUInteger j = (arc4random_uniform(numberOfCharacters - i) + i);
        unichar c = characters[i];
        characters[i] = characters[j];
        characters[j] = c;
    }

    // Turn the result back into a string
    NSString *result = [NSString stringWithCharacters:characters length:numberOfCharacters];
    free(characters);
    return result;
}
于 2013-01-15T15:59:57.443 に答える
2

これは、正しくシャッフルされたアルファベットの生成を実行するためのより効率的な方法です。

- (NSString *)shuffledAlphabet
{
    const NSUInteger length = 'Z' - 'A' + 1;
    unichar alphabet[length];
    alphabet[0] = 'A';

    for ( NSUInteger i = 1; i < length; i++ )
    {
        NSUInteger j = arc4random_uniform((uint32_t)i + 1);
        alphabet[i] = alphabet[j];
        alphabet[j] = 'A' + i;
    }
    return [NSString stringWithCharacters:alphabet length:length];
}

これは、フィッシャーイェーツシャッフルの「裏返し」バージョンを使用し、。を使用して疑似乱数を生成することにより、モジュラバイアスを回避しarc4random_uniformます。また、すべての順列は一時バッファーで実行されるため、単一の割り当てが必要です。

于 2013-01-15T16:03:03.887 に答える
1

Objective-C で乱数を生成することは役に立ちますか? *乱数を生成 *26で割ってリマインダーを取る *インデックス配列[リマインダー]

于 2013-01-15T15:33:29.687 に答える
0

最初にシャッフルするのではなく、文字列を作成するときに、(残りの) アルファベットからランダムな要素を選択できます。

NSMutableArray *alphabet = [NSMutableArray arrayWithObjects:@"A",@"B",@"C",@"D",@"E",@"F",@"G",@"H",@"I",@"J",@"K",@"L",@"M",@"N",@"O",@"P",@"Q",@"R",@"S",@"T",@"U",@"V",@"W",@"X",@"Y",@"Z", nil];
NSMutableString *result = [NSMutableString string];
NSUInteger numberOfLetters = alphabet.count;
for (NSUInteger i = 0; i < numberOfLetters; i++) {
    int n = arc4random() % alphabet.count;
    [result appendString:[alphabet objectAtIndex:n]];
    [alphabet removeObjectAtIndex:n];
}
NSLog(@"%@", result);

これにより、コードが少し短くなります。文字が追加されるたびNSMutableStringに新しい文字列を作成するよりも、文字列を使用する方が効率的であることにも注意してください。NSString

于 2013-01-15T15:39:47.960 に答える