Словарь‹char, char› для сопоставления алфавита с уникальными ключами и значениями

Мне нужно создать словарь, который выражает сопоставление между каждым символом в алфавите и другим символом в этом алфавите, где и ключ, и значение уникальны - как очень простой шифр, который выражает, как кодировать/декодировать сообщение. Не может быть повторяющихся ключей или значений.

Кто-нибудь видит, что не так с этим кодом? Он по-прежнему создает повторяющиеся значения в отображении, несмотря на то, что на каждой итерации пул доступных символов уменьшается для каждого уже использованного значения.

        string source_alphabet = _alphabet; //ie "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        string target_alphabet = _alphabet;

        Dictionary<char, char> _map = new Dictionary<char, char>();

        for (int i = 0; i < source_alphabet.Length; i++)
        {
            int random = _random.Next(target_alphabet.Length - 1); //select a random index

            char _output = target_alphabet[random]  //get the char at the random index

            _map.Add(source_alphabet[i], _output); //add to the dictionary

            target_alphabet = target_alphabet.Replace(_output.ToString(), string.Empty); 
            // remove the char we just added from the remaining alphabet
        } 

Спасибо.


person Sean Thoman    schedule 14.09.2011    source источник
comment
этот тип кода не гарантирует, что random всегда отличается от i, поэтому дубликаты могут (и обычно будут) происходить...   -  person Yahia    schedule 14.09.2011
comment
Это не должно иметь значения, потому что random не обязательно должно отличаться от i. Символ, который уже был добавлен в словарь в качестве значения, не должен даже находиться в доступном пуле символов для выбора. Если случайно A оказывается сопоставленным с A, это нормально. Просто в словаре не может быть повторяющихся значений.   -  person Sean Thoman    schedule 14.09.2011
comment
Удаляйте символ из target_alphabet каждый раз после создания случайного индекса.   -  person mishau    schedule 14.09.2011


Ответы (4)


Я бы рассмотрел возможность выполнения простого Fisher Yates перетасовать одну или обе последовательности алфавита, затем вы можете просто перебрать вывод и собрать воедино свой преобразователь.

Псевдокод

Shuffle(sequence1)
Shuffle(sequence2)

for index 0 to 25
    dictionary add sequence1[index], sequence2[index]

Когда вы пытаетесь выбрать случайное значение каждый раз, существует высокая вероятность того, что вы получите коллизию и, следовательно, выберете неуникальное значение. Ответ обычно состоит в том, чтобы перетасовать, а затем выбрать по порядку.

person Anthony Pegram    schedule 14.09.2011

«быстрое исправление», хотя и не оптимальное, было бы (если сопоставление A с A НЕ разрешено)

 int random = _random.Next(target_alphabet.Length - 1);
 while ( source_alphabet[i] == target_alphabet[random] ) {random = _random.Next(target_alphabet.Length - 1);};

если сопоставление A с A разрешено, игнорируйте вышеуказанное изменение... НО, по крайней мере, измените последнюю строку на

target_alphabet = target_alphabet.Remove ( random, 1 );
person Yahia    schedule 14.09.2011
comment
Не уверен, почему, но я все еще получаю дубликаты, использую ли я .Replace() или .Remove() или метод Array.FindAll(), который опубликовал Мишау. Я думаю, может быть, что-то еще происходит, потому что это должно работать. - person Sean Thoman; 14.09.2011
comment
Тогда в коде должно быть что-то не показанное... это многопоточность? любые статические переменные? любые повторяющиеся имена переменных, которые могут вызвать некоторые проблемы? - person Yahia; 14.09.2011

Я думаю, вы могли бы добавить еще один цикл «для» в target_alphabet внутри существующего цикла «для» и проверить, не совпадают ли символы с небольшим условием «если», и продолжить внутренний цикл, если то же самое, или прервать, если нет.

person Praveen    schedule 14.09.2011

Это работает.

 for (int i = 0; i < source_alphabet.Length; i++)
    {
        int random = _random.Next(target_alphabet.Length - 1); //select a random index

        char _output = target_alphabet[random];  //get the char at the random index


        _map.Add(source_alphabet[i], _output); //add to the dictionary

        // remove the char we just added from the remaining alphabet
        target_alphabet = target_alphabet.Remove(random, 1);


    }
person mishau    schedule 14.09.2011