Зашифровать слово с помощью Java

Я хотел зашифровать строку, чтобы сделать ее нечитаемой, и поэтому придумал этот метод:

public String scrambleWord(String start_word){

     char[] wordarray = start_word.toCharArray();

        char[] dummywordarray = start_word.toCharArray();

        Random random = new Random();

        int r = random.nextInt(wordarray.length-1);
        int i = 0;

        int j = r+1;

        while(i <= r){

            dummywordarray[wordarray.length -i-1] = wordarray[i];

            i++;
        }


        while (j <= wordarray.length -1){

            dummywordarray[j-r-1] = wordarray[j];

            j++;

        }

        String newword = String.valueOf(dummywa);



        return newword;

Итак, я сначала преобразовал строку в массив символов, и в моем методе мне пришлось дублировать массив символов "dummywordarray". При однократном прохождении этого алгоритма каждая буква слова поменяет свое положение. Но она не будет очень хорошо перемешана, в том смысле, что вы сможете собрать ее обратно с первого взгляда. Итак, я передал заданную строку длиной менее 9 символов через метод 7 раз, и слова довольно хорошо зашифрованы, то есть нечитаемы. Но я попробовал это со строкой из 30 символов, и потребовалось 500 проходов, прежде чем я смог гарантировать, что она будет красиво зашифрована. 500! Я уверен, что есть лучший алгоритм, мне бы хотелось посоветовать либо а) улучшить этот метод, либо б) лучший способ.


person Community    schedule 22.11.2010    source источник
comment
Что вы имеете в виду под "красиво скремблированным"?   -  person Richard J. Ross III    schedule 22.11.2010
comment
Вы просто хотите перетасовать буквы в одну сторону, и это будет невосстановимо позже? Или вы на самом деле хотите, чтобы шифр создавал обратимую перетасовку?   -  person wkl    schedule 22.11.2010
comment
Красиво зашифровано довольно субъективно. Извините, я не могу дать вам правильное определение. Если исходное слово - возмутитель спокойствия, то makerelbuort, tromakbleuer не очень хорошо зашифрованы. Вы можете собрать их вместе через пять секунд.   -  person    schedule 22.11.2010
comment
Нет необходимости его реверсировать. Я просто хочу хорошую перетасовку, которая эффективна.   -  person    schedule 22.11.2010
comment
@JJG: Природа случайности заключается в том, что иногда нарушитель спокойствия будет случайным образом зашифрован как нарушитель спокойствия. Способность человеческого разума решать анаграммы или путаницы на разных стадиях перетасовки — гораздо более серьезная проблема, которая имеет мало общего с программированием.   -  person Mark Peters    schedule 22.11.2010
comment
Спасибо, Марк Питерс. Я знаю, что есть выбросы, где, возможно, может вернуться даже исходное слово. Но в большинстве случаев, когда я вставлял свою 30-символьную фразу (без пробелов) в алгоритм, чаще всего она собиралась обратно вместе без особых умственных усилий, если только я не прохожу описанный выше метод сотни раз. . Я предполагаю, что ожидалось, что мне придется прогонять слово через метод много раз, но я думал, что 500+ будет разумным.   -  person    schedule 22.11.2010
comment
@JJG: В этом случае Collections.shuffle - хороший алгоритм. Это в значительной степени гарантирует, что все перестановки равновероятны.   -  person Mark Peters    schedule 22.11.2010


Ответы (1)


Как насчет

ArrayList<Character> chars = new ArrayList<Character>(word.length());
for ( char c : word.toCharArray() ) {
   chars.add(c);
}
Collections.shuffle(chars);
char[] shuffled = new char[chars.size()];
for ( int i = 0; i < shuffled.length; i++ ) {
   shuffled[i] = chars.get(i);
}
String shuffledWord = new String(shuffled);

Другими словами, вы можете воспользоваться существующим java.util.Collections.shuffle(List) метод. К сожалению, вам придется пройти через пару обручей, чтобы использовать его, так как вы не можете использовать примитивы в Generics.

Редактировать:

Основной способ работы shuffle (полное объяснение см. в Javadoc) выглядит следующим образом:

for position = last_index to first_index
   let swap_pos = random number between first_index and position, inclusive
   swap(swap_pos, position)

Редактировать 2:

Этот подход значительно менее многословен с в Guava. Chars утилиты:

List<Character> chars = Chars.asList(word.toCharArray());
Collections.shuffle(chars);
String shuffledWord = new String(Chars.toArray(chars));
person Mark Peters    schedule 22.11.2010
comment
Красиво и просто. Вы можете использовать Arrays.asList(word.toCharArray()) для дальнейшего сокращения. - person Adamski; 22.11.2010
comment
@Adamski: я думаю, что это приведет к List<char[]>, поскольку Character[] не совпадает с char[]. - person Mark Peters; 22.11.2010
comment
Спасибо, я посмотрю на это. У меня нет большого опыта работы с дженериками, но я попробую. Но знаете ли вы алгоритм метода suffle(list)? Мне просто интересно, как они это делают. - person ; 22.11.2010
comment
Можете ли вы использовать char[] shuffled = chars.ToArray(char[] shuffled) для удаления второй конструкции for? - person Thomas Langston; 22.11.2010
comment
@Thomas: Нет, к сожалению, это не компилируется, опять же, поскольку char не применимо для параметра универсального типа. - person Mark Peters; 22.11.2010
comment
@JJG: ссылка, которую я включил, указывает на Javadoc, в котором подробно рассказывается о том, как работает алгоритм перемешивания. Я помещу резюме в свой пост. - person Mark Peters; 22.11.2010
comment
Обратите внимание, что это перетасовка Кнута или перетасовка Фишера-Йейтса. en.wikipedia.org/wiki/Shuffling#Randomization - person Thomas Langston; 22.11.2010
comment
Кажется, что мой алгоритм вычислительно тяжелее, чем должен быть, с большим отрывом. Хотя преимущество моей тасовки в том, что она позволяет мне установить степень сложности тасовки (с учетом тасовки слова, а не карт). - person ; 22.11.2010