Fonction rot13 courte-Python [fermé]

Je suis à la recherche d'une fonction rot13 courte et cool en Python ;-) J'ai écrit cette fonction:

def rot13(s):
    chars = "abcdefghijklmnopqrstuvwxyz"
    trans = chars[13:]+chars[:13]
    rot_char = lambda c: trans[chars.find(c)] if chars.find(c)>-1 else c
    return ''.join( rot_char(c) for c in s ) 

Quelqu'un Peut-il faire mieux? Par exemple, soutenir les caractères majuscules.

53
demandé sur dreftymac 2010-07-17 04:33:29

20 réponses

Voici une solution maketrans / translate

import string
rot13 = string.maketrans( 
    "ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", 
    "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
string.translate("Hello World!", rot13)
# 'Uryyb Jbeyq!'
68
répondu Paul Rubel 2017-04-15 21:20:09

, C'est très simple:

>>> import codecs
>>> codecs.encode('foobar', 'rot_13')
'sbbone'
108
répondu Nazmul Hasan 2018-07-08 15:58:11
>>> 'foobar'.encode('rot13')
'sbbone'

(j'ai entendu des rumeurs que cela ne fonctionne pas dans Python 3.x cependant.)

61
répondu Amber 2010-07-17 00:37:07

Le maketrans et translate fonctions dans le string module sont à portée de main pour ce genre de chose. Bien sûr, la méthode encode dans la réponse D'Amber est encore plus pratique pour ce cas spécifique.

Voici une solution générale:

import string

def make_rot_n(n):
 lc = string.ascii_lowercase
 uc = string.ascii_uppercase
 trans = string.maketrans(lc + uc,
                          lc[n:] + lc[:n] + uc[n:] + uc[:n])
 return lambda s: string.translate(s, trans)

rot13 = make_rot_n(13)

rot13('foobar')
# 'sbbone'
21
répondu ars 2015-08-13 08:22:43

Du module this.py (import this).

d = {}
for c in (65, 97):
    for i in range(26):
        d[chr(i+c)] = chr((i+13) % 26 + c)

print "".join([d.get(c, c) for c in s])
10
répondu Artur Gaspar 2015-05-11 20:40:30

, Comme de Python 3.1, string.translate et string.maketrans n'existent plus. Cependant, ces méthodes peuvent être utilisées avec bytes à la place.

Ainsi, une solution à jour directement inspirée de celle de Paul Rubel, est:

rot13 = bytes.maketrans(
    b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
    b"nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM")
b'Hello world!'.translate(rot13)

Conversion à partir de string à bytes et vice-versa peut être fait avec l'encode et decode les fonctions intégrées.

8
répondu bbc 2012-05-01 10:34:49

Essayez ceci:

import codecs
codecs.encode("text to be rot13()'ed", "rot_13")
5
répondu Barrest 2013-06-19 12:33:04

En python-3 le str-codec @orange mentionné a déménagé à codecs standard-bibliothèque:

> import codecs
> codecs.encode('foo', 'rot13')
sbb
4
répondu ankostis 2015-08-04 19:31:58

Pour les valeurs arbitraires, quelque chose comme ça fonctionne pour 2.x

from string import ascii_uppercase as uc, ascii_lowercase as lc, maketrans                                                                                                            

rotate = 13 # ROT13                                                                    
rot = "".join([(x[:rotate][::-1] + x[rotate:][::-1])[::-1] for x in (uc,lc)])   

def rot_func(text, encode=True):                                                
    ascii = uc + lc                                                             
    src, trg = (ascii, rot) if encode else (rot, ascii)                         
    trans = maketrans(src, trg)                                                 
    return text.translate(trans)                                                

text = "Text to ROT{}".format(rotate)                                           
encode = rot_func(text)                                                         
decode = rot_func(encode, False)
2
répondu user1543747 2012-07-22 09:14:48

Cela fonctionne pour les majuscules et les minuscules. Je ne sais pas à quel point vous le jugez élégant.

def rot13(s):
    rot=lambda x:chr(ord(x)+13) if chr(ord(x.lower())+13).isalpha()==True else chr(ord(x)-13)
    s=[rot(i) for i in filter(lambda x:x!=',',map(str,s))]
    return ''.join(s)
2
répondu Eratosthenes 2012-08-24 13:59:40

Vous pouvez prendre en charge les majuscules sur le code original posté par M. Walter en alternant les majuscules et les minuscules.

chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"

Si vous remarquez l'index des lettres majuscules sont tous des nombres pairs, tandis que l'indice des lettres minuscules sont impairs.

  • A = 0 a = 1,
  • B = 2, b = 3,
  • C = 4, c = 4,
  • ...

Ce modèle pair-impair nous permet d'ajouter en toute sécurité la quantité nécessaire sans avoir à se soucier de l'affaire.

trans = chars[26:] + chars[:26]

La raison pour laquelle vous ajoutez 26 est parce que la chaîne a doublé en lettres en raison des lettres majuscules. Cependant, le décalage est toujours 13 espaces sur l'alphabet.

Le code complet:

def rot13(s):
    chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
    trans = chars[26:]+chars[:26]
    rot_char = lambda c: trans[chars.find(c)] if chars.find(c) > -1 else c
    return ''.join(rot_char(c) for c in s)

Sortie (testée avec Python 2.7):

print rot13("Hello World!") --> Uryyb Jbeyq!
2
répondu Diaz 2013-12-26 04:02:56

La fonction suivante rot(s, n) code une chaîne s avec un codage ROT-n pour tout entier n, avec n par défaut à 13. Les lettres majuscules et minuscules sont prises en charge. Des valeurs de n supérieures à 26 ou des valeurs négatives sont traitées de manière appropriée, par exemple, le déplacement de 27 positions est égal au déplacement d'une position. Le décodage se fait avec invrot(s, n).

import string

def rot(s, n=13):
    '''Encode string s with ROT-n, i.e., by shifting all letters n positions.
    When n is not supplied, ROT-13 encoding is assumed.
    '''
    upper = string.ascii_uppercase
    lower = string.ascii_lowercase
    upper_start = ord(upper[0])
    lower_start = ord(lower[0])
    out = ''
    for letter in s:
        if letter in upper:
            out += chr(upper_start + (ord(letter) - upper_start + n) % 26)
        elif letter in lower:
            out += chr(lower_start + (ord(letter) - lower_start + n) % 26)
        else:
            out += letter
    return(out)

def invrot(s, n=13):
    '''Decode a string s encoded with ROT-n-encoding
    When n is not supplied, ROT-13 is assumed.
    '''
    return(rot(s, -n))
2
répondu jeroen 2015-06-22 11:51:46

Un one-liner pour rot13 une chaîne S:

S.translate({a : a + (lambda x: 1 if x>=0 else -1)(77 - a) * 13 for a in range(65, 91)})
2
répondu wjv 2016-02-20 07:19:34
def rot13(s):
    lower_chars = ''.join(chr(c) for c in range (97,123)) #ASCII a-z
    upper_chars = ''.join(chr(c) for c in range (65,91)) #ASCII A-Z
    lower_encode = lower_chars[13:] + lower_chars[:13] #shift 13 bytes
    upper_encode = upper_chars[13:] + upper_chars[:13] #shift 13 bytes
    output = "" #outputstring
    for c in s:
        if c in lower_chars:
                output = output + lower_encode[lower_chars.find(c)]
        elif c in upper_chars:
            output = output + upper_encode[upper_chars.find(c)]
        else:
            output = output + c
    return output

Une autre solution avec le déplacement. Peut-être que ce code aide les autres à mieux comprendre rot13. N'ai pas testé complètement.

1
répondu DeaD_EyE 2013-09-25 23:26:56
from string import maketrans, lowercase, uppercase

def rot13(message):
   lower = maketrans(lowercase, lowercase[13:] + lowercase[:13])
   upper = maketrans(uppercase, uppercase[13:] + uppercase[:13])
   return message.translate(lower).translate(upper)
0
répondu user847988 2015-02-13 19:44:33

Exercice intéressant ; -) je pense avoir la meilleure solution car:

  1. aucun module nécessaire, utilise uniquement des fonctions intégrées -- > aucune dépréciation
  2. , il peut être utilisé comme une doublure
  3. basé sur ascii, pas de mappage dicts / strings etc.

Python 2 et 3 (probablement Python 1):

def rot13(s):
    return ''.join([chr(ord(n) + (13 if 'Z' < n < 'n' or n < 'N' else -13)) if n.isalpha() else n for n in s])

def rot13_verbose(s):
    x = []
    for n in s:
        if n.isalpha():
            # 'n' is the 14th character in the alphabet so if a character is bigger we can subtract 13 to get rot13
            ort = 13 if 'Z' < n < 'n' or n < 'N' else -13
            x.append(chr(ord(n) + ort))
        else:
            x.append(n)
    return ''.join(x)



# crazy .min version (99 characters) disclaimer: not pep8 compatible^

def r(s):return''.join([chr(ord(n)+(13if'Z'<n<'n'or'N'>n else-13))if n.isalpha()else n for n in s])
0
répondu yamm 2015-04-09 15:24:50

J'ai trouvé ce post quand j'ai commencé à me poser des questions sur la façon la plus simple de mettre en œuvre rot13 en Python moi-même. Mes objectifs étaient:

  • fonctionne à la fois en python 2.7.6 et 3.3.
  • gère les majuscules et les minuscules.
  • N'utilise aucune bibliothèque externe.

Cela répond à ces trois exigences. Cela étant dit, je suis sûr qu'il ne gagne pas de compétitions de golf de code.

def rot13(string):
    CLEAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
    ROT13 = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'
    TABLE = {x: y for x, y in zip(CLEAR, ROT13)}

    return ''.join(map(lambda x: TABLE.get(x, x), string))



if __name__ == '__main__':
    CLEAR = 'Hello, World!'
    R13 = 'Uryyb, Jbeyq!'

    r13 = rot13(CLEAR)
    assert r13 == R13

    clear = rot13(r13)
    assert clear == CLEAR

Cela fonctionne en créant une table de recherche et en renvoyant simplement le caractère d'origine pour tout caractère introuvable dans la table de recherche.

Mettre à jour

Je me suis inquiété de quelqu'un qui voulait l'utiliser pour chiffrer un fichier arbitrairement volumineux (disons, quelques gigaoctets de texte). Je ne sais pas pourquoi ils voudraient faire ça, mais si c'était le cas? Donc je l'ai réécrit comme un générateur. Encore une fois, cela a été testé dans Python 2.7.6 et 3.3.

def rot13(clear):
    CLEAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
    ROT13 = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'
    TABLE = {x: y for x, y in zip(CLEAR, ROT13)}

    for c in clear:
        yield TABLE.get(c, c)



if __name__ == '__main__':
    CLEAR = 'Hello, World!'
    R13 = 'Uryyb, Jbeyq!'

    r13 = ''.join(rot13(CLEAR))
    assert r13 == R13

    clear = ''.join(rot13(r13))
    assert clear == CLEAR
0
répondu Doug R. 2015-06-19 17:22:59

Je ne pouvais pas laisser cette question ici sans une seule instruction utilisant l'opérateur modulo.

def rot13(s):
    return ''.join([chr(x.islower() and ((ord(x) - 84) % 26) + 97
                        or x.isupper() and ((ord(x) - 52) % 26) + 65
                        or ord(x))
                    for x in s])

C'est pas pythonique ni bonne pratique, mais ça marche!

>> rot13("Hello World!")
Uryyb Jbeyq!
0
répondu Zv_oDD 2016-02-21 05:36:41

Vous pouvez également l'utiliser aussi

def n3bu1A(n):
    o=""
    key = {
       'a':'n', 'b':'o', 'c':'p', 'd':'q', 'e':'r', 'f':'s', 'g':'t', 'h':'u', 
       'i':'v', 'j':'w', 'k':'x', 'l':'y', 'm':'z', 'n':'a', 'o':'b', 'p':'c', 
       'q':'d', 'r':'e', 's':'f', 't':'g', 'u':'h', 'v':'i', 'w':'j', 'x':'k',
       'y':'l', 'z':'m', 'A':'N', 'B':'O', 'C':'P', 'D':'Q', 'E':'R', 'F':'S', 
       'G':'T', 'H':'U', 'I':'V', 'J':'W', 'K':'X', 'L':'Y', 'M':'Z', 'N':'A', 
       'O':'B', 'P':'C', 'Q':'D', 'R':'E', 'S':'F', 'T':'G', 'U':'H', 'V':'I', 
       'W':'J', 'X':'K', 'Y':'L', 'Z':'M'}
    for x in n:
        v = x in key.keys()
        if v == True:
            o += (key[x])   
        else:
            o += x
    return o

Yes = n3bu1A("N zhpu fvzcyre jnl gb fnl Guvf vf zl Zragbe!!")
print(Yes)
0
répondu Francis Bangura 2017-04-15 21:20:20

Solution courte:

def rot13(text):
    return "".join([x if ord(x) not in range(65, 91)+range(97, 123) else
            chr(((ord(x)-97+13)%26)+97) if x.islower() else
            chr(((ord(x)-65+13)%26)+65) for x in text])
-2
répondu SyntaxError 2016-04-19 13:58:51