Повтор участка кода по заданному значению int. Помогите решить задачку по шифрованию :)

Всем доброго дня! Решаю задачку, суть которой следующая: Методу дается строка String text и число int n. Все эти данные передаются в final статусе. Необходимо отделить все четные знаки в text от нечетных и проделать это столько раз, сколько задано в n. Если n=0 или -n, то ничего не делается.

К примеру, "This is a test!" при n=1 ---> "hsi etTi sats!", а при n=2 *"s eT ashi tist!"*и так далее. Эта перестановка должна быть, скажем так, n-times.

Не много покипев мозгами я пришел к следующему:

public static String encrypt(final String text, final int n){

        String result ="";

        int t = n;// временная переменная t для подсчета кол-ва проходов шифрования

        Character [] textArr = new Character[text.length()];
            for (int i = 0;i<text.length();i++){
                textArr[i] = text.charAt(i);
            }

        List<Character> charArr = Arrays.asList(textArr);

        List<Character> oddCharArr = new ArrayList<>();
        List<Character> evenCharArr = new ArrayList<>();

        List<Character> tempCharArr = new ArrayList<>(charArr);

 


            for (int i = 0; i < tempCharArr.size(); i++) {
                if (i % 2 == 0) {
                    evenCharArr.add(tempCharArr.get(i));
                } else oddCharArr.add(tempCharArr.get(i));
                tempCharArr.addAll(oddCharArr);
                tempCharArr.addAll(evenCharArr);
            }

Мысль такая, строку разделить на массив Char, а за тем циклом пройти по этому массиву и разделить все четные и нечётные символы на два доп. массива. За тем, финальный массив перевести в строку. В моем случае я делаю через List.

Перестановка вроде получилась. Массив собирается правильно, но только один раз.

Пытался сделать через while, но безуспешно. Подскажите, как мне лучше и эффективнее сделать это действие n-раз?

И сразу вопрос в догонку, в другом методе надо вернуть все как было изначально. Подскажите, или хотя бы намекните алгоритм как это сделать :)

Заранее благодарю!

UPD (для Дмитрий Алексеенко):

public static String encrypt(final String text, final int n) {
    String result ="";

    int t = n;// временная переменная t для подсчета кол-ва проходов шифрования
    Character [] textArr = new Character[text.length()];
        for (int i = 0;i<text.length();i++){
            textArr[i] = text.charAt(i);
        }

    List<Character> charArr = Arrays.asList(textArr);
    List<Character> oddCharArr = new ArrayList<>();
    List<Character> evenCharArr = new ArrayList<>();

    List<Character> tempCharArr = new ArrayList<>();

        for (int i = 0; i < charArr.size(); i++) {
            if (i % 2 == 0) {
                evenCharArr.add(charArr.get(i));
            } else oddCharArr.add(charArr.get(i));
        }
    tempCharArr.addAll(oddCharArr);
    tempCharArr.addAll(evenCharArr);
    System.out.println(tempCharArr.toString());


    return result;
}

Надеюсь на помощь)) Выше выложил код, который работает, но всего один раз.

Теперь надо сделать так, чтобы он делал эту перестановку заданное кол-во раз. Вот с этим у меня и проблемы. Неделю голову выношу себе и нарываюсь на бесконечные циклы)

Можете хотя бы подсказать как тут лучше это реализовать? А то вообще грусть(


Ответы (2 шт):

Автор решения: Дмитрий Алексеенко

думаю можно попробовать как-то так

public static void main(String[] args) {
//        String result ="";
        String text = "This is a test!";
        int t = 2;// временная переменная t для подсчета кол-ва проходов шифрования
        while (t != 0) {
            List<String> blablaList = getBlaBlaList(text);
            text = blablaConvert(blablaList);
            t--;
        }
        System.out.println(text);


    }

    public static  List<String> getBlaBlaList(String text) {
        List<String> ret = new ArrayList<>();
        List<String> even = new ArrayList<>();
        List<String> odd = new ArrayList<>();
        for (int i = 0; i < text.length(); i++) {
            if (i % 2 == 0) {
                even.add(text.substring(i, i + 1));
                continue;
            }
            odd.add(text.substring(i, i + 1));
        }
        ret.addAll(even);
        ret.addAll(odd);
        return ret;
    }

    public static String blablaConvert(List<String> blablaList) {
        String ret = "";
        for (int i = 0; i < blablaList.size(); i++) {
            if (i % 2 == 0) {
                ret += blablaList.get(i);
                continue;
            }
            ret += blablaList.get(i);
        }
        return ret;
    }
→ Ссылка
Автор решения: MBo

В качестве альтернативы предложу такой метод - вместо того, чтобы переколбашивать строку много раз, вычислим место, на которое встанет каждый символ после n преобразований, и поставим его сразу на нужное место. Аналогично можно сделать и с обратными преобразованием.

Замечу, что для каждой длины строки есть значение p (вот оно), при котором строка возвращается в начальное состояние, поэтому в принципе для больших n можно делать n%p преобразований, ну да ладно, p нетривиально.

Демонстрация принципа на Python:

def shuf(s, n):
    le = len(s)
    half = (le) // 2
    result = ['']*le  # список такой же длины, как строка
    for idx in range(0, le):
        t = idx
        for k in range(n):
                t = (t + 1)%2 * half  + t // 2
        result[t] = s[idx]
    return ''.join(result)   #склейка символов из списка в строку

for n in range(1,5):
    print(n, shuf("This is a test!", n))


1 hsi  etTi sats!
2 s eT ashi tist!
3  Tah itse sits!
4 This is a test!
→ Ссылка