Archive for May, 2008

Resolvendo desafios

Sunday, May 18th, 2008

O site Tableless tem “dado” ingressos para o décimo encontro Locaweb de profissionais de Internet. Disse dado entre aspas, pois, o site vem lançando desafios e, premia com ingressos a primeira pessoa que posta a resposta correta.

A estratégia é ótima, pois, os desafios geralmente envolvem lógica e programação e acabam atingindo em cheio o público certo para o evento.

Resolvi colocar abaixo a solução para um dos desafios que achei interessante. Eu resolvi usando Python, porém, você poderá usar a mesma lógica com outra linguagem. Se tiver usando o SO da MS, use o instalador do Python para Windows. Se estiver usando Linux, provavelmente você já terá o Python instalado. É só abrir o console e digitar python.

O desafio era:

67 7A 69 70 3A 1F 8B 08 08 D0 11 1B 48 02 FF 65 00 CB 28 29 29 B0 D2 D7 CF 4D 2C 28 D6 4B CF CF 4F CF 49 D5 4B CE CF D5 4B 2A 02 0B D9 E7 E4 D8 EA 1A 19 E9 59 1A 1A 99 9B 98 EA E8 9A 18 EB 19 19 98 19 1B 02 00 29 22 3E 34 36 00 00 00

Onde fica isso?

Bem, a primeira coisa é olharmos para a sequência acima e identificarmos que é algo “escrito” em hexadecimal, afinal, tudo está entre 0 e F. Pra quem não tem a menor idéia do que significa isso, recomendo dar uma olhada aqui.

O próximo passo é convertermos esse hexadecimal para algo legível. Como a pergunta nos leva a pensar que o código representa um texto, a primeira coisa que pensei foi, converto para base 10 e vejo o valor correspondente da tabela ascii. Para isso fiz o seguinte:

# Jogo a sequência em uma string s
s = “67 7A 69 70 3A 1F 8B 08 08 D0 11 1B 48 02 FF 65 00 CB 28 29 29 B0 D2 D7 CF 4D 2C 28 D6 4B CF CF 4F CF 49 D5 4B CE CF D5 4B 2A 02 0B D9 E7 E4 D8 EA 1A 19 E9 59 1A 1A 99 9B 98 EA E8 9A 18 EB 19 19 98 19 1B 02 00 29 22 3E 34 36 00 00 00″

# Dou um split sem argumentos na string s e coloco o resultado
# em uma variável chamada lista_hexa.
# Obs: o método split sem argumento usa o espaço como separador
lista_hexa = s.split()

# Crio uma função chamada hex2dec que recebe um parâmetro
# e converte para base 10
def hex2dec(hx): return int(hx, 16)

# Aplico a função criada acima em cada item da lista_hexa
# e coloco o resultado em outra lista chamada lista_decimais.
lista_decimais = map(hex2dec, lista_hexa)

# Agora aplico a função chr em cada número da lista_decimais
# A função chr recebe como parêmtro um número inteiro e retorna
# uma string de um caractere correspondente ao seu valor na tabela ascii.
lista_chars = map(chr, lista_decimais)

Se visualizarmos o conteúdo da variável lista_chars, será o seguinte:
['g', 'z', 'i', 'p', ':', '\x1f', '\x8b', '\x08', '\x08', '\xd0', '\x11', '\x1b', 'H', '\x02', '\xff', 'e', '\x00', '\xcb', '(', ')', ')', '\xb0', '\xd2', '\xd7', '\xcf', 'M', ',', '(', '\xd6', 'K', '\xcf', '\xcf', 'O', '\xcf', 'I', '\xd5', 'K', '\xce', '\xcf', '\xd5', 'K', '*', '\x02', '\x0b', '\xd9', '\xe7', '\xe4', '\xd8', '\xea', '\x1a', '\x19', '\xe9', 'Y', '\x1a', '\x1a', '\x99', '\x9b', '\x98', '\xea', '\xe8', '\x9a', '\x18', '\xeb', '\x19', '\x19', '\x98', '\x19', '\x1b', '\x02', '\x00', ')', '"', '>', '4', '6', '\x00', '\x00', '\x00']

Eu achei que já teríamos o resultado, porém, pelos caracteres iniciais da nossa lista (gzip:…), dá pra ver que agora o que temos é a representação de um arquivo compactado com o gzip. Vamos então descompactá-lo para ver se chegamos no resultado. Existem várias formas de fazer isso, mas, já que estamos no Python, vamos em frente.

# Importando dois módulos que iremos usar
import gzip, cStringIO

# Transformando a lista_chars em uma string e tirando o gzip:
s_final = ”.join(lista_chars)[5:]

# Agora, pra terminar, uso o método GzipFile que recebe como parêmtro
# um arquivo. Como nós já temos o conteúdo do arquivo na variável s_final,
# uso o módulo StringIO que faz exatamente o que precisamos.
gz = gzip.GzipFile(fileobj = cStringIO.StringIO(s_final))
gz.read()

A pergunta do desafio era: onde fica isso? A resposta é um endereço do Google Maps. :)
http://maps.google.com.br/maps?ll=-22.912745,-43.20631

Espero que tenham gostado. Apenas pra finalizar, Python é tão bacana que resolvi tentar fazer tudo isso em uma linha apenas e acabou ficando bem bacana, veja abaixo. Na verdade duas linhas, pois preciso importar os módulos antes.

import gzip, cStringIO
gzip.GzipFile(fileobj = cStringIO.StringIO(”.join(map(chr, map(lambda value:int(value, 16), “67 7A 69 70 3A 1F 8B 08 08 D0 11 1B 48 02 FF 65 00 CB 28 29 29 B0 D2 D7 CF 4D 2C 28 D6 4B CF CF 4F CF 49 D5 4B CE CF D5 4B 2A 02 0B D9 E7 E4 D8 EA 1A 19 E9 59 1A 1A 99 9B 98 EA E8 9A 18 EB 19 19 98 19 1B 02 00 29 22 3E 34 36 00 00 00″.split())))[5:])).read()

Será que dá pra fazer tudo isso em uma linha em alguma outra linguagem? :)