![Изображение записи](https://selectel.ru/blog/wp-content/uploads/2024/08/MD-3091.jpg)
Условие
Андрей пришел на стажировку в команду информационной безопасности. Он учится в университете на профильном направлении, но многих практических знаний пока не хватает. Чтобы помочь стажеру, его бадди Сережа дает разные задания.
В этот раз Андрей спросил, как работают алгоритмы шифрования, с помощью которых хакеры могут испортить почти все данные компании. Сережа предложил посмотреть на практике и написать код, который будет подбирать ключ для расшифровки несложного шифра. Для первого раза решили остановиться на шифре Цезаря.
Задача
Помогите Андрею расшифровать текст.
Входные данные:
Jwm kxcq cqjc vxawrwp nzdjuuh ujh Rw unjenb wx bcny qjm caxmmnw kujlt. Xq, R tnyc cqn orabc oxa jwxcqna mjh! Hnc twxfrwp qxf fjh unjmb xw cx fjh, R mxdkcnm ro R bqxdum nena lxvn kjlt. R bqjuu kn cnuurwp cqrb frcq j brpq Bxvnfqnan jpnb jwm jpnb qnwln: Cfx axjmb mrenapnm rw j fxxm, jwm R— R cxxt cqn xwn unbb cajenunm kh, Jwm cqjc qjb vjmn juu cqn mroonanwln.
Как разгадать шифр
В шифре Цезаря каждый символ заменяется на другой символ со сдвигом на три. То есть символ A заменяется на D, символ B — на E, символ Z на C. Можно использовать и другие сдвиги — например, на две буквы или шесть.
Сережа предложил Андрею написать такую функцию, которая будет определять, зашифрован ли текст методом со сдвигом и если да, то каков сдвиг.
В реальной жизни если произошла хакерская атака и данные зашифрованы, то расшифровать их крайне сложно, иногда приходится идти на сделку с мошенниками.
Для практики предположим, что некоторые строки мы можем расшифровать с помощью метода со сдвигом. Пусть система получает на входе зашифрованную строку. Задача — написать алгоритм, который выведет «False», если текст не зашифрован методом со сдвигом, или число, обозначающее сдвиг, и расшифрованную строку, если шифр применим.
Решение
Нам известно, что использован шифр Цезаря, поэтому можно смело выбрать несколько вариантов решения.
Воспользоваться статистическим анализом. Как и любой перестановочный шифр, шифр Цезаря подвергается взлому путем анализа частоты появления каждого символа в шифротексте. Для алфавитов существуют таблицы, отражающие частоту появления букв в тексте.
Решение с использованием таблицы частотности
Так как шифротекст на английском языке, можно взять, например, таблицу Letter frequency.
Использовать старый добрый брутфорс. То есть перебрать все варианты сдвигов (для английского языка возможны 25 вариантов) и проанализировать дешифрованные тексты.
Напишем следующий код на Python:
#импорт модуля для работы с регулярными выражениями
import re
#исходный шифротекст
text = 'Jwm kxcq cqjc vxawrwp nzdjuuh ujh Rw unjenb wx bcny qjm caxmmnw kujlt. Xq, R tnyc cqn orabc oxa jwxcqna mjh! Hnc twxfrwp qxf fjh unjmb xw cx fjh, R mxdkcnm ro R bqxdum nena lxvn kjlt. R bqjuu kn cnuurwp cqrb frcq j brpq Bxvnfqnan jpnb jwm jpnb qnwln: Cfx axjmb mrenapnm rw j fxxm, jwm R— R cxxt cqn xwn unbb cajenunm kh, Jwm cqjc qjb vjmn juu cqn mroonanwln.'
#от исходной строки оставляем только буквы и делаем их все строчными
string = re.sub("[^A-Za-z]", "", text.lower())
#подготовим словарь
dict = {'a':0, 'b':0, 'c':0, 'd':0, 'e':0, 'f':0, 'g':0, 'h':0, 'i':0, 'j':0, 'k':0, 'l':0, 'm':0, 'n':0, 'o':0, 'p':0, 'q':0, 'r':0, 's':0, 't':0, 'u':0, 'v':0, 'w':0, 'x':0, 'y':0, 'z':0}
#и список
list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
#пустой словарь для данных в процентах
dict_percents = {}
#в этой функции будет происходить статистический анализ букв в исходном шифротексте
def analyze ():
#проходимся по каждой букве исходного шифротекста и при совпадении с ключом в словаре увеличиваем значение в словаре на единицу
for i in string:
dict[i] += 1
#циклом проходим по всем элементам словаря и вычисляем частоту появления каждой буквы как отношение количества появлений буквы к общему количеству букв в исходном шифротексте; умножаем на 100 и округляем до одного символа после запятой
for i in dict:
dict_percents[i] = round(dict[i] / len(string) * 100, 1)
#и возвращаем сортированный список
return sorted(dict_percents.items(), key=lambda item: item[1], reverse=True)
#функция преобразования шифротекста путем сдвига символов на заданное количество
def move(count):
result = ''
#используем исходный шифротекст, чтобы в дешифрованном варианте сохранились символы помимо букв
for i in text.lower():
if i.isalpha():
result += list[(list.index(i) + count) % 26]
else:
result += i
return result
if __name__ == "__main__":
#вызов функции анализа
print('\n' + 'Сортированный список в процентах:', analyze())
#количество шагов для сдвига
count = 0
#вызов функции сдвига с указанным количеством шагов
print("Сдвиг:", count, "Исходный текст:", move(count))
#цикл для брутфорса
for i in range(1,26):
print('*' * 50, '\n', "Сдвиг:", i, "Исходный текст:", move(i))
Вызываем сначала только функцию analyze():
if __name__ == "__main__":
#вызов функции анализа
print('\n' + 'Сортированный список в процентах:', analyze())
И получаем результат:
Сортированный список в процентах: [('n', 12.6), ('j', 9.7), ('c', 7.9), ('x', 7.9), ('m', 6.9), ('q', 6.5), ('r', 6.5), ('w', 6.5), ('b', 5.4), ('u', 5.4), ('a', 4.0), ('f', 2.9), ('h', 2.5), ('p', 2.5), ('k', 2.2), ('l', 1.8), ('o', 1.8), ('t', 1.8), ('e', 1.4), ('v', 1.4), ('d', 1.1), ('y', 0.7), ('z', 0.4), ('g', 0.0), ('i', 0.0), ('s', 0.0)]
Теперь обращаемся к таблице частоты букв Letter frequency. В исходном шифротексте чаще всего встречалась буква n — 12.6%. В таблице наибольшее значение имеет буква e — 13%. Так как исходный шифротекст небольшой, то частотное распределение может не полностью соответствовать эталонным значениям.
Следующими кандидатами из таблицы будут:
- t — 9.1%;
- a — 8.2%.
Проверим гипотезу: попробуем преобразовать исходный шифротекст так, чтобы сдвиг менял e на n. Так как в коде…
result += list[(list.index(i) + count) % 26]
…мы описали только сдвиг при дешифровании вправо, необходимо посчитать количество шагов от n к e слева направо. Получается 17.
Вызываем функцию сдвига с аргументом 17:
if __name__ == "__main__":
#количество шагов для сдвига
count = 17
#вызов функции сдвига с указанным количеством шагов
print("Сдвиг:", count, "Исходный текст:", move(count))
И получаем:
Сдвиг: 17 Исходный текст: and both that morning equally lay in leaves no step had trodden black. oh, i kept the first for another day! yet knowing how way leads on to way, i doubted if i should ever come back. i shall be telling this with a sigh somewhere ages and ages hence: two roads diverged in a wood, and i— i took the one less traveled by, and that has made all the difference.
Похоже, все получилось. Чтобы проверить решение, попробуем сдвинуть текст на другие значения.
Сдвиг на пять символов:
if __name__ == "__main__":
#количество шагов для сдвига
count = 5
#вызов функции сдвига с указанным количеством шагов
print("Сдвиг:", count, "Исходный текст:", move(count))
Результат:
Сдвиг: 5 Исходный текст: obr pchv hvoh acfbwbu seiozzm zom wb zsojsg bc ghsd vor hfcrrsb pzoqy. cv, w ysdh hvs twfgh tcf obchvsf rom! msh ybckwbu vck kom zsorg cb hc kom, w rciphsr wt w gvcizr sjsf qcas poqy. w gvozz ps hszzwbu hvwg kwhv o gwuv gcaskvsfs ousg obr ousg vsbqs: hkc fcorg rwjsfusr wb o kccr, obr w— w hccy hvs cbs zsgg hfojszsr pm, obr hvoh vog aors ozz hvs rwttsfsbqs.
Сдвиг на 10 символов:
if __name__ == "__main__":
#количество шагов для сдвига
count = 10
#вызов функции сдвига с указанным количеством шагов
print("Сдвиг:", count, "Исходный текст:", move(count))
Результат:
Сдвиг: 10 Исходный текст: tgw uhma matm fhkgbgz xjnteer etr bg extoxl gh lmxi atw mkhwwxg uetvd. ha, b dxim max ybklm yhk tghmaxk wtr! rxm dghpbgz ahp ptr extwl hg mh ptr, b whnumxw by b lahnew xoxk vhfx utvd. b latee ux mxeebgz mabl pbma t lbza lhfxpaxkx tzxl tgw tzxl axgvx: mph khtwl wboxkzxw bg t phhw, tgw b— b mhhd max hgx exll mktoxexw ur, tgw matm atl ftwx tee max wbyyxkxgvx.
Решение методом перебора
Переберем все возможные варианты сдвигов и проанализируем каждый дешифрованный текст.
В ранее написанном коде вызываем метод сдвига в цикле:
if __name__ == "__main__":
#цикл для брутфорса
for i in range(1,26):
print('*' * 50, '\n', "Сдвиг:", i, "Исходный текст:", move(i))
Получаем результат:
**************************************************
Сдвиг: 1 Исходный текст: kxn lydr drkd wybxsxq oaekvvi vki sx vokfoc xy cdoz rkn dbynnox lvkmu. yr, s uozd dro psbcd pyb kxydrob nki! iod uxygsxq ryg gki voknc yx dy gki, s nyeldon sp s cryevn ofob mywo lkmu. s crkvv lo dovvsxq drsc gsdr k csqr cywogrobo kqoc kxn kqoc roxmo: dgy byknc nsfobqon sx k gyyn, kxn s— s dyyu dro yxo vocc dbkfovon li, kxn drkd rkc wkno kvv dro nsppoboxmo.
**************************************************
Сдвиг: 2 Исходный текст: lyo mzes esle xzcytyr pbflwwj wlj ty wplgpd yz depa slo eczoopy mwlnv. zs, t vpae esp qtcde qzc lyzespc olj! jpe vyzhtyr szh hlj wplod zy ez hlj, t ozfmepo tq t dszfwo pgpc nzxp mlnv. t dslww mp epwwtyr estd htes l dtrs dzxphspcp lrpd lyo lrpd spynp: ehz czlod otgpcrpo ty l hzzo, lyo t— t ezzv esp zyp wpdd eclgpwpo mj, lyo esle sld xlop lww esp otqqpcpynp.
**************************************************
Сдвиг: 3 Исходный текст: mzp naft ftmf yadzuzs qcgmxxk xmk uz xqmhqe za efqb tmp fdappqz nxmow. at, u wqbf ftq rudef rad mzaftqd pmk! kqf wzaiuzs tai imk xqmpe az fa imk, u pagnfqp ur u etagxp qhqd oayq nmow. u etmxx nq fqxxuzs ftue iuft m eust eayqitqdq msqe mzp msqe tqzoq: fia dampe puhqdsqp uz m iaap, mzp u— u faaw ftq azq xqee fdmhqxqp nk, mzp ftmf tme ympq mxx ftq purrqdqzoq.
**************************************************
Сдвиг: 4 Исходный текст: naq obgu gung zbeavat rdhnyyl ynl va yrnirf ab fgrc unq gebqqra oynpx. bu, v xrcg gur svefg sbe nabgure qnl! lrg xabjvat ubj jnl yrnqf ba gb jnl, v qbhogrq vs v fubhyq rire pbzr onpx. v funyy or gryyvat guvf jvgu n fvtu fbzrjurer ntrf naq ntrf urapr: gjb ebnqf qviretrq va n jbbq, naq v— v gbbx gur bar yrff geniryrq ol, naq gung unf znqr nyy gur qvssrerapr.
**************************************************
Сдвиг: 5 Исходный текст: obr pchv hvoh acfbwbu seiozzm zom wb zsojsg bc ghsd vor hfcrrsb pzoqy. cv, w ysdh hvs twfgh tcf obchvsf rom! msh ybckwbu vck kom zsorg cb hc kom, w rciphsr wt w gvcizr sjsf qcas poqy. w gvozz ps hszzwbu hvwg kwhv o gwuv gcaskvsfs ousg obr ousg vsbqs: hkc fcorg rwjsfusr wb o kccr, obr w— w hccy hvs cbs zsgg hfojszsr pm, obr hvoh vog aors ozz hvs rwttsfsbqs.
**************************************************
Сдвиг: 6 Исходный текст: pcs qdiw iwpi bdgcxcv tfjpaan apn xc atpkth cd hite wps igdsstc qaprz. dw, x ztei iwt uxghi udg pcdiwtg spn! nti zcdlxcv wdl lpn atpsh dc id lpn, x sdjqits xu x hwdjas tktg rdbt qprz. x hwpaa qt itaaxcv iwxh lxiw p hxvw hdbtlwtgt pvth pcs pvth wtcrt: ild gdpsh sxktgvts xc p ldds, pcs x— x iddz iwt dct athh igpktats qn, pcs iwpi wph bpst paa iwt sxuutgtcrt.
**************************************************
Сдвиг: 7 Исходный текст: qdt rejx jxqj cehdydw ugkqbbo bqo yd buqlui de ijuf xqt jhettud rbqsa. ex, y aufj jxu vyhij veh qdejxuh tqo! ouj ademydw xem mqo buqti ed je mqo, y tekrjut yv y ixekbt uluh secu rqsa. y ixqbb ru jubbydw jxyi myjx q iywx iecumxuhu qwui qdt qwui xudsu: jme heqti tyluhwut yd q meet, qdt y— y jeea jxu edu buii jhqlubut ro, qdt jxqj xqi cqtu qbb jxu tyvvuhudsu.
**************************************************
Сдвиг: 8 Исходный текст: reu sfky kyrk dfiezex vhlrccp crp ze cvrmvj ef jkvg yru kifuuve scrtb. fy, z bvgk kyv wzijk wfi refkyvi urp! pvk befnzex yfn nrp cvruj fe kf nrp, z uflskvu zw z jyflcu vmvi tfdv srtb. z jyrcc sv kvcczex kyzj nzky r jzxy jfdvnyviv rxvj reu rxvj yvetv: knf ifruj uzmvixvu ze r nffu, reu z— z kffb kyv fev cvjj kirmvcvu sp, reu kyrk yrj druv rcc kyv uzwwvivetv.
**************************************************
Сдвиг: 9 Исходный текст: sfv tglz lzsl egjfafy wimsddq dsq af dwsnwk fg klwh zsv ljgvvwf tdsuc. gz, a cwhl lzw xajkl xgj sfglzwj vsq! qwl cfgoafy zgo osq dwsvk gf lg osq, a vgmtlwv ax a kzgmdv wnwj ugew tsuc. a kzsdd tw lwddafy lzak oalz s kayz kgewozwjw sywk sfv sywk zwfuw: log jgsvk vanwjywv af s oggv, sfv a— a lggc lzw gfw dwkk ljsnwdwv tq, sfv lzsl zsk esvw sdd lzw vaxxwjwfuw.
**************************************************
Сдвиг: 10 Исходный текст: tgw uhma matm fhkgbgz xjnteer etr bg extoxl gh lmxi atw mkhwwxg uetvd. ha, b dxim max ybklm yhk tghmaxk wtr! rxm dghpbgz ahp ptr extwl hg mh ptr, b whnumxw by b lahnew xoxk vhfx utvd. b latee ux mxeebgz mabl pbma t lbza lhfxpaxkx tzxl tgw tzxl axgvx: mph khtwl wboxkzxw bg t phhw, tgw b— b mhhd max hgx exll mktoxexw ur, tgw matm atl ftwx tee max wbyyxkxgvx.
**************************************************
Сдвиг: 11 Исходный текст: uhx vinb nbun gilhcha ykouffs fus ch fyupym hi mnyj bux nlixxyh vfuwe. ib, c eyjn nby zclmn zil uhinbyl xus! syn ehiqcha biq qus fyuxm ih ni qus, c xiovnyx cz c mbiofx ypyl wigy vuwe. c mbuff vy nyffcha nbcm qcnb u mcab migyqbyly uaym uhx uaym byhwy: nqi liuxm xcpylayx ch u qiix, uhx c— c niie nby ihy fymm nlupyfyx vs, uhx nbun bum guxy uff nby xczzylyhwy.
**************************************************
Сдвиг: 12 Исходный текст: viy wjoc ocvo hjmidib zlpvggt gvt di gzvqzn ij nozk cvy omjyyzi wgvxf. jc, d fzko ocz admno ajm vijoczm yvt! tzo fijrdib cjr rvt gzvyn ji oj rvt, d yjpwozy da d ncjpgy zqzm xjhz wvxf. d ncvgg wz ozggdib ocdn rdoc v ndbc njhzrczmz vbzn viy vbzn czixz: orj mjvyn ydqzmbzy di v rjjy, viy d— d ojjf ocz jiz gznn omvqzgzy wt, viy ocvo cvn hvyz vgg ocz ydaazmzixz.
**************************************************
Сдвиг: 13 Исходный текст: wjz xkpd pdwp iknjejc amqwhhu hwu ej hawrao jk opal dwz pnkzzaj xhwyg. kd, e galp pda benop bkn wjkpdan zwu! uap gjksejc dks swu hawzo kj pk swu, e zkqxpaz eb e odkqhz aran ykia xwyg. e odwhh xa pahhejc pdeo sepd w oecd okiasdana wcao wjz wcao dajya: psk nkwzo zerancaz ej w skkz, wjz e— e pkkg pda kja haoo pnwrahaz xu, wjz pdwp dwo iwza whh pda zebbanajya.
**************************************************
Сдвиг: 14 Исходный текст: xka ylqe qexq jlokfkd bnrxiiv ixv fk ibxsbp kl pqbm exa qolaabk yixzh. le, f hbmq qeb cfopq clo xklqebo axv! vbq hkltfkd elt txv ibxap lk ql txv, f alryqba fc f pelria bsbo zljb yxzh. f pexii yb qbiifkd qefp tfqe x pfde pljbtebob xdbp xka xdbp ebkzb: qtl olxap afsbodba fk x tlla, xka f— f qllh qeb lkb ibpp qoxsbiba yv, xka qexq exp jxab xii qeb afccbobkzb.
**************************************************
Сдвиг: 15 Исходный текст: ylb zmrf rfyr kmplgle cosyjjw jyw gl jcytcq lm qrcn fyb rpmbbcl zjyai. mf, g icnr rfc dgpqr dmp ylmrfcp byw! wcr ilmugle fmu uyw jcybq ml rm uyw, g bmszrcb gd g qfmsjb ctcp amkc zyai. g qfyjj zc rcjjgle rfgq ugrf y qgef qmkcufcpc yecq ylb yecq fclac: rum pmybq bgtcpecb gl y ummb, ylb g— g rmmi rfc mlc jcqq rpytcjcb zw, ylb rfyr fyq kybc yjj rfc bgddcpclac.
**************************************************
Сдвиг: 16 Исходный текст: zmc ansg sgzs lnqmhmf dptzkkx kzx hm kdzudr mn rsdo gzc sqnccdm akzbj. ng, h jdos sgd ehqrs enq zmnsgdq czx! xds jmnvhmf gnv vzx kdzcr nm sn vzx, h cntasdc he h rgntkc dudq bnld azbj. h rgzkk ad sdkkhmf sghr vhsg z rhfg rnldvgdqd zfdr zmc zfdr gdmbd: svn qnzcr chudqfdc hm z vnnc, zmc h— h snnj sgd nmd kdrr sqzudkdc ax, zmc sgzs gzr lzcd zkk sgd cheedqdmbd.
**************************************************
Сдвиг: 17 Исходный текст: and both that morning equally lay in leaves no step had trodden black. oh, i kept the first for another day! yet knowing how way leads on to way, i doubted if i should ever come back. i shall be telling this with a sigh somewhere ages and ages hence: two roads diverged in a wood, and i— i took the one less traveled by, and that has made all the difference.
**************************************************
Сдвиг: 18 Исходный текст: boe cpui uibu npsojoh frvbmmz mbz jo mfbwft op tufq ibe uspeefo cmbdl. pi, j lfqu uif gjstu gps bopuifs ebz! zfu lopxjoh ipx xbz mfbet po up xbz, j epvcufe jg j tipvme fwfs dpnf cbdl. j tibmm cf ufmmjoh uijt xjui b tjhi tpnfxifsf bhft boe bhft ifodf: uxp spbet ejwfshfe jo b xppe, boe j— j uppl uif pof mftt usbwfmfe cz, boe uibu ibt nbef bmm uif ejggfsfodf.
**************************************************
Сдвиг: 19 Исходный текст: cpf dqvj vjcv oqtpkpi gswcnna nca kp ngcxgu pq uvgr jcf vtqffgp dncem. qj, k mgrv vjg hktuv hqt cpqvjgt fca! agv mpqykpi jqy yca ngcfu qp vq yca, k fqwdvgf kh k ujqwnf gxgt eqog dcem. k ujcnn dg vgnnkpi vjku ykvj c ukij uqogyjgtg cigu cpf cigu jgpeg: vyq tqcfu fkxgtigf kp c yqqf, cpf k— k vqqm vjg qpg nguu vtcxgngf da, cpf vjcv jcu ocfg cnn vjg fkhhgtgpeg.
**************************************************
Сдвиг: 20 Исходный текст: dqg erwk wkdw pruqlqj htxdoob odb lq ohdyhv qr vwhs kdg wurgghq eodfn. rk, l nhsw wkh iluvw iru dqrwkhu gdb! bhw nqrzlqj krz zdb ohdgv rq wr zdb, l grxewhg li l vkrxog hyhu frph edfn. l vkdoo eh whoolqj wklv zlwk d vljk vrphzkhuh djhv dqg djhv khqfh: wzr urdgv glyhujhg lq d zrrg, dqg l— l wrrn wkh rqh ohvv wudyhohg eb, dqg wkdw kdv pdgh doo wkh gliihuhqfh.
**************************************************
Сдвиг: 21 Исходный текст: erh fsxl xlex qsvrmrk iuyeppc pec mr pieziw rs wxit leh xvshhir fpego. sl, m oitx xli jmvwx jsv ersxliv hec! cix orsamrk lsa aec piehw sr xs aec, m hsyfxih mj m wlsyph iziv gsqi fego. m wlepp fi xippmrk xlmw amxl e wmkl wsqialivi ekiw erh ekiw lirgi: xas vsehw hmzivkih mr e assh, erh m— m xsso xli sri piww xvezipih fc, erh xlex lew qehi epp xli hmjjivirgi.
**************************************************
Сдвиг: 22 Исходный текст: fsi gtym ymfy rtwsnsl jvzfqqd qfd ns qjfajx st xyju mfi ywtiijs gqfhp. tm, n pjuy ymj knwxy ktw fstymjw ifd! djy pstbnsl mtb bfd qjfix ts yt bfd, n itzgyji nk n xmtzqi jajw htrj gfhp. n xmfqq gj yjqqnsl ymnx bnym f xnlm xtrjbmjwj fljx fsi fljx mjshj: ybt wtfix inajwlji ns f btti, fsi n— n yttp ymj tsj qjxx ywfajqji gd, fsi ymfy mfx rfij fqq ymj inkkjwjshj.
**************************************************
Сдвиг: 23 Исходный текст: gtj huzn zngz suxtotm kwagrre rge ot rkgbky tu yzkv ngj zxujjkt hrgiq. un, o qkvz znk loxyz lux gtuznkx jge! ekz qtucotm nuc cge rkgjy ut zu cge, o juahzkj ol o ynuarj kbkx iusk hgiq. o yngrr hk zkrrotm znoy cozn g yomn yuskcnkxk gmky gtj gmky nktik: zcu xugjy jobkxmkj ot g cuuj, gtj o— o zuuq znk utk rkyy zxgbkrkj he, gtj zngz ngy sgjk grr znk jollkxktik.
**************************************************
Сдвиг: 24 Исходный текст: huk ivao aoha tvyupun lxbhssf shf pu slhclz uv zalw ohk ayvkklu ishjr. vo, p rlwa aol mpyza mvy huvaoly khf! fla ruvdpun ovd dhf slhkz vu av dhf, p kvbialk pm p zovbsk lcly jvtl ihjr. p zohss il alsspun aopz dpao h zpno zvtldolyl hnlz huk hnlz olujl: adv yvhkz kpclynlk pu h dvvk, huk p— p avvr aol vul slzz ayhclslk if, huk aoha ohz thkl hss aol kpmmlylujl.
**************************************************
Сдвиг: 25 Исходный текст: ivl jwbp bpib uwzvqvo mycittg tig qv tmidma vw abmx pil bzwllmv jtiks. wp, q smxb bpm nqzab nwz ivwbpmz lig! gmb svweqvo pwe eig tmila wv bw eig, q lwcjbml qn q apwctl mdmz kwum jiks. q apitt jm bmttqvo bpqa eqbp i aqop awumepmzm ioma ivl ioma pmvkm: bew zwila lqdmzoml qv i ewwl, ivl q— q bwws bpm wvm tmaa bzidmtml jg, ivl bpib pia uilm itt bpm lqnnmzmvkm.
Связный текст получился только при сдвиге на 17 символов право, что соответствует сдвигу на девять влево.
Ответ
Исходный текст сдвинут на девять символов вправо или на 17 символов влево:
and both that morning equally lay in leaves no step had trodden black. oh, i kept the first for another day! yet knowing how way leads on to way, i doubted if i should ever come back. i shall be telling this with a sigh somewhere ages and ages hence: two roads diverged in a wood, and i— i took the one less traveled by, and that has made all the difference.