Codingame - Encryption-Decryption of Enigma Machine
Може ли малко разяснения относно задачата: Encryption-Decryption of Enigma Machine в codingame.
Така както е зададен дефолтния код в задачата, според мен не може да се реши задачата защото четем съобщението едва след като сме прочели трите ротора. По този начин, след завъртането на цикъла, можем да работим само с третия ротор, а така не може да се реши задачата. Аз направих едно решение, което работи коректно, но играта не ми го приема.
https://pastebin.com/yiduuj3D
Благодаря за разясненията и забележките! Пооправих си малко кода и дори първият ми тест мина успешно. Но на останалите се провалям. Програмата ми се чупи със съобщение: string subscript out of range. Кой стринг ми е извън обхват не знам. И ако е така защо ми минава първият тест?
https://pastebin.com/yiduuj3D
Привет,
Предполагам проблема ти е тук:
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 различни неща в твоята задача и ще видиш проблема.
Първия тест ти минава, защото е "прост" и не покрива голяма част от подводните камъни.
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;
}
Това може да стане с един цикъл.
Нямаш нужда от нови променливи.
Проблема ми беше в caesarShift функцията. Оправих я. Сега ми остана да оправя само deCaesarShift функцията. Вече ми гърми само последният тест. А това за цикъла, не знам как ще стане.
Почти си го направил Най-важното в тази задача е да изчислиш правилно индексите, т.е, отместването спрямо началото на масива. Задачата не е сложна, обаче се старай да пишеш по-изчистен и прост код. Това ще ти намали потенциалните грешки. Ето ти едно примерно имплементиране на функцията caesarShift()
По подобен начин можеш да направиш deCaesarShift(). Останалите функции са също толкова прости.
Грешката ми беше в 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
Благодаря за добрата идея! Вече ми дава 100%
Измислих, поне според мен, по-разбираемо решение за 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;
}
Съветвам те да разгледаш други решения на задачата. Има доста интересни решения, някои от тях използват std::transform(), ламбда функции и дори темплейти. Има какво да научиш, най-малкото ще видиш как да викаш роторите в цикъл, макар че за някои решения това е излишно.