3190 - Vigenere
Vigenere
La fel ca cifrul Cezar, cifrul Vigenere deplasează literele, dar acesta folosește o deplasare multiplă. Cheia este constituită din câțiva întregi ki, unde 0 ≤ ki ≤ 25. Aceşti întregi pot fi, de exemplu, k = (21, 4, 2 19, 14, 17). Această cheie ar provoca deplasare primei litere cu 21, c1 = p1 + 21 (mod 26), a celei de-a doua cu 4, c2 = p2 + 4 (mod 26), ş.a.m.d. până la sfârşitul cheii și apoi de la început, din nou.
Pentru o memorare mai ușoară cheia este de regulă dată printr-un cuvânt – cheia de mai sus corespunde cuvântului vector, litera 'v'” corespondând numărului 21 (numerotarea începe de la 0), litera 'e' cu 4, etc. Un exemplu de cifru Vigenere:
Textul clar: thisisanexampleofthevigenerecipher
Cheia: vector
Textul cifrat: olklwjvrgqodkpghtkcixbuviitxqzklgk
Cerinţa
Se citesc două texte a și b cu lungimea maximă de 255 de caractere. Să se afișeze textul după aplicarea cifrului Vigenere la textul a cu cheia b.
Date de intrare
Fișierul de intrare vigenerein.txt conține pe prima linie textul a iar pe a doua linie textul b.
Date de ieșire
Fișierul de ieșire vigenereout.txt va conține pe prima linie rezultatul criptării.
Restricţii şi precizări
- lungimea lui b ⩽ Lungimea lui a ⩽ 255;
- cele două șiruri vor conține doar litere mici din alfabetul englez.
Exemplu 1
- vigenerein.txt
pbinfo dio
- vigenereout.txt
Datele de intrare corespund restrictiilor impuse sjwqnc
Exemplu 2
- vigenerein.txt
abc123
- vigenereout.txt
Datele de intrare nu corespund restrictiilor impuse
Explicatie
În Cifrul Vigenere începem numărătoarea caracterelor din cheie de la 0, astfel, caracterul 'd' din cheie deplasează caractrrul corespunzător din text cu 3 caractere; astfel, 'p' devine 's'. Acest procedeu se repetă și pentru restul șirului.
Rezolvare
<syntaxhighlight lang="python" line> def vigenere(a, b, c):
# Aplică cifrul Vigenere pe textul a cu cheia b alfabet = 'abcdefghijklmnopqrstuvwxyz' if c == 1: return .join([alfabet[(alfabet.index(a[i]) + alfabet.index(b[i % len(b)])) % 26] for i in range(len(a))]) else: return .join([alfabet[(alfabet.index(a[i]) - alfabet.index(b[i % len(b)])) % 26] for i in range(len(a))])
def main():
with open('vigenerein.txt', 'r') as fin, open('vigenereout.txt', 'w') as fout: a = fin.readline().strip() b = fin.readline().strip()
# Verifică dacă textele respectă restricțiile if len(a) > 255 or len(b) > len(a) or not a.islower() or not b.islower(): fout.write("Datele de intrare nu corespund restrictiilor impuse\n") return
fout.write("Datele de intrare corespund restrictiilor impuse\n")
# Aplică cifrul Vigenere pe textul a cu cheia b și scrie rezultatul în fișierul de ieșire fout.write(vigenere(a, b, 1) + '\n')
if __name__ == "__main__":
main()
</syntaxhighlight>