Loading...
DimovIvan avatar DimovIvan 16 Точки

Codingame - Encryption-Decryption of Enigma Machine

Може ли малко разяснения относно задачата:  Encryption-Decryption of Enigma Machine в codingame.

Така както е зададен дефолтния код в задачата, според мен не може да се реши задачата защото четем съобщението едва след като сме прочели трите ротора. По този начин, след завъртането на цикъла, можем да работим само с третия ротор, а така не може да се реши задачата. Аз направих едно решение, което работи коректно, но играта не ми го приема.

https://pastebin.com/yiduuj3D

Тагове:
0
C++ Fundamentals
j.petrov_90 avatar j.petrov_90 373 Точки

Привет, колега,

Задачата си има условие, което трябва да спазваш.
Входните данни в задачата са копектни, но ти правилно си разбрал, че това е само СКЕЛЕТ, с който може да се прочете входа.

Част от решението на задачата е да измислиш как да промениш този скелет, така че да работи.
Щом ти се дават 3 ротора един след друг и чак след това съобщението...трябва да се досетиш, че трябва да съхраниш някъде тези прочетени ротори.
На по-късен етап от задачата вече може да ги ползваш.

Забележи, че имаш доста повтарящ се код при четене на роторите. Това може да е ... функция.
Забележи, че не е нужно да имаш 3 променливи...можеш да имаш масив.
Опитай да вкараш логиката за ENCODE and DECODE във собствени си функции.

Задачата изобщо не е лесна!
Това не значи, че не можеш да се забавляваш, докато я решаваш :)
Успех!
 

0
21/04/2021 11:40:14
DimovIvan avatar DimovIvan 16 Точки

Благодаря за разясненията и забележките! Пооправих си малко кода и дори първият ми тест мина успешно. Но на останалите се провалям. Програмата ми се чупи със съобщение: string subscript out of range. Кой стринг ми е извън обхват не знам. И ако е така защо ми минава първият тест? 

https://pastebin.com/yiduuj3D

0
j.petrov_90 avatar j.petrov_90 373 Точки

Привет,

Предполагам проблема ти е тук:
std::string decryptedRotorMsg(std::string& msg, const std::string& rotor) {
    const std::vector<int> msgIndexes = getMsgIndexes(msg);
    const size_t arrSize = msgIndexes.size();
    for (size_t i = 0; i < arrSize; i++)
    {
        msg[i] = getAlphaFromIndex(rotor.find(msg[i]));
    }
    return msg;
}

В msg[i] достъпваш несъщестнуващ индекс.
Пробвай да принтираш на cerr различни неща в твоята задача и ще видиш проблема.

Първия тест ти минава, защото е "прост" и не покрива голяма част от подводните камъни.

1
j.petrov_90 avatar j.petrov_90 373 Точки

void printEncryptedMsg(const std::vector<std::string>& rotors, std::string& masage, const int& pseudoRandomNumber) {
    std::string shiftMsg = caesarShift(pseudoRandomNumber, masage);
    std::string encryptedMsgAfterFirstRotor = encryptedRotorMsg(shiftMsg, rotors[0]);
    std::string encryptedMsgAfterSecondRotor = encryptedRotorMsg(encryptedMsgAfterFirstRotor, rotors[1]);
    std::string encryptedMsgAfterThirdRotor = encryptedRotorMsg(encryptedMsgAfterSecondRotor, rotors[2]);
    std::cout << encryptedMsgAfterThirdRotor << std::endl;
}

Това може да стане с един цикъл.

Нямаш нужда от нови променливи.

1
DimovIvan avatar DimovIvan 16 Точки

Проблема ми беше в caesarShift функцията. Оправих я. Сега ми остана да оправя само deCaesarShift функцията. Вече ми гърми само последният тест. А това за цикъла, не знам как ще стане.

0
kolioi avatar kolioi 641 Точки

Почти си го направил smiley Най-важното в тази задача е да изчислиш правилно индексите, т.е, отместването спрямо началото на масива. Задачата не е сложна, обаче се старай да пишеш по-изчистен и прост код. Това ще ти намали потенциалните грешки. Ето ти едно примерно имплементиране на функцията caesarShift()

void CaesarShift(string& msg, const int n)
{
    constexpr int len = 'Z' - 'A' + 1;
    for (size_t i = 0; i < msg.length(); i++)
    {
        msg[i] = 'A' + (msg[i] + n + i - 'A') % len;
    }
}

По подобен начин можеш да направиш deCaesarShift(). Останалите функции са също толкова прости.

0
DimovIvan avatar DimovIvan 16 Точки

Грешката ми беше в caesarShift и deCaesarShift функциите. Оправих ги като си направих една променлива  char newAlpha = msg[i] - number - i; за deCaesarShift и int newAlpha = msg[i] + number + i; за  caesarShift. В caesarShift функцията променливата ми е от тип int защото ако е char ми дава грешка като излезе от обхвата на ASCII таблицата. В deCaesarShift функцията малко бабешки съм направил проверките, но не можах да се сетя за друг начин. Относно забележката, че не използвам цикъл за извикването на функциите encryptedRotorMsg и decryptedRotorMsg, не можах да го измисля. При всяко викане на тези функции използвам различен message като параметър и не знам как ще стане да ги викам в цикъл. Иначе, минавам всички тестове, но ми дава 66% защото имам хардкоднато решение. Но това са ми възможностите.

https://pastebin.com/edit/yiduuj3D

0
DimovIvan avatar DimovIvan 16 Точки

Благодаря за добрата идея! Вече ми дава 100%

0
DimovIvan avatar DimovIvan 16 Точки

Измислих, поне според мен, по-разбираемо решение за caesarShift функцията.

std::string caesarShift(const int& number, std::string& msg) {

    const size_t msgSize = msg.size();

    for (size_t i = 0; i < msgSize; i++)

    {

        int increaseLetter = msg[i] + number + i;

        for(int j = msg[i]; j < increaseLetter; j++){

            msg[i]++;

            if (msg[i] == 'Z' + 1) {

                msg[i] = 'A';

            } 

        }

    }

    return msg;

}

0
24/04/2021 10:29:26
kolioi avatar kolioi 641 Точки

Съветвам те да разгледаш други решения на задачата. Има доста интересни решения, някои от тях използват std::transform(), ламбда функции и дори темплейти. Има какво да научиш, най-малкото ще видиш как да викаш роторите в цикъл, макар че за някои решения това е излишно.

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.