Skip to content. | Skip to navigation
Solução para a provinha do Google Developer Day 2011 em Python
Posted by
Ricardo Bánffy
at
Aug 22, 2011 03:20 PM
|
Permalink
Esse ano, resolvi tratar com um pouco mais de respeito a prova do GDD. Ano passado, eu resolvi com o prompt do Python aberto, olhando o browser em uma janela e o prompt na outra. Esse ano, as perguntas eram um pouco mais trabalhosas e as strings maiores e isso me fez, em vez disso, escrever um programa. Mais tarde eu coloco o programa no github, mas, por hora, eu transcrevo e comento aqui a minha solução. A prova apresenta dois textos escritos no idioma Googlon, com os quais vamos trabalhar, e quatro perguntas. Para ajudar (eles são realmente bonzinhos), eles dão as soluções para o primeiro texto, o que ajuda a testar se o código está correto. Letras foo, bar e preposiçõesA primeira pergunta explica que algumas letras são chamadas de "letras foo" e todas as demais, "letras bar" e que preposições são palavras de cinco letras que começam com uma letra bar e não contém a letra "q" (é muito provável que a sua prova seja diferente da minha e que elas sejam geradas aleatoriamente - é como eu faria). Para ajudar a resolver, eu escrevi algumas funções def foo(l): return l in "snrbg" def bar(l): return not foo(l) def preposicao(p): return len(p) == 5 and bar(p[-1]) and 'q' not in p Aí, testar a resposta dada no enunciado é fácil: >>> palavras_a = texto_a.split(' ') >>> len(filter(preposicao, palavras_a)) 63 Assim como responder a pergunta: >>> palavras_b= texto_b.split(' ') >>> len(filter(preposicao, palavras_b)) 57 Verbos e verbos em primeira pessoaA segunda pergunta ensina que verbos são palavras de 6 letras que terminam em uma letra bar. Se ele também começar com uma letra bar, estará em primeira pessoa. def verbo(p): return len(p) >= 6 and bar(p[-1]) def verbo_primeira_pessoa(p): return verbo(p) and bar(p[0]) Agora podemos testar nosso código com o dado do enunciado: >>> len(filter(verbo, palavras_a)) == 216 True >>> len(filter(verbo_primeira_pessoa, palavras_a)) == 160 True E descobrir a nossa própria resposta: >>> len(filter(verbo, palavras_b)) 224 >>> len(filter(verbo_primeira_pessoa, palavras_b)) 154 No meu caso, eu tinha 224 verbos, dos quais 154 em primeira pessoa. VocabulárioAgora o problema pede para criar uma lista com o vocabulário, ordenado segundo o alfabeto googlon. Para isso, eu vou usar o ordenador que já vem embutido nas listas do Python e vou produzir uma função de comparação. Essa função pode ser facilmente plugada em seu próprio sort, se você quiser muito: def cmp_googlon(p1, p2): v = 'jgptzmqskbclrhdfnvwx' for l1, l2 in zip(p1, p2): if v.index(l1) != v.index(l2): return v.index(l1) - v.index(l2) return len(p1) - len(p2) E podemos testar com os dados do enunciado: >>> vocabulario_a_unsorted = list(set(palavras_a)) >>> ' '.join(sorted(vocabulario_a_unsorted, ... cmp = cmp_googlon)) == vocabulario_a True Nota: ao construir um set com as palavras do texto A, eu eliminei as repetições. Como objetos do tipo set não são ordenáveis, eu transformei o conjunto em uma lista. Agora podemos encontrar nossa resposta: >>> vocabulario_b_unsorted = list(set(palavras_b)) >>> vocabulario_b = ' '.join(sorted(vocabulario_b_unsorted, cmp = cmp_googlon)) >>> vocabulario_b 'jgspd jgv jpgzkx jzvjw jmrmlq jmdxx jmntpzq jqw jspk jkc jbb jcphbk jch jcv jlkm... NúmerosAgora a prova nos explica que todas as palavras em googlon tem um valor numérico. Em googlon, os números são escritos do dígito menos significativo para o mais significativo e em base 20. Pra isso, precisamos de mais uma função: def valor_numerico(p): v = 'jgptzmqskbclrhdfnvwx' vn = 0 i = 0 for c in p: vn += v.index(c) * (20 ** i) i += 1 return vn que, podemos testar contra o enunciado: >>> valor_numerico('blsmgpz') == 262603029 True Essa parte está certa. Mas a pergunta pede para contarmos os números bonitos. Para eles, números bonitos são divisíveis por 5 e maiores que 492528. def numero_bonito(p): return valor_numerico(p) > 492528 and (valor_numerico(p) % 5 == 0) Agora podemos testar: >>> len(filter(numero_bonito, vocabulario_a.split(' '))) == 75 True E chegar na nossa resposta: >>> len(filter(numero_bonito, vocabulario_b.split(' '))) 71 ConclusãoFoi difícil? Nem um pouco. Se você não conseguiu responder por conta própria, precisa estudar mais. Foi mais trabalhosa do que a do ano passado? Um pouco. Por outro lado, ela tinha informações suficientes para você poder testar suas próprias soluções - e isso ajudou quem teve mais problemas para resolver a prova a aprender alguma coisa. Prova boa é assim - você aprende enquanto faz. Uma última observação: eu gosto de list comprehensions, mas também gosto de map, filter e reduce. O código fica mais limpo quando eles são bem empregados. Document Actions |
|