Publicado por: hugolt | fevereiro 2, 2010

Estou deixando o WordPress para usar o Blogger

É, estou deixando este velho blog na WordPress pra usar o Blogger, o novo blog fica em http://hltbra.blogspot.com.

Os motivos estão explicados no primeiro post lá, mas que fique bem claro que o maior deles foi eu não poder editar o meu próprio CSS no serviço aqui do WordPress sem ter que pagar anuidade por isso.

Pretendo escrever TODOS os novos posts no blog novo e espero vocês lá🙂

Bem, espero ficar satisfeito com o serviço do Blogger!

Vejo vocês no novo blog🙂

Publicado por: hugolt | janeiro 17, 2010

Criando uma Calculadora Usando o Pyparsing

Criando uma Calculadora Usando o Pyparsing

Não é de hoje que eu venho me interessando pela implementação de parsers, mas nunca estudei o suficiente pra fazer um BOM trabalho.
Começei a folhear o livro Programming Languages: Application and Interpretation (PLAI), que o Luciano Ramalho tinha me indicado na PythonBrasil[5] em Setembro de 2009. O livro é bem intessante, mas eu estava lendo no meu PSP e é um pouco desconfortável, por isso estou pensando em procurar saber se está à venda ou acabar imprimindo mesmo (está sob Creative Commons). O livro começa dizendo que nada melhor pra entender uma determinada linguagem do que escrevendo um interpretador para a mesma, assim, começa escrevendo um interpretador pra uma linguagem (inicialmente aritmética) em Scheme.

Achei bem interessante esta abordagem e acabei por tentar fazer algo parecido em Ruby, mas como em Ruby não há o mesmo suporte que Scheme pra expressões do tipo: (+ 1 2) e a linguagem já perceber que isto é um bloco e separar pra você o +, o 1 e o 2, acabei indo pro Python brincar com o Pyparsing – o qual eu já estou pra aprender de verdade há uns poucos meses e não estudei direito. Foi uma ótima oportunidade pra aprender um pouco do Pyparsing e botar alguns conhecimentos em prática.

Uma coisa que eu acho interessante quando se trata de interpretadores/parsers é a gramática – coisa que só começei a me interessar nos últimos meses. O Cucumber por exemplo, usa o TreeTop pra montar seu parser, dado uma gramática definida. Eu não poderia deixar de citar o famoso Yacc, que criar parsers em C (muito usado em conjunto com o Lex na criação de compiladores), mas eu nunca usei nenhuma dessas ferramentas e acabei por pegar o Pyparsing mesmo, o qual eu tenho que aprender a usar.

O objetivo desse tutorial é mostrar o uso do Pyparsing pra criar uma calculadora com notação prefixada e parênteses.
O que significa isso? Significa que as expressões matemáticas não serão do tipo: 1 + 2, mas sim (+ 1 2) [notação comum pra quem programa em LISP].

Caso eu fosse definir uma gramática BNF eu começaria assim:

<expr> ::= <num>
         | (+ <num> <num>)
         | (- <num> <num>)

O que isso significa? Significa que nossas expressões podem ser do tipo:

1
(+ 1 2)
(- 3 4)

E nada além disso!

Depois te instalar o pyparsing, vamos começar nossa implementação (pra instalar basta um easy_install pyparsing):

from pyparsing import Word, White, nums, Literal, OneOrMore, Group

numero = Word(nums)
abre_parenteses = Literal('(').suppress()
fecha_parenteses = Literal(')').suppress()
espacos = OneOrMore(White()).suppress()
mais = Literal('+')
menos = Literal('-')
expr = Group(numero |
             (abre_parenteses +
                 (mais|menos) + espacos + numero + espacos + numero +
              fecha_parenteses))

OPERACOES = {
             '+': lambda x, y: x + y,
             '-': lambda x, y: x - y,
            }

def calcular(e):
    expr_parseada = expr.parseString(e)[0]
    if len(expr_parseada) == 1:
        return int(expr_parseada[0])
    operacao = OPERACOES[expr_parseada[0]]
    return operacao(int(expr_parseada[1]), int(expr_parseada[2]))

Sempre que for necessário dizer que queremos um certo conjunto de caracteres que representam uma coisa só (diz-se que é uma palavra), usamos o Word. Nesse caso, nums é uma string com os caracteres de 0 a 9. Assim, temos um objeto que pode conter os dígitos de 0 a 9 em qualquer quantidade – uma “palavra” em que os caracteres possíveis são 0, 1, 2, 3, 4, 5, 6, 7, 8 ou 9 em qualquer ordem e quantidade.

O Literal é usado sempre que queremos dizer EXATAMENTE o que queremos – nada mais, nada menos! O método suppress apenas indica pro pyparsing que pra nós esse valor não importa, apesar de ter que estar no texto, nós o ignoramos como resultado.

Quando precisamos que algo apareça pelo menos uma vez, podemos usar o OneOrMore. No nosso caso deve haver pelo menos um espaço em branco, que está representado pelo White() (que diz respeito aos caracteres ' ', '\t', '\n', '\r') e também ignoraremos esse resultado.

O mais e menos são também expressões literais. Mas vejam que não foi usado o suppress neles, pois nesse caso é necessário obte-los como resultado.

Por fim, nossa expressão será um grupo (Group) de “subexpressões”. Estamos dizendo que nossa expressão expr será: um número OU um parêntese pra abrir, sinal de + ou de -, espaços, um número, espaços, outro número e um parêntese pra fechar. O pipe (|) significa OU de expressões.

Quando parsearmos alguma expressão válida com o pyparsing através do método parseString, ele retornará um objeto do tipo ParseResults, que pode ser usado com a mesma interface de uma lista. No caso acima o método parseString foi chamado passando como segundo argumento o valor True, indicando que nossa expressão não pode conter nada além do que foi definido.
Assim, dado o caso acima, quando fizermos:

>>> expr.parseString("1")
([(['1'], {})], {})

>>> print expr.parseString("1")
[['1']]

>>> print expr.parseString("1")[0]
['1']

O que nos interessa saber aqui é que no caso acima o resultado será uma lista-like, e o primeiro objeto é o nosso Group. O primeiro e único elemento nesse caso é o número 1 (como string).

O segundo caso (um bem simples), seria fazer:

>>> print expr.parseString("(+ 1 2)")[0]
['+', '1', '2']

Agora já é possível entender a implementação: se o resultado tiver apenas um elemento, é um número único. Caso contrário é uma expressão, tendo o operador como primeiro elemento e os dois próximos elementos são os operandos.

Bem, nossa calculadora está MUITO simples até agora. Só aceitamos números inteiros, podemos somar ou subtrair e subexpressões não funcionam. O interessante agora é implementar subexpressões.

Vamos começar trocando a nossa gramática BNF:

<expr> ::= <num>
         | (+ <expr> <expr>)
         | (- <expr> <expr>)

E agora, o que estamos dizendo?! Estamos dizendo que uma expressão pode ser um número sozinho, como em “1”, ou pode ser algo como “(+ (- 2 1) 3)”, que seria uma expressão com subexpressões. Oh, confuso? É a recursividade!
Parando pra analisar não fica difícil de entender. Atentente-se pra que no fim das contas vai existir uma subexpressão que será do tipo (+ <num> <num>), tornando possível fazer subexpressões em qualquer quantidade!

Vamos à implementação:

from pyparsing import Word, White, nums, Literal, OneOrMore, Group, Forward

numero = Word(nums)
abre_parenteses = Literal('(').suppress()
fecha_parenteses = Literal(')').suppress()
espacos = OneOrMore(White()).suppress()
mais = Literal('+')
menos = Literal('-')
expr = Forward()
atomo = numero | expr
expr << Group(numero |
              (abre_parenteses +
                 (mais|menos) + espacos + atomo + espacos + atomo +
               fecha_parenteses))

OPERACOES = {
             '+': lambda x, y: x + y,
             '-': lambda x, y: x - y,
            }

def avaliar(e):
    if len(e) == 1:
        return int(e[0])
    operacao = OPERACOES[e[0]]
    return operacao(avaliar(e[1]), avaliar(e[2]))

def calcular(e):
    expr_parseada = expr.parseString(e, True)[0]
    return avaliar(expr_parseada)

A maior diferença desse código pro anterior está na definição da expressão expr. Aquele Forward significa que definiremos depois o valor pra expr, mas ela já pode ser usada, mesmo sem valor definido! Mas pra que diabos seria isso necessário? Bem, é a única maneira de fazermos nossa expressão “recursiva”. Continuemos com a definição pra que clarifique o raciocínio… Foi definido atomo que pode ser um número ou uma expressão. Nesse ponto está a mágica. Cada “subexpressão” será um número ou uma expressão (que pode ser um número ou uma expressão e assim recursivamente, até chegar num momento que a subexpressão será um simples número). Se não pudessemos definir uma expressão sem valor previamente definido não seria possível fazer isso! Depois dizemos que expr vai receber (<<) a expressão desejada, que será: um número OU um parêntese pra abrir, sinal de + ou de -, espaços, uma expressão, espaços, outra expressão e um parêntese pra fechar. Repetindo: vai chegar numa hora que cada subexpressão será basicamente um número!

O método calcular agora passou a responsabilidade de avaliar cada subexpressão pro método avaliar, porque tem que ser feito recursivamente.
O método avaliar verifica se a expressão e é um número sozinho (ou seja, tem tamanho um), e, caso seja, retorna a string como inteiro. Caso contrário a expressão será do tipo “(+ <expr> <expr>)”, e teremos que ir avaliando essas subexpressões até chegar no ponto em que <expr> será um <num> (caso que retorna a conversão pra inteiro).

Simples, não?!

Agora implementar multiplicação, divisão e exponenciação é simples e ficará como exercício. A idéia de fazer uma calculadora com parênteses e prefixada é pra facilitar mesmo, pois não é necessário importar-se com precedências e etc.

Os códigos acima estão no github (e estão com testes!) como gists:
primeira calculadora em http://gist.github.com/279361 e a segunda calculadora em http://gist.github.com/279362

Depois que o leitor tiver feito o exercício, pode dar uma olhada numa outra calculadora um pouco mais “potente” que eu fiz usando a mesma idéia: http://gist.github.com/279357

Achei o Pyparsing realmente muito útil. O problema é que a documentação livre dele é muito fraca, mas pelo menos há vários códigos de exemplo no site. Há um livro sobre o Pyparsing, Geting Started with Pyparsing mas não está disponível livremente na rede. Não sei nem se existe algum material em português, mas fica aí a minha contribuição!

update: corrigida a confusão com os nomes infix e prefix

Publicado por: hugolt | novembro 19, 2009

PythOnCampus IFF nos dias 27 e 28 de novembro!

PythOnCampus IFF está chegando!

Semana que vêm haverá PythOnCampus IFF aqui em Campos dos Goytacazes!
Nós, do NSI, estamos organizando o evento que contará com palestras e minicursos sobre Python. O objetivo do evento é trazer conhecimento e experiência dos profissionais da área pra dentro da instituição, qualificando e preparando os alunos tanto para o mercado de trabalho como para a vida acadêmica.

Na manhã da sexta-feira haverá pelo menos 3 turmas com cursos introdutórios a linguagem (Python for Dummies) e um Coding Dojo.
À tarde e a noite o evento contará com várias palestras de pessoas conhecidas e influentes na comunidade. Gente da Canonical, Globo.com, SERPRO, Peta5, UFF, UENF, IFF e outros lugares virão pra cá compartilhar conhecimento conosco.
No sábado haverá pela manhã minicursos de Django, Grok e Plone e à tarde mais palestras!

As inscrições pro evento podem têm que ser feitas pelo site do evento http://pythoncampus.iff.edu.br/inscricao. As vagas pro auditório e pros minicursos são limitadas.
Quem quiser se inscrever em algum minicurso basta entrar no site, se cadastrar e levar 1kg de arroz, feijão ou macarrão ao NSI (sala 133, bloco A). Como são vagas limitadas e provavelmente vai ter muita procura, procure levar o mais rápido possível o quilo de alimento pra garantir sua vaga nos minicursos!

A programação pode ser conferida aqui: http://pythoncampus.iff.edu.br/programacao

Os panfletos podem ser visualizados (PDF) aqui e aqui.

Banner Grande

Nos vemos na PythOnCampus🙂

Publicado por: hugolt | setembro 28, 2009

Por que eu mudei de idéia sobre o Twitter

Na primeira vez que eu vi o Twitter eu achei a maior bobeira de todas. O maior motivo eu acho que é porque eu estava acostumado a usar GMail, IRC, MSN, Orkut e não vi nenhuma vantagem no início.
Bem, estou aqui pra dizer que eu mudei de idéia, e muito.
O Twitter é simplesmente um fenômeno. Você vê o que as pessoas no mundo todo estão fazendo (twittando). Sabe dos acontecimentos antes de chegar na mídia. Sabe o que aquele cara que você idolatra fez ontem ou está fazendo agora. Enfim, fiquei viciado.
Instalei o TwitterFox (agora chama-se Echofon) e PowerTwitter no meu Firefox. O primeiro, antigo TwitterFox, é uma mão na roda! Ele deixa uma janelinha no canto direito do seu Firefox mostrando de tempos em tempos os tweets das pessoas que você segue, mensagens em que você está (com @) ou mensagens diretas pra você (direct message).
O Power Twitter também é interessante, apesar de eu não entender o motivo das minhas imagens estarem tão feias no twitter.com depois dele. Ele renderiza imagens (previews) na sua página do twitter.com, mostra preview de vídeo no YouTube.com, favicons das páginas citadas e etc. Recomendo os dois!

O twitter é mais interessante ainda quando você está em conferências, como foi o meu caso na PythonBrasil[5], porque eu podia ver todo mundo que estava falando do evento, inclusive sobre as minhas palestas🙂

O passarinho é bom – revolucionário pra dizer mais. É a nova maneira de transformar todos os usuários da Grande Rede em “amigos”. Sabe aquele cara fodão, astro famoso ou qualquer coisa do tipo!? Então, você pode mandar mensagens pros seus amigos falando dele ou diretamente pra ele em no máximo 140 caracteres. Irado.

Bem, está aí a dica: USEM O TWITTER.
Meu usuário é @hltbra😉
Vejo vocês lá.

Publicado por: hugolt | setembro 15, 2009

Relatos da PythonBrasil[5]

A PythonBrasil[5] foi foda. Não teve tantas pessoas como no ano passado, mas mesmo assim foi muito foda😉

Caxias do Sul é frio demais pra mim – acostumado com cidades quentes (sou itaperunense). Eu e Tiago chegamos na quarta em Caxias e saímos na rua pra conhecer. Pegamos 5º a tarde, absuradamente frio.

O Primeiro Dia

Chegamos cedo no primeiro dia do evento e pra mim a melhor palestra do dia foi a do Jacob, o co-autor do Django. Às 18:00 começaram as palestras relâmpagos, eu inscrevi uma, “Frame Hacks”, pra mostrar como podemos usar o sys._getframe pra fazer DSLs e etc. Foi bem interessante, apesar de ter slots pra 12 palestras acho que tiveram umas 4.

O Segundo Dia

O segundo dia também foi bem interessante, Collin Winter, do projeto Unladen Swallow do Google deu uma palestra sobre como eles querem aumentar a performance do Python. Muito interessante! Mais a noite mais palestras relâmpagos e eu inventei de dar uma sobre o zope.testbrowser. O problema é que eu criei uns 5 slides às 17:00 pra falar às 18:00 e mostrar na prática como funcionava. Até aí tudo bem. O problema é que a conexão de internet quase me deixou numa roubada, porque na hora de mostrar a prática o site do Google não abriu instantaneamente e me deixou meio nervoso. Mas nos fins das contas ainda sobrou 15 segundos! Depois fomos pra Hamburgueria Juventus, onde havia vários lanches imensos e super saborosos.

Terceiro Dia

No último dia a minha palestra era a primeira, às 9:00, eu ia falar sobre BDD e algumas ferramentas em Python, incluindo projetos meus como Pyhistorian, PyCukes, Should-DSL e outros de fora como o Pyccuracy, Freshen e Yeti, além dos frameworks de mock como o Mockito e o Ludíbrio (do meu amigo Gustavo Rezende). Fiquei nervoso no início, mas depois fui acalmando. Havia poucas pessoas, mas mesmo assim foi uma boa experiẽncia e creio que foi proveitosa.
Por fim, juntamos com o pessoal da PythonRio pra ir a uma vinícula, num castelo. Conhecemos o lugar, degustamos vários vinhos e trouxemos uma boa quantidade de vinho nas bagagens🙂

Conclusões

A PythonBrasil[5] foi foda, como eu já disse. Me senti em casa, super bem acolhido. O pessoal da PythonRio passou boa parte do tempo comigo e com o Tiago e foi super irado. Gostei muito!

Que venha a PythonBrasil[6]!

Publicado por: hugolt | agosto 5, 2009

PythonBrasil[5] em Caxias do Sul eu vou!

Ano passado eu fui à minha primeira PyConBrasil, no Rio de Janeiro. Esse ano o evento mudou de nome, chama-se PythonBrasil e é a quinta edição – PythonBrasil[5].

Eu submeti uma palestra e foi aceita!
Vou falar sobre Behaviour-Driven Development e como pode ser aplicado em Python, e claro, falar das ferramentas que eu tenho me envolvido na área, como o meu bebê Pyhistorian e o Should-DSL😉

Infelizmente a palestra do meu amigo Gustavo, aqui do NSI, não foi aceita. Ele falaria sobre um framework de Test Doubles que ele criou, o Ludíbrio.

Agora só espero que o IFF me custeie pra eu poder participar desse evento anual da comunidade Python do Brasil que esse ano conta com muitas palestras iradas.

Confiram as palestras aceitas aqui.

Publicado por: hugolt | julho 3, 2009

FISL10 e outras atividades

FISL 10 e outras coisas que tem acontecido

Eu estive pela primeira vez em um FISL, foi na décima edição, em Porto Alegr – RS na semana passada.
O evento é muito foda, você encontra gente do mundo todo! Desde gurus, como Richard Stallman, a blogueiros como Fábio Akita.

Esse ano teve uma grande quantidade de grupos de usuários, inclusive os que eu participo (PythonBrasil e PythOnRio).
As palestras foram excelentes, as conversas muito boas também. É muito prazeroso conversar com as pessoas que você só conhece de nome e às vezes nem conhece, mas na hora vê que todo mundo ali tem o mesmo objetivo: Contato Social com a comunidade de Software Livre.

Palestras como a do Alexandre Oliva vão ficar um bom tempo na memória – foram aquelas de dar arrepios e parar pra pensar e ver que “é isso que eu quero pro resto da minha vida” – e outras várias.

No último dia de FISL teve um horário pra palestras relâmpagos da Associação Python Brasil (APyB), onde cada palestrante tinha 5 minutos pra aprensentar uma palestra sobre qualquer tema. Eu me inscrevi pra falar de BDD e do Pyhistorian.

Além do nervosismo de estar falando pela primeira vez pra uma grande quantidade de pessoas num evento de tão alto nível, tem o nervosismo de ter que expor as idéias em apenas 5 minutos! Foi muito bom, serviu como uma baita experiência.

Porto Alegre é muito legal, a PUCRS parece uma cidade e eu vou parar por aqui, pois o FISL poderia ter sido definido com somente uma frase: “foda pra caralho!”.

Outras coisas que tem acontecido

Esse ano tem sido bem movimentado pra mim, um bom ano. Muitas responsabilidades e tarefas (ensino médio, ensino técnico, trabalho no NSI, projetos open sources …) que acabam me deixando meio desnorteado e fazem perder algumas datas importantes, como aconteceu com a OBI2009.

Eu fiz a primeira fase da OBI. Passei, mas perdi a data da segunda fase. Acontece.

Tenho pensando muito sobre a continuação do projeto pyhistorian, analisando as opções e levando muito em consideração as facilidades do Cucumber. Talvez surja algum port do Cucumber pra Python, mas não pretendo parar o pyhistorian no momento. Isso vai dar artigo!

Vou tentar dar uma moral pro Mockito (a versão em Python), pois parece ser um excelente mock framework, muito pouco burocrático. Hackeando o código achei alguns probleminhas e idéias de implementações, mas está faltando um tempo pra mexer.

Também quero olhar melhor o Pyccuracy, pois o pessoal tem trabalhado bastante nele (conheci o time de desenvolvimento do Pyccuracy no FISL, gente boa) e eu sei que posso ajudar em algumas coisas.
Tenho que terminar de ler o Refactoring do Martin Fowler, quero começar a ler algum da The Pragmatic Bookshelf.
Preciso terminar a escola e ter férias pra poder programar e estudar por mais tempo =) Há muitos projetos open source que estou querendo contribuir, mas não tem dado.

Conversando com a Leslie Hawthorn do Google Summer of Code durante o FISL descobri que eles tem um programa pra alunos de ensino médio e talvez dê pra eu tentar participar esse ano (já que eu não posso tentar o Google Summer of Code por não estar na universidade ainda). Parece bem interessante, o dinheiro é muito menor, mas a complexidade parece ser bem próxima.

Vou ficando por aqui, até o próximo post😉

Publicado por: hugolt | maio 1, 2009

BDD em Python, duas novas crianças

Há um tempo venho conversando sobre Behaviour-Driven Development (BDD) com o Rodrigo e acabaram surgindo varias idéias.

Não conheço nenhuma ferramenta famosa para BDD em Python, sei existe o Behaviour, pyspec (por causa do Google) e talvez outras, mas elas ilustram de maneira diferente o que eu queria.

O Cucumber é lindo! O RSpec nem tanto, mas ilustram bem a necessidade e a idéia real de BDD.
São ferramentas escritas em Ruby e pra Ruby, e Ruby provê bastante facilidade pra escrever DSLs, e ficou bem legal o trabalho deles com as ferramentas de BDD.
Porém, em Python não há tanta liberdade como Ruby, mas mesmo assim é possível fazer boas DSLs, fluent interfaces e etc.

Decidi então criar as minhas próprias ferramentas pra Python.

A primeira idéia era criar uma DSLs de “should”, pra desfocar totalmente da idéia de assertions. Tentei fazer uma maneira de tornar transparente um código python que usa-se essa DSL, mas não ficou tão transparente.
Em Python não há uma classe base pra todos os objetos, então não dá pra simplesmente adicionar métodos em uma tal classe base.
Acabou que por fim, usei o truque de importar a classe DSLObject que eu criei como _ [underscore], pra tentar tornar o mais transparente possível, ficando como no exemplo que segue (código Python):
_(VALOR).should_be.equal_to(OUTRO_VALOR)
Que é bem próxomo de VALOR should be equal to OUTRO_VALOR, levando em conta as limitações da linguagem.

Esse projeto chamei de should-dsl e hospedei no Google Code:
http://code.google.com/p/should-dsl/

A outra idéia era a de criar uma ferramenta de criação de Story (Histórias) com BDD, mas a nível de código.

Para facilitar o entendimento, vou dar um exemplo de como é uma história (story):

As a <role>
I want to <action>
So that <benefit>

Scenario: <title>
Given <pre-conditions>
When <actions>
Then <outcome>

Essa seria uma template pra uma história, que poderia ser do tipo:

As a lazy mathematician
I want to use a calculator
So that I rest my mind

Scenario 1: Using my calculator to sum
Given I have a calculator
When I enter with 1 + 1 and press =
Then I see 2 on the display

Esse seria um exemplo de uso de histórias pra descrever uma especificação de aceitação de uma calculadora.

O Cucumber faz isso, porém você tem que escrever um texto livre (seguindo a idéia de como deve ser uma história em BDD) e depois criar códigos Ruby em uma certa convenção de diretórias e nome de arquivos contendo código para os passos (given, when, then) que existirem. Eu pensei em fazer primeiro uma abstração dessas a nível de código, sem ter texto livre e fiz.

O código está também no Google Code, em:
http://code.google.com/p/pyhistorian/
Um exemplo de uso, um completo código Python está na página inicial do projeto, vale a pena conferir.

Nas páginas dos projetos há explicações melhores e exemplos, é software livre, fique a vontade pra modificar e sugerir qualquer coisa.

Mais idéias surgiram e breve estarão implementadas!

Aguardem.

Publicado por: hugolt | maio 1, 2009

Resultado da OBI 2009

Vou ser bem breve no post.

Eu achei que tinha ido muito bem na fase 1 da OBI 2009, mas acabei não indo tão bem.
Postei o meu relato e apareceram vários comentários, fico feliz que tenham gostado do meu relato e gostei das opiniões também. Fiquei muito feliz por isso.

Passei para a segunda-fase, junto com um amigo, Ângelo, que participou da Olimpíada de Algoritmo da Hostnet comigo no ano passado.

Aguardarei a segunda-fase e até lá talvez dar uma estudada, porque o resultado não foi o esperado.

Fiz apenas 270 pontos (de 400). Até agora não sei o por quê (e nem vou procurar saber muito), mas eu fiz 5 pontos na  questão Caminho das Pontes, a questão que eu usei Dijkstra e fiz 65 na questão O Fugitivo.
Na questão O Fugitivo minha saída foi errada em alguns testes, e isso dá pra saber pelos comentários que fizeram no outro post. Porém, a questão das pontes não obteve saída na maioria dos conjuntos de testes, ainda não sei como… Mas fica como experiência.

Parabéns a todos que participaram e principalmente para os que foram pra segunda-fase.

🙂

Publicado por: hugolt | abril 12, 2009

And the Oscar goes to: The Big Bang Theory!

Já havia ouvido várias pessoas falando do seriado The Big Bang Theory, porém nunca tinha visto nenhum episódio até quinta-feira, quando o Bruno me mostrou alguns episódios da primeira temporada.

Só parei de assistir porque esgotaram todos os meus episódios, é hilário! Deu pra assistir a primeira temporada inteira e 11 capítulos da segunda.

É o tipo de par perfeito das séries. É a série feita por nerds, que fala sobre nerds e destinada pra nerds, ou seja, fascinante!

Vale a pena conferir, é muito engraçado. Eu me identifiquei um pouco com cada personagem e gostaria de ter uma vizinha como a Penny. Seria engraçado se eu conhecesse caras daquele tipo, é um tipo ultra-nerd nunca visto. Eles são geeks, físicos, engenheiros. Oh shit! How?

Com certeza vou baixar outros episódios essa semana e recomendo a todos nerds que assistam.

Older Posts »

Categorias