| « Scammer atrapalhado | Comparação de versões » |
Text Munger (ou nem tudo é como deveria ser)
Tudo começou quando eu esbarrei nesse link . O texto contém 15 exercícios de programação, entre eles o que eu me propus a fazer, o text munger.
O exercício consiste no seguinte: dado um texto qualquer, o text munger deve retornar o texto com as palavras desse texto modificadas da seguinte forma: ao invés da palavra original, teremos a primeira letra da palavra original, o resto da palavra (com exceção da última letra) embaralhado seguido da última letra da palavra.
Dentre as várias soluções disponíveis no ruby quiz, a solução em destaque, de Gordon Thiesfeld, usa a expressão regular \b para dividir as palavras. Expressões regulares são iguais em qualquer linguagem, certo? Bom, quase certo. O b funciona da mesma forma no ruby, perl e php, mas funciona de forma diferente no python. Ou não funciona. Na verdade, não sei se é um bug da implementação ou algo assim.
Eu poderia usar outra regex para dividir as palavras e as pontuações, mas já que o fato do \b não funcionar tinha me deixado frustrado com as regex (e eu não queria pensar muito nelas, pra mim o \b deveria funcionar), parti para outra solução. Descobri o shlex, um analisador léxico simples, que para o que eu precisava, funcionava muito bem.
Minha solução para o problema:
import sys
import shlex
from random import shuffle
def munge(text):
t = shlex.shlex(text, posix=False)
t.quotes = "'"
s = [munge_word(word) for word in t]
print(" ".join(s))
def munge_word(aword):
s = list(aword)
first = s.pop(0)
try:
last = s.pop()
except IndexError:
return aword
shuffle(s)
return first + ''.join(s) + last
try:
s = open(sys.argv[1]).read()
munge(s)
except IndexError:
print("Usage: munge.py file")
Observe que a solução não está 100% igual a proposta em ruby. Devido a junção em (" ".join(s)), acabam aparecendo uns espaços em branco que não existiam no texto original.
Existe ainda uma solução em smalltalk proposta pelo Rodrigo Cacilhas no kodumaro. E você gosta de exercícios assim? Sabe porque o \b na implementação de regex do python não funciona como eu esperava? (ou serão minhas expectativas que estão erradas?). Os comentários estão aí para vocês!
Endereço de trackback para este post
Trackback URL (clique direito e copie atalho/localização do link)
5 comentários, 1 trackback
re.compile('\b')
ao invés de:
re.compile(r'\b')
Isso porque \b em uma string normal em Python corresponde ao caractere Backspace (ASCII valor 8). Para funcionar como separador de palavras na regex ele deve ser colocado em uma string literal, para não ser interpretado pelo Python.
E sim, string literals em Python existem principalmente para uso com Regex :P
Abraços
Apesar de estar morrendo de cansaço, não consigo dormir. Já li, já escutei música, já fiquei no escuro. Nada. Então resolvi vir para o computador, esperar o sono chegar e enquanto navegava por aí, encontrei este post, do Walter Cruz, falando so...
Para medir o tempo utilizei o módulo "hotshot" :)
Abraços!


