Text Munger (ou nem tudo é como deveria ser)

por Walter Cruz on 30/06/2008
in Python, Ruby, Geek life

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


Notice: Undefined index: comment_secret in /home/walter/repositories/whissip-dev/blogs/inc/comments/model/_comment.class.php on line 161
  1. LKRaider says :

    Não é um bug, você provavelmente não utilizou string literals ao escrever sua regex, ou seja, fez:

    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

  2. Walter Cruz (Member) Email says :

    Oi LKRaider! Eu bem queria que eu tivesse cometido um erro básico assim, mas não foi o que aconteceu ;) O \b do python não divide como no php, ruby, ou perl.

  3. root says :

    Apesar de o \b não funcionar, é possível utilizar (\W+) para obter o mesmo resultado. Fiz alguns testes e acabei de postar no meu blog, depois passa lá.

    Abraços

  4. Trackback de: :root...blog: [Visitante]

    Insônia novamente
    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...

  5. root says :

    Olá Walter!

    Para medir o tempo utilizei o módulo "hotshot" :)

    Abraços!

  6. Walter Cruz (Member) Email says :

    Bacana! Você se incomodaria de testar a versão que eu acabei de postar? Ou de me mandar os textos que você usou pra eu testar aqui?

Share Your Thoughts


Seu endereço de e-mail não será revelado nesse site.

Sua URL será exibida.
PobreExcelente
(Quebras de linha se tornam <br />)
(Nome, e-mail & website)
(Permitir que usuários o contatem através de um formulário eletrônico (seu e-mail não será exibido.))
Subscribe to comments by email

You can just use your OpenID to provide your name, e-mail and url.