# Curtindo a Vida Adoidado

Caloni, 2014-04-02 cinema movies [up] [copy]

O diretor/produtor/roteirista John Hughes (Gatinhas e Gatões, Clube dos Cinco) é a cara da juventude da década de 80 e consegue expressar isso em cada um de seus filmes que aborda temas recorrentes entre os jovens. A consequência disso é que seus trabalhos daquela época se universalizaram, tanto que hoje temos fãs incondicionais de Ferris Bueller nascendo após ele sair do colégio. Não é difícil entendê-los. Assistir hoje à Curtindo a Vida Adoidado é poder captar sua mensagem sobre a vida sob o ponto de vista adolescente, mas, acima de tudo, o ponto de vista humano.

Dirigido e roteirizado por Hughes, o filme se passa no decorrer de um dia em que o garoto Ferris Bueller (Matthew Broderick) vai matar a aula pela nona vez esse ano. O diretor da escola (Jeffrey Jones) desconfia há tempos das desculpas de doenças de Bueller e hoje resolve tirar isso a limpo. Sua irmã odeia que o irmão sempre se safe de suas artimanhas e não fará o mínimo esforço para salvá-lo. Seu melhor amigo é o estresse em pessoa, mas assim mesmo vai emprestar a Ferrari do pai para o dia de folga. Ferris fala conosco todo o tempo, como se fizéssemos parte de tudo aquilo, o que nesse caso funciona muito bem ao nos trazer na emoção do momento. A câmera de Hughes é uma visão de mundo que flerta todo o tempo com a fantasia, e que continua mantendo sua síntese no número musical que é a alma do filme.

Acho que já falei sobre isso em O Clube dos Cinco, mas a grande virtude de Hughes é entender essa juventude e levá-la a sério nos mínimos detalhes de sua vida. Isso é o que torna Ferris Bueller's Day Off tão completo em sua mensagem aparentemente despretensiosa. Despretensiosos mesmas são as comédias românticas de hoje, que trata os jovens como completos imbecis.


# Penelope

Caloni, 2014-04-05 cinema movies [up] [copy]

Peguemos um livro de contos infantis e transformemos em um filme live-action (com atores de carne-e-osso). Pode ser aquela história da maldição da empregada que é renegada pelo seu amor de um aristocrata, de novo?, e cuja mãe é uma bruxa e roga uma praga que transforma a primeira filha da família de sangue azul em uma abominação. Quer dizer, o nome "abominação" vai depender de quem consegue enxergar na bela Christina Ricci um monstro, quando no fundo a única coisa que incomoda em seu visual são suas orelhas flácidas e seu focinho de porco. Nada que justifique tantas janelas quebradas de pretendentes que parecem ter se encontrado com uma besta selvagem prestes a devorá-los.

Porém, a virada de expectativas que o filme prometia, onde o monstro não é Christina Ricci, mas a sociedade onde ela vive (família inclusa), ele alcança defeituoso. Nas amizades que a garota ganha quando escolhe sua independência, incluindo a bonitinha Reese Witherspoon, há uma crítica ácida sobre as pessoas que buscam contato com pessoas famosas em algum lugar, mas que se perde no roteiro de Leslie Caveny, acostumado com produções televisivas de fácil degustação e pouca recompensa cinéfila. E o que dizer da reviravolta bobinha a respeito do que poderia quebrar a maldição?

Entre altos e baixos Penélope alcança o seu divertimento moderado em poucos momentos onde é claro se devemos rir ou chorar (incluindo a "moral de história"). Um passatempo televisivo que se veste como Cinema, contudo, não merece muita atenção. Sobre o que falávamos, mesmo?


# Bad Guy (aka Tipo Ruim)

Caloni, 2014-04-05 cinema movies [up] [copy]

Vi vários filmes desse diretor sul-coreano, um dos meus favoritos, e é fácil entender que ele possui estilo e temas que vão se refletindo no decorrer de sua carreira e que possuem como ponto em comum a narrativa quase sem diálogos de histórias simples, mas que através das expressões e enquadramentos de Kim-Ki Duk assume sempre o formato de um excelente estudo de personagem. É sem dúvida esse o caso em Fôlego, Casa Vazia, Pietá, Primavera, Verão... e nesse Bad Guy, ou Tipo Ruim —, onde o protagonista é um cafetão e o sexo vira pano de fundo para uma relação incomum entre duas pessoas que no princípio não tinham nada em comum.

O filme começa com um beijo proibido entre esse cafetão e uma garota universitária com seu namorado e todos os clichês dessa situação. Essa cena isolada tem um alto poder metafórico e é nosso guia para o resto da história que envolve uma obsessão que parece não ter limites e que vira em muitos ótimos momentos uma reflexão sobre auto-destruição. A rotina do prostíbulo onde ele trabalha é repetitiva e nos faz mudar de humor entre a excitação e a desesperança conforme o filme se arrasta. E ele se arrasta muito, parece que em vários momentos vai parar. Tudo isso para que percebamos pelas pequenas diferenças o que é importante para a história, o que envolve elementos prosaicos como um espelho, fotos rasgadas e um cabide.

Não é o trabalho mais coeso de Kim-Ki Duk e depois de Pietá está longe de ser o mais controverso, mas como sempre ele merece todos os créditos por fazer o Cinema sair de sua mesmice hollywoodiana e se aprofundar em temas cada vez mais abordados de maneira superficial pela indústria.


# Um Monstro em Paris

Caloni, 2014-04-05 cinema movies [up] [copy]

Uma animação francesa de alta qualidade em sua direção de arte, movimento dos personagens e números musicais que são bonitinhos por natureza, mas às vezes parecem mal trabalhados pela artificialidade do ritmo (talvez uma câmera aqui e ali resolvessem, mas a maioria dos números insiste em se manter na visão da plateia). É uma história batida a respeito de um monstro que surge na cidade de Paris na época em que ela abrigava ninguém menos que George Méliès, o mago da arte cinematográfica que tinha acabado de nascer e que foi homenageado recentemente no arranca-lágrimas Hugo Cabret.

O curioso da história é que o monstro na verdade é uma pulga superdesenvolvida, e isso é curioso porque boa parte dos truques de Mélès envolviam a ainda-não-velha técnica da perspectiva forçada: coloque uma lupa em um inseto e ele vira um monstro (ou um borrão, se formos realistas chatos). O batido da história é que há dois casais que com certeza ficarão junto no final do filme e sequer temos paciência de esperar isso acontecer. Podemos dizer que o roteiro se auto-sabota quando coloca essa questão em foco. O que salva realmente é a criatividade dos realizadores, principalmente a direção, que transforma o encontro entre o monstro e uma bela cantora do final da Belle Époque em um ponto forte.


# Oblivion

Caloni, 2014-04-06 cinema movies [up] [copy]

Oblivion consegue a proeza de citar diversas obras de ficção científica memoráveis e ainda assim ficar muito longe dos resultados que as mesmas obras tiveram em suas épocas. Talvez o maior problema seja Tom Cruise, que desde muito tempo vem repetindo suas performances e evitando que uma trama até que interessante ganhe frutos, um toque de Midas ao contrário que chega a rivalizar com Will Smith.

A história se passa mais de 60 anos no futuro, quando após em embate planetário com uma raça alienígena de saqueadores, "mas ganhamos a guerra", como gosta de repetir Jack, personagem de Cruise, a Lua foi destruída e com ela metade da vida na Terra, que além disso se contaminou com a radiação das bombas atômicas que foram necessárias para "ganhar a guerra". De mudança para Titã, um dos satélites de Saturno e que de fato se apresenta como uma das alternativas mais viáveis de moradia para um futuro distante, a espécie humana ainda precisa de água, e é por isso que Jack precisa resguardar com a ajuda de seus drones e sua esposa (Andrea Riseborough) um equipamento gigantesco que suga os oceanos. Uma operação diária de rotina é orquestrada por uma estação espacial triangular que enfeita o horizonte fantástico desse futuro distópico.

E por falar em horizonte, essa é uma das maiores virtudes de Oblivion. Cercado de terrenos completamente desertos e visivelmente alterados pelos acontecimentos do último século, os desenhos da equipe de produção são primorosos, além de nunca nos cansarmos de olhar para o céu ou as curiosas construções em torno deste. Infelizmente não se pode dizer o mesmo do acompanhamento sonoro, que é repleto de trilhas clichês e inconvenientes em boa parte da produção.

Jack é um homem treinado para proteger a Terra, mas parece incapaz de enxergar o perigo em sua volta, pois quase morre em diversos momentos da história por puro descuido. É um homem curioso e é assombrado por lembranças cinzentas de uma mulher (Olga Kurylenko, de Quantum of Solace) que não faz parte do seu passado. Aliás, nunca sabemos do passado de Jack ou de sua mulher, nem o que fez com que marido e esposa fizessem parte do mesmo projeto. No entanto, sabemos que ainda existem sobreviventes de outra raça rondando o planeta, e qualquer cuidado é pouco (mais um motivo para criticar a postura do mocinho).

O resto da história segue um plágio (na melhor das intenções, espero) mais ou menos bem definido entre O Vingador do Futuro, Wall-E, 2001, Planeta dos Macacos e continuações. Por não conseguir definir sua própria personalidade, o filme é sabotado em sua narrativa, que simplesmente acompanha o protagonista para o previsível embate, pelo qual nunca tememos (afinal de contas, é o Tom Cruise ali!).


# Lambda: o Retorno!

Caloni, 2014-04-08 computer [up] [copy]

Na última vez que foi abordado o tema "lambda na ferida" falamos brevemente sobre como C++ agora permite criar funções dentro de funções. Hoje vamos apenas falar que aquela construção bizarra que criamos fica ainda mais bizarra se precisarmos retornar alguma coisa dessa função ou usá-la mais de uma vez.

O padrão do lambda é supor que sua função embutida e enlatada não precisa retornar nada, o que torna a sintaxe mais simples: é um void AlgumaCoisa(argumentos). No entanto, para algoritmos como o find_if isso não funciona, então é necessário retornar algo. E, no caso de find_if, chamá-lo mais de uma vez pode ser feito facilmente criando uma variável lambda:

#include "Common.h"
#include <algorithm>
#include <vector>
#include <string>
int main()
{
    std::vector<Employee> employees; // um bando de empregados
    std::string currentDate = GetCurrentDate();
    // definindo uma função, como quem não quer nada, dentro de uma função
    auto FindByBithDate = [&]->bool // <-- tipo de retorno
    {
      return employee.birthDate == currentDate;
    };
    GetEmployees(employees);
    auto findIt = std::find_if(employees.begin(), employees.end(), FindByBithDate);
    while( findIt != employees.end() )
    {
      SendMail(*findIt);
      findIt = std::find_if(findIt + 1, employees.end(), FindByBithDate);
    }
}

O tipo de retorno que colocamos através de uma flechinha é obrigatória? De fato, não. Se eu omiti-la vai funcionar do mesmo jeito porque o único ponto de saída da minha função retorna um bool.

Esses compiladores estão ficando cada vez mais espertos.


# Noé

Caloni, 2014-04-09 cinema movies [up] [copy]

O filme é muito melhor que o livro, mas nesse caso estamos falando de um livro escrito há milênios atrás e que sequer é um livro, mas dois ou três versículos de Gênesis, o primeiro dos mais de 70 trabalhos da Bíblia. Porém, o dilúvio, ou inundação global, também é um mito amplamente conhecido por povos antigos, todos à mesma época, e existiam diversas formas de contar a mesma história (incluindo o Livro de Enoque, que cita a existência dos anjos vigilantes). Nesse sentido, podemos dizer que a versão escrita pelo diretor Darren Aronofsky (Cisne Negro, O Lutador, Pi) e seu produtor Ari Handel consegue mesclar de maneira surpreendente essas histórias em uma discussão razoavelmente interessante sobre a luta do bem contra o mal, da crença e dos desígnios de um Criador e da natureza de nosso livre-arbítrio.

Mas do que isso, Noé consegue a proeza de recriar seu personagem-título com a ajuda muito bem-vinda de Russell Crowe não apenas como um enviado de Deus, mas como um ser humano primitivo e obediente do desconhecido, além de sua família formada pelos seus três filhos em três fases distintas de compreensão do pai, uma garota adotada (Emma Watson) que sofre a angústia de possivelmente ser a única mulher sobrevivente do castigo divino e não poder engravidar, e, por fim, uma composição delicada de Jennifer Connelly como uma esposa submissa, mas pensante e nosso guia moral; se há um ótimo motivo para ir ao cinema é testemunhar seu doce sorriso após quase duas horas de projeção.

Não é um filme necessariamente de ação, mas essa parte é muito bem desempenhada, ainda mais pela presença de certos seres mitológicos que junto com o céu estrelado mesmo de dia e animais de espécies inexistentes complementam a ideia de um mundo sobrenatural e antigo: um mundo que não nos pertence mais. Para os religiosos e pessoas sensíveis como eu há inúmeras cenas-catarse no decorrer da narrativa que funcionam exatamente porque Aronofsky as dosa com poder milimétrico, além de ser auxiliado pela indispensável trilha sonora de Clint Mansell, que consegue engrandecer sem ferir a naturalidade dos acontecimentos.

Essa é a primeira incursão do diretor e sua equipe no 3D, que pode até ter sido uma imposição do estúdio, mas aqui é feito com o esmero de um realizador que sabe o que faz. Dessa forma é um prazer presenciar um furacão de seres voadores, a expansão do universo ou qualquer cena que o filme tenha a oportunidade de aplicar sua profundidade de campo. Não é um uso gratuito, porque assim como a música, comenta os acontecimentos muitas vezes desafiadores do bom senso.

E, por falar em bom senso, é óbvio que não dá para esperar uma ficção científica de um conto antigo, e é por isso que a suspensão de descrença é vital para aproveitar a sessão, mas nem por isso o filme deixa de florear diversas passagens bíblicas e enfatizar que flerta duramente com a possibilidade real de um dilúvio. Isso, para mim, é respeito pela arte de contar histórias. Um espectador que sabe que vai assistir um faz-de-conta deveria ter a mente aberta para tentar entender quais as subtramas que fazem parte dessa realidade fantástica. Não é com esse objetivo que histórias como Chapeuzinho Vermelho foram inventadas?


# Madoka Magica

Caloni, 2014-04-14 cinema animes [up] [copy]

A revisita a este animê que para mim ainda é meu favorito -- pela originalidade e pela fuga do lugar-comum e dos roteiros fáceis que a maioria das adaptações dos quadrinhos japoneses são submetidos -- foi feita em apenas uma noite. Mais de quatro horas depois posso reafirmar com convicção: é uma obra ousada para seu formato tanto em história quanto na direção/edição/arte. Desafia o espectador a esquecer os detalhes centrais de uma história que vai se abrindo muito lentamente, e sua força é sentida exatamente por esse cuidado em cada detalhe.

Madoka Mágica é um trabalho caricatual que segue à risca a cartilha de heroinas de cosplay (ou, diria, se usa desse artifício como metalinguagem e crítica ao gênero), mas, mais do que isso, segue um tratamento estilizado e inspirado levemente no surrealismo, mas que empurra a animação para além das histórias de luta ao lidar com conceitos complexos como auto-sacrifício, religião, viagens no tempo, destino e física teórica (além de vida extraterrena) sem perder seu ritmo com história secundárias bobinhas para fazer rir/ganhar tempo. É uma fantasia com um pé na ciência, um pé na filosofia e outro pé na arte. Esse tripé mantém a câmera posicionada nos lugares mais inusitados para capturar cada quadro como se esse fosse uma obra de arte única a resumir aquele momento através de sutis e significativos movimentos.

E há vários momentos que merecem ser congelados para nossa apreciação.

A história gira em torno de Madoka Kaname, uma garota comum que encontra um bicho estranho e mágico que revela que existem garotas mágicas que lutam contra bruxas e salvam pessoas de suicídios. Na verdade, revela mais: ela e sua amiga, Sayaka Miki, podem se tornar garotas mágicas também, e a recompensa por este feito heróico é terem um desejo, qualquer desejo, realizado pelo tal bicho mágico.

O curioso da série é que ela não tem pressa em realizar o que 90% das produções semelhantes ocidentais fariam: um grupo de garotas lutando contra o mal a la Meninas Superpoderosas. No fundo, o "mal" aqui não está materializado e nem tem desejo de fúria. Ele é um conceito, e relativo, dependendo do ponto de vista. Sequer há emoções em jogo. Na verdade, é mais profundo que isso: a emoção aqui é usada de uma maneira completamente diferente. Uma Meninas Superpoderosas para gente grande.

Mas além da empolgante história o que cativa mesmo o espectador é a qualidade narrativa criada não apenas a partir dos sensacionais traços dos criadores, mas de uma invejável e coesa trilha sonora (Yuki Kajiura) e uma fotografia de cair o queixo (Shinichiro Eto). Tudo isso, com a edição de Rie Matsuhara, combina em uma experiência sensorial cada vez mais fácil de ser encontrada em séries de TV ambiciosas e menos nos cinemas comerciais.


# Geleia de Código

Caloni, 2014-04-15 [up] [copy]

Não costumo participar de campeonatos de programação por alguns motivos vagos: é perda de tempo (não ganho nada com isso), sou um péssimo programador (ou pasteleiro), dá preguiça (esse é o mais válido) e por aí vai o mimimi. Dessa forma, sempre passei ileso de eventos como o atual Google Code Jam, que pretende levar a categoria de código ofuscado para um novo patamar.

No entanto, esse ano apareceram dois motivos que me levaram a gastar cinco minutos de paciência com as historinhas bestas da equipe do Google. Primeiro o Python, que desde 2013 tem renovado em mim a sensação que programar ainda é divertido (e que o pessoal da Microsoft e do padrão C++ tinham tirado de mim há muito tempo com seus compiladores cada vez mais complexos/lentos e as IDEs que demoram o tempo do cafezinho para abrir). Segundo o que move o mundo: a concorrência. Minha digníssima esposa, levada por alguns pontos-extra na faculdade (uma iniciativa até que louvável do professor), resolveu participar da primeira fase (a classificação desta fase também dava pontos).

O fato é que depois desses cinco minutos eu simplesmente não consegui parar até o minuto final das 23 horas (horário de Brasília) de domingo, quando o tempo-limite esgotou. O aspecto mais divertido do Code Jam é que há liberdade total para a ferramenta que você pretende usar: linguagens de programação, Excel, uma calculadora ou apenas seu cérebro. Você recebe uma "missão" e um arquivo de entrada e precisa cuspir um arquivo de saída de acordo com a missão. Apenas isso. O resto fica por conta da criatividade dos codadores e gambiarreiros de plantão.

Todos os exercícios levam em consideração um arquivo de entrada que possui em sua primeira linha o número de testes que serão feitos e em seguida um número determinado de linhas e parâmetros, geralmente divididos por espaço. O primeiro problema, por exemplo, apenas considerava a suposição de cartas em pequeno truque de mágica e recebia como entrada a disposição dessas cartas junto com a escolha da fileira que o participante dizia onde estava a carta escolhida.

   
   2
   1 2 3 4
   5 6 7 8
   9 10 11 12
   13 14 15 16
   3
   1 2 5 4
   3 11 6 15
   9 10 7 12
   13 14 8 16
import sys
f = open(sys.argv[1])
total = int(f.readline())
for case in range(0, total):
    guess1 = int(f.readline())
    row1 = None
    for i in range(1, 5):
      row = f.readline().split()
      if i == guess1:
        row1 = row
    guess2 = int(f.readline())
    row2 = None
    for i in range(1, 5):
      row = f.readline().split()
      if i == guess2:
        row2 = row
    cards = list(set(row1) & set(row2))
    if len(cards) == 1:
      print 'Case #' + str(case+1) + ': ' + cards[0]
    elif len(cards) > 1:
      print 'Case #' + str(case+1) + ': Bad magician!'
    else:
      print 'Case #' + str(case+1) + ': Volunteer cheated!'

O segundo exercício já envolvia um jogo bem divertido em que o jogador ficava clicando em cookies como se não houvese amanhã. Esse deu um pouco mais de trabalho, mas foi mais divertido que o primeiro.

import sys
def CookieClicker(farmCost, farmIncrement, cookieTarget):
    cookiePerSecond = 2.0
    bestTime = cookieTarget / cookiePerSecond # melhor tempo soh fazendo cookies
    cookieFarmTime = cookieTarget / (cookiePerSecond + farmIncrement) # melhor tempo ja com fazenda criada
    farmTime = farmCost / cookiePerSecond + cookieFarmTime # quanto vai custar fazer a fazenda e depois fazer cookies com a fazenda
    while farmTime < bestTime: # enquanto fazer a fazenda custar menos tempo que soh fazer cookies...
      bestTime = farmTime # por enquanto melhor tempo
      cookiePerSecond = cookiePerSecond + farmIncrement # novo tempo para fazer cookies (mais uma fazenda ja criada)
      farmTime = farmTime - cookieFarmTime # tiramos o tempo de soh fazer cookies para fazer mais uma fazenda
      cookieFarmTime = cookieTarget / (cookiePerSecond + farmIncrement) # novo tempo com mais uma fazenda criada
      farmTime = farmTime + farmCost / cookiePerSecond + cookieFarmTime # agora com o novo tempo de fazer outra fazenda e soh cookies
    return bestTime
f = open(sys.argv[1])
total = int(f.readline())
for case in range(1, total + 1):
    args = [float(i) for i in f.readline().split()]
    ret = CookieClicker(args[0], args[1], args[2])
    print 'Case #' + str(case) + ': ' + '{0:.7f}'.format(ret)

Já o terceiro... o terceiro passa. Vamos para o quarto, um dos mais instigantes, pois envolve duas regras distintas de um jogo e a otimização das melhores estratégias para ambos. Isso consumiu bem mais tempo que os outros dois iniciais, pois lembro de ter me isolado por uma hora para conseguir colocar tudo na cabeça.

import sys
def BestBlock(block, blocks):
    bestBlock = 0
    for i in range(len(blocks) - 1, -1, -1):
      if blocks[i] < block: break
      bestBlock = blocks[i]
    if not bestBlock:
      bestBlock = blocks[0]
    return bestBlock
def War(naomi, ken):
    naomi = sorted(naomi)
    ken = sorted(ken)
    naomiCount = 0
    while len(naomi):
      naomiBlock = naomi[-1]
      kenBlock = BestBlock(naomiBlock, ken)
      if naomiBlock > kenBlock:
        naomiCount = naomiCount + 1
      #print str(naomiBlock) + ' vs ' + str(kenBlock) + ': ' + str(naomiCount)
      naomi.remove(naomiBlock)
      ken.remove(kenBlock)
    return naomiCount
def WarCheat(naomi, ken):
    naomi = sorted(naomi)
    ken = sorted(ken)
    naomiCount = 0
    while len(naomi):
      naomiTold = 0
      naomiBlock = naomi[-1]
      bestKen = ken[-1]
      if naomiBlock > bestKen:
        naomiTold = bestKen + 0.00000001
      else:
        naomiTold = bestKen - 0.00000001
      kenBlock = BestBlock(naomiTold, ken)
      naomiBlock = BestBlock(kenBlock, naomi)
      if naomiBlock > kenBlock:
        naomiCount = naomiCount + 1
      #print str(naomiTold) + '(' + str(naomiBlock) + ') vs ' + str(kenBlock) + ': ' + str(naomiCount)
      naomi.remove(naomiBlock)
      ken.remove(kenBlock)
    return naomiCount
f = open(sys.argv[1])
total = int(f.readline())
for case in range(1, total + 1):
        f.readline()
        naomi = [float(i) for i in f.readline().split()]
        ken = [float(i) for i in f.readline().split()]
        war = War(naomi, ken)
        warCheat = WarCheat(naomi, ken)
        print 'Case #' + str(case) + ': ' + str(warCheat)+ ' ' + str(war)

Já o terceiro foi um fracasso total. Tentei de todas as maneiras resolver o impasse de descobrir qual disposição de um jogo de campo minado poderia ser resolvido em apenas um clique (parece o jogo oposto do viciado clicador de cookies), mas falhei miseravelmente. E desconfio o porquê. Primeiro entendo que meu perfeccionismo me impediu de realizar uma checagem padrão para exceções já conhecidas (quando há apenas uma linha ou coluna, quando há apenas um espaço sem minas, etc). Eu pensei: se o Google fez esse problema, ele deve ter bolado alguma solução genérica que independa de ifs. Bom, não que eu saiba. Depois de terminado o tempo dei uma olhada em algumas soluções dos competidores e não achei nenhuma solução que usasse algum algoritmo maluco e genérico (não achei nenhum indiano, contudo).

Eis a solução porca e mal-resolvida (alguns pontos do códido foram feitos depois de ver o código de outrem):

import sys
def FieldToString(field):
        ret = '\n'
    for r in field:
      for c in r:
        ret = ret + str(c)
      ret = ret + '\n'
    return ret
def CountMines(field, r, c):
        ret = 0
        row = len(field)
        col = len(field[0])
        if r < row-1 and field[r+1][c] == '*': ret = ret + 1
        if c < col-1 and field[r][c+1] == '*': ret = ret + 1
        if r > 0 and field[r-1][c] == '*': ret = ret + 1
        if c > 0 and field[r][c-1] == '*': ret = ret + 1
        if r < row-1 and c < col-1 and field[r+1][c+1] == '*': ret = ret + 1
        if r > 0 and col > 0 and field[r-1][c-1] == '*': ret = ret + 1
        if r < row-1 and c > 0 and field[r+1][c-1] == '*': ret = ret + 1
        if r > 0 and c < col-1 and field[r-1][c+1] == '*': ret = ret + 1
        return ret
def ExpandClick(field, r, c):
        if field[r][c] != '0': return
        def Expand(field, r, c):
                if field[r][c] == '.':
                        field[r][c] = str(CountMines(field, r, c))
                        ExpandClick(field, r, c)
        row = len(field)
        col = len(field[0])
        if r < row-1 and field[r+1][c] != '*':
                Expand(field, r+1, c)
        if c < col-1 and field[r][c+1] != '*':
                Expand(field, r, c+1)
        if r > 0 and field[r-1][c] != '*':
                Expand(field, r-1, c)
        if c > 0 and field[r][c-1] != '*':
                Expand(field, r, c-1)
        if r < row-1 and c < col-1 and field[r+1][c+1] != '*':
                Expand(field, r+1, c+1)
        if r > 0 and col > 0 and field[r-1][c-1] != '*':
                Expand(field, r-1, c-1)
        if r < row-1 and c > 0 and field[r+1][c-1] != '*':
                Expand(field, r+1, c-1)
        if r > 0 and c < col-1 and field[r-1][c+1] != '*':
                Expand(field, r-1, c+1)
def FieldClicker(field):
    row = len(field)
    col = len(field[0])
        for r in range(row):
                for c in range(col):
                        if field[r][c] == 'C':
                                field[r][c] = str(CountMines(field, r, c))
                                ExpandClick(field, r, c)
                                break
        return field
def FieldValidate(field):
        ret = True
    row = len(field)
    col = len(field[0])
        for r in range(row):
                for c in range(col):
                        if field[r][c] == '.':
                                ret = False
                                break
        return ret
def FieldRender(row, col, mines):
    field = []
        for i in range(row):
                field.append(['.'] * col)
        if row == 2:
                nextRow = 0
                nextCol = 0
                while mines:
                        field[nextRow][nextCol] = '*'
                        nextRow = nextRow + 1
                        if nextRow == row:
                                nextRow = 0
                                nextCol = nextCol + 1
                        mines = mines - 1
                field[0][col-1] = 'C'
        elif col == 2:
                nextRow = 0
                nextCol = 0
                while mines:
                        field[nextRow][nextCol] = '*'
                        nextCol = nextCol + 1
                        if nextCol == col:
                                nextRow = nextRow + 1
                                nextCol = 0
                        mines = mines - 1
                field[row-1][0] = 'C'
    elif row * col - mines < 3:
                nextRow = row - 1
                nextCol = 0
                while mines:
                        field[nextRow][nextCol] = '*'
                        nextCol = nextCol + 1
                        if nextCol == col:
                                nextRow = nextRow - 1
                                nextCol = 0
                        mines = mines - 1
                field[0][col-1] = 'C'
        else:
                for r in range(len(field)):
                        for c in range(len(field[0])):
                                field[r][c] = '*'
                if row * col - mines >= 9 and row >= 3 and col >= 3:
                        empties = row * col - mines
                        nextRow = 0
                        nextCol = 0
                        while empties:
                                
    return field
def Mine(row, col, mines):
        if row * col - mines == 2 and row > 1 and col > 1:
      return 'Impossible!'
    if row * col - mines == 3:
      return 'Impossible!'
    elif row * col - mines == 5:
      return 'Impossible!'
    elif row * col - mines == 7:
      return 'Impossible!'
    else:
      return FieldToString(FieldRender(row, col, mines))
f = open(sys.argv[1])
total = int(f.readline())
for case in range(1, total + 1):
        field = [int(i) for i in f.readline().split()]
        print 'Case #' + str(case) + ': ' + Mine(field[0], field[1], field[2])
#############################################################################3
def FieldRenderWrong(row, col, mines):
    field = []
    for i in range(row):
      field.append(['.'] * col)
        def GetNextRow(field, clickRow, clickCol):
                row = len(field)
                col = len(field[0])
                nextRow = 0
                nextCol = 0
                rowDist = 0
                colDist = 0
                for r in range(row):
                        for c in range(col):
                                if field[r][c] == '.':
                                        rDist = abs(r - clickRow)
                                        cDist = abs(c - clickCol)
                                        totDist = rDist + cDist
                                        currTotDist = rowDist + colDist
                                        if totDist > currTotDist:
                                                nextRow = r
                                                rowDist = rDist
                                                nextCol = c
                                                colDist = cDist
                                        else:
                                                rowCount = 0
                                                for r2 in range(row):
                                                        if field[r2][c] == '*':
                                                                rowCount = rowCount + 1
                                                colCount = 0
                                                for c2 in range(col):
                                                        if field[r][c2] == '*':
                                                                colCount = colCount + 1
                                                lastRow = rowCount == row - 1
                                                lastCol = colCount == col - 1
                                                if lastRow or lastCol:
                                                        nextRow = r
                                                        rowDist = rDist
                                                        nextCol = c
                                                        colDist = cDist
                return nextRow, nextCol
        clickRow = 0
        clickCol = col-1
    field[clickRow][clickCol] = 'C'
        nextRow, nextCol = GetNextRow(field, clickRow, clickCol)
    while mines:
      field[nextRow][nextCol] = '*'
      nextRow, nextCol = GetNextRow(field, clickRow, clickCol)
      mines = mines - 1
    return field

Não, eu não usei o Google para descobrir a lógica por trás do problema. Vai que os caras ficam monitorando quem fica fazendo pesquisas. E, não, tampouco usei o Bing. Não sou masoquista a esse ponto.

_PS: Bom, estou na próxima fase. Veremos o que o futuro nos espera. Esse programador foi fisgado pelo campeonato de pastéis._


# Gigantes de Aço

Caloni, 2014-04-16 cinema movies [up] [copy]

Esse é aquele tipinho de filme que tem o espírito Disney e Spielberg ao mesmo tempo, tanto que é produzido por ambos, mas felizmente consegue lançar uma nova e empolgante luz para uma história já batida. Conduzido pelo diretor/produtor Shawn Levy e escrito por John Gatins (O Voo e... arght! Norbit), ambos estão claramente "inspirados" pelo coração de Mickey Mouse e o dedo de E.T.: a história une pai e filho, até então completos desconhecidos, em torno da luta de robôs de aço gigantes, uma mania que se tornou a regra após a decadência do boxe e das lutas de UFC por conta da sede cada vez maior do público por destruição total.

E destruição total é o que bem define Charlie Kenton (Hugh Jackman, ótimo), que parece destruir todas as oportunidades de se reerguer de apostas cada vez mais arriscadas e que sempre dão errado. Até a chegada da notícia do falecimento de sua ex-esposa e o ressurgimento de Max Kenton (Dakota Goyo, excelente), seu filho quase-bastardo. Evitando a todo o custo sua aproximação, Charlie chega a trocar a guarda do filho por dinheiro de seu cunhado rico, uma vez que sua tia deseja adotar o garoto. Porém, um mês de férias com o menino é o suficiente para que ele perceba que talvez tenha a chance definitiva de fazer uma única coisa certa em sua vida.

O filme empolga com ótimas construções em torno da fascinação de Max pela luta de robôs e como o seu temperamento idêntico ao do pai (talvez mais jovem e esperançoso), nos fazendo ficar empolgados no processo a respeito desse mundo, que se abre aos poucos, o que nos deixa entender como tudo funciona em detalhes que são organicamente colocados durante a trama. Tirando os personagens caricatos (praticamente todos, exceto a dupla Jackman/Goyo) e as situações caricatas (todas que tem música de fazer chorar e a câmera gira) o filme possui cortes precisos em torno da ação e é preciso ter um coração de lata para não se emocionar com o primeiro soco dado pelo robô deles na última luta.

Tudo isso, porém, não faria sentido, se os robôs mostrados no filme fossem indiferentemente retratados como nos três primeiros Transformers de Michael Bay. No entanto, além de efeitos visuais tão bons que sequer são notados, a imaginação dos realizadores através dos movimentos desses pequenos gigantes é algo que assusta a cada momento e nunca foge da realidade. Praticamente nos acostumamos a ver robôs andando em meio à multidão e lutando nos mais diferentes ringues. Isso se torna uma realidade absorvida completamente durante o filme, o que é um mérito e tanto dos criadores.


# Sword Art Online - Primeira Temporada

Caloni, 2014-04-16 cinema animes [up] [copy]

O tema de mundos virtuais já tem certa data, mas é a primeira vez que vejo ele ser explorado nos jogos online. Mais interessante, ainda, é construir uma história cujo pano de fundo é o lançamento de mais um RPG online a la "World of Warcraft", com direito a versões beta, coleção de itens, aumento de experiência, novas habilidades, com a diferença que seu controle é exercido e sentido diretamente pelo cérebro dos jogadores atráves de um sensor na forma de capacete. O enredo principal: se os criadores de um jogo de realidade virtual conseguem controlar os sentidos de seus jogadores o que os impede de levar essa experiências às últimas consequências?

Com base nisso e um bom toque de animê/novela é que Sword Art Online se baseia ao longo da sua temporada de 25 capítulos divididos tematicamente em duas "fases". A primeira é a melhor das duas, pois expande diversos conceitos curiosos a respeito desse futuro distópico, como a relação afetiva (e sexual) entre seus membros e qual é a definição de "sentimento" nesse mundo, além de em diversos momentos utilizar a figura do casal principal Kirito e Asuna para servir de olhos e reflexão do espectador sobre o que faria em determinadas situações, ou até onde vai a brincadeira. Nesse sentido, a vinda de uma personagem muito especial "adotada" pelos heróis é sintomático e um dos melhores momentos da série, além de representar muitas homenagens óbvias ao longo da narrativa, notadamente Matrix, a obra cinematográfica dos irmãos Wachoski (que já referenciava e homenageava praticamente todos os ramos do entretenimento e da filosofia em torno da possibilidade de estarmos sonhando acordados em um mundo de mentiras).

É com o uso de uma excelente trilha sonora dramática quase nunca exagerada e ótimas cenas de ação que a primeira metade de SAO capta a essência de sua história. Claro que isso ocorre graças ao pano de fundo que vai sendo contruído junto com a relação entre seus personagens, pois essa não é uma série de lutas de espadas comuns, mas uma interessantíssima reflexão sobre o que o ser humano é capaz de fazer para sobreviver e manter a sua honra, seu caráter, seus princípios. Existiria uma ética em um mundo onde tudo é possível?

Essas questões existenciais parecem que nunca envelhecem...


# Sword Art Online - Segunda Temporada

Caloni, 2014-04-16 cinema animes [up] [copy]

A série japonesa de animação SAO (Sword Art Online) possui uma estrutura bem confusa. Essa segunda temporada é formada por duas histórias, assim como a primeira, mas diferente da primeira as histórias quase não têm relação.

Na primeira parte entramos em um jogo de tiros, o que descaracterizaria o nome da série não fosse a espirituosa referência a Star Wars e o menino que usa uma espada para desviar das balas. Kirito aqui adquire poderes sobrenaturais, o que é uma próxima escala aceitável considerando o desfecho da história anterior. Já Asuna possui muito mais novas experiências. Aprendemos como é sua família, e uma nova amizade (segunda parte) consegue abordar um dos melhores temas da série até agora, quiçá o melhor.

Pra variar, as sequências de ação funcionam quase todo o tempo. No entanto, como toda série comercial, existem episódios de enche-linguiça, e há um momento de tanta pausa nas lutas que o animê vira um quase-drama. Ainda assim, e a despeito de parecer em alguns momentos que estamos assistindo um vídeo do YouTube de jogadores online, SAO ainda impressiona pela construção de seus personagens principais, a interação entre eles e as reflexões sempre inspiradas da dualidade real/virtual (há um momento em que Asuna e Kirito admitem que não é tão relevante assim pontuar qual a camada real, uma vez que esta pode ser apenas mais uma camada de uma série infinita; nunca saberemos).

Sempre com um figurino de dar inveja a muitos animês, e se aproveitando das possibilidades dos mundos virtuais para criar sequências criativas, SAO sempre pode ser melhor do que é, mas no nível que está, já impressiona um bocado.


# As Crônicas de Spiderwick

Caloni, 2014-04-17 cinema movies [up] [copy]

Essa é basicamente uma versão infanto-juvenil de A Morte do Demônio: alguém acha um livro amaldiçoado em uma casa abandonada e que ninguém deveria habitar e agora está impossibilitado de sair do lugar, pois parte da maldição prega que tanto o livro quanto seus leitores devem ser eliminados. A parte infanto-juvenil da história é que ela deve envolver ogros, globlins, trolls, ter uma moral da história, que se for Disney/Spielberg, vai envolver uma relação pai e filho... bingo!, e, o essencial: ninguém deve se machucar no processo, mas todos devem se divertir como em um parque de diversões temático.

A diferença desse tipo de filme e Os Goonies é que os personagens do clássico dos anos 80 eram cativantes, espertos e tinham o espírito da aventura. Os personagens de Crônicas de Spiderwick são espectadores passivos de um pequeno deslize que o pequeno Jared toma quando, mesmo advertido com um bilhete de aviso, ainda assim abre o maldito livro. Freddie Highmore, que está encantador no remake de A Fantástica Fábrica de Chocolates, está aqui no papel de Jared. Após este pequeno deslize o resto é um filme de uma hora e meia sobre as consequências deste único ato.

Mas, como já disse, não é um filme ruim, embora eu gostaria que fosse. Ficar no meio do caminho entre o bom e o ruim é o caminho mais fácil para um filme ser esquecido, mas não a sensação de ter duas horas de sua vida desperdiçada.


# Woman in Love (aka Rubbeldiekatz)

Caloni, 2014-04-18 cinema movies [up] [copy]

Essa é uma comédia romântica estilo Notting Hill, com a diferença de ser na Alemanha e ter o plot de um ator que se veste de mulher para conseguir o papel em um curta produzido por Hollywood sobre o nazismo (sempre ele). O resultado é algumas pouquíssimas piadas semi-originais, quase sempre envolvendo o ator que representa Hitler, e muitas piadas recicladas daquela velha situação do homem travestido já visto em produções tão bizarras desde "Glen ou Glenda?" (Ed Wood, 1953) passando por As Branquelas (2004).

O problema principal é no seu início, que não consegue nos convencer da história que pretende contar. A única coisa que lembro é que o diretor gosta de usar câmeras lentas. Muitas. Em exaustão e sem significado. A própria "paixão à primeira vista" do casal principal é enfocado em uma longa e tediosa cena de sexo, e o fato de ter tediosa é um feito e tanto, já que estamos falando de uma cena com a bela Alexandra Maria Lara, cuja atuação nem impressiona nem decepciona. O resto do filme é leve, sincero e cativante. O trabalho de Matthias Schweighöfer como o ator travestido convence por seu tipo físico quase andrógeno, mas não por sua atuação sem alma.

No final temos aquela velha perseguição em busca da pessoa amada que vemos em gêneros Notting Hill. E se citei novamente o ótimo trabalho de Roger Michell não é por que estou pegando no pé dele, mas apenas porque é um filme fácil de se lembrar, exatamente porque utiliza razoavelmente bem os seus clichês. No caso de Woman in Love, são apenas clichês reproduzidos em alemão.


# Uma Manhã Gloriosa

Caloni, 2014-04-19 cinema movies [up] [copy]

Uma Manhã Gloriosa é o tipo de filme que tem tudo para ser mais uma comédia romântica clichê com um final feliz e uma boa lição de moral. No entanto, a direção sempre presente de Roger Michell consegue, assim como em Um Lugar Chamado Notting Hill, transformar um roteiro trivial em uma empolgante experiência pelo mundo da mídia televisiva.

A história gira em torno de Rachel McAdams (Diário de uma Paixão), produtora executiva de um telejornal. Esperando por uma promoção, é demitida, e consegue um emprego apenas em um outro telejornal matinal largado às traças, como o próprio diretor do estúdio (Jeff Goldblum) o coloca. No entanto, o desespero da personagem de McAdams tenta de toda forma virar esperança, o que a faz tomar decisões arriscadas, como escalar um lendário e ranzinza âncora (Harrison Ford) que é conhecido nos bastidores como a terceira pior pessoa do mundo.

O filme consegue nos fazer pensar no pior mesmo sendo uma comédia, da mesma forma com que o brilhante Missão Madrinha de Casamento. Além disso, faz uma curiosa crítica sobre o conteúdo da TV estar sendo direcionado por um público que anseia cada vez mais pela risada fácil e menos pelo conteúdo. Harrison Ford convence do começo ao fim, o que não é pouca coisa considerando seus filmes de menor expressão (e até os blockbusters como Star Wars ou Indiana Jones).

No fundo, o que uma dramédia romântica mais precisa é de personagens críveis, uma boa trilha sonora e uma história que não saia dos trilhos. Esse filme tem tudo isso e conseguimos enxergá-lo sem muito esforço. Afinal de contas, é um divertimento temporário ao qual estamos assistindo, não Cidadão Kane.


# Actores S.A.

Caloni, 2014-04-20 cinema movies [up] [copy]

Uma comédia argentina com um roteiro até que interessante visto de fora, mas de dentro é uma bagunça. Possui uma história que gira em torno do salvamento de um teatro ao mesmo tempo que constrói a relação do casal protagonista, ambos se relacionando através de coincidências absurdas. A ideia dos atores para conseguir dinheiro é aceitar qualquer trabalho, mesmo fora dos palcos. Porém, não é isso o que atores já fazem? Ainda mais os decadentes? Qual seria a grande ideia para este filme?

Enfim, logo no segundo "serviço por fora" há uma proposta de 3 milhões, e não é preciso dizer que ela irá tomar o tempo de todo o resto do filme. Mais reviravoltas acontecem, e situações engraçadinhas enchem linguiça, particularmente uma envolvendo armas, beijos gays (ou não) e uma câmera absurdamente grande. Contratados para impedir um casamento que mais parece um contrato entre empresas, não há emoção senão risadas disfarçadas de constrangimento.

Um mal roteiro pode ser salvo por uma direção competente assim como um bom roteiro pode ser estragado completamente por uma direção equivocada. Actores S.A. se enquadra na segunda situação.


# Hoje Eu Quero Voltar Sozinho

Caloni, 2014-04-23 cinema movies [up] [copy]

Quatro anos depois do diretor Daniel Ribeiro realizar um dos curtas mais concisos e injustamente chamados de polêmicos a respeito da paixão de um garoto cego por um aluno novo da escola, eis que o mesmo Daniel Ribeiro dirige e escreve com os mesmos atores principais a versão em longa metragem dessa história, e se isso geralmente é uma péssima ideia por tentar alongar uma ideia que só funciona por dezessete minutos, nesse caso o resultado é no mínimo cativante.

Buscando uma identidade visual (e sonora) ao abordar pela primeira vez Leonardo (Ghilherme Lobo) e sua amiga Giovana (Tess Amorim) de cima, estirados em torno da piscina, essa cena inicia no escuro com o som das ondas geradas pelo braço de Leo na água. O filme se esquece de usar essa mesma rima em diversos momentos apropriados, mas usa outra, essa muito mais eficiente: mostra seus personagens apenas das pernas para cima, como se andassem nas nuvens, além de diminuir a profundidade de campo sempre que possível, focando muitas vezes em um único ponto. Isso não é cegueira, mas para quem enxerga, consegue extrair muito da visão de mundo de Leo, que depende muitas vezes da ajuda dos outros para realizar alguma ação simples, mas evita, sempre que possível, transparecer sua dependência.

É, portanto, natural, até nessa idade, que Leo bata de frente com a super-proteção dos pais, que, sim, usam a deficiência visual do filho como um motivo presente, embora nem sempre dito. Já na escola ocorre justamente o contrário, pois sua deficiência sempre vira motivo ou de compaixão ou de brincadeiras. Dessa forma, se seus colegas costumam praticar o bullying nosso de cada dia, sua amiga Giovana se preocupa em demasiado com o amigo, talvez por gostar dele mais do que como um amigo. De toda forma, é compreensível que a vinda de Gabriel (Fabio Audi) dê essa sensação de novos ares, pois este não está acostumado com os "temas proibidos" de serem abordados com pessoas com essa limitação (como perguntar se viu um vídeo no YouTube).

As descobertas dessa época sempre são excitantes e frustrantes ao mesmo tempo, e o filme consegue demonstrar isso de uma maneira equilibrada com o triângulo amoroso entre Léo, Giovana e Gabriel. Digo "triângulo" porque o roteiro evita criar complicações a respeito de uma quarta personagem, e com isso perde densidade. Talvez a relação nessas uma hora e meia de filme seja equilibrada demais, pois evita justamente as questões que poderiam estar presentes dos espectadores do curta-metragem (onde está o depois?), o que pode soar até um tanto covarde.

No entanto, existem momentos "picantes" entre os meninos, o suficiente para fazer sair dos buracos mais escuros os moralistas de plantão. Porém, diferente do quasi-soft-porn Azul é a Cor Mais Quente, essa transição de sentimentos e sensações soa tão natural e tão de acordo com o ritmo do amarrado roteiro, que consegue explicar esse triângulo amoroso usando um eclipse, que esses momentos não são apenas esperados, mas até desejados. Afinal de contas, quem não quer sentir o prazer de ver pessoas decentes em busca de sua própria felicidade?


# 2048 motivos para não programar

Caloni, 2014-04-24 computer blogging [up] [copy]

Pronto, posso programar em paz. O jogo 2048 é uma lástima para todos os trabalhadores intelectuais que dependem de suas mentes para produzir algo que preste. Ele gerou mais posts no Hacker News do que a moda dos bitcoins (talvez não) e mais projetos no GitHub do que a busca para a cura do câncer (talvez não). Obviamente que este post vai gerar mais um gist Python para minha coleção.

Não sou fã de jogos, e dos poucos que participei logo parei (exceções honrosas: Portal e Portal 2, esses malditos). Posso dizer o mesmo de 2048, a versão de uma espécie de jogo já conhecido feita pelo italiano Gabriele Cirulli em um fds para descobrir se seria capaz de fazê-lo. Ele o fez e de brinde também fez o índice de produtividade mundial desabar.

Houve pelo menos dois projetos de I.A. para resolver o problema, que consiste em dobrar números múltiplos de 2 em um quadrado 4 x 4 até que se consiga o quadrado com o valor 2048 (e além). O artigo de Nicola Pezzotti, An Artificial Intelligence for the 2048 game, explica o mais efetivo deles, de autoria de Robert Xiao (eu acho). O programa desenvolvido por Xiao otimiza o tabuleiro do jogo guardando-o em um inteiro de 64 bits, deixando 4 bits para cada casa, mais que o suficiente para que seja armazenada a potência de 2 localizada no quadrado (o limite fica sendo de 2 16, ou 65536). Ao rodar a versão executável console ele imprime cada posição do tabuleiro em um formato "fácil" de ser lido.

   Move #69, current score=584
    1356
    0051
    0012
    0000

Como pode-se perceber, cada número diferente de zero contém a potência de dois que ocupa a casa (1 é igual a 2, 5 é igual a 2 elevado a 5, que é igual a 32, e assim por diante). Para alinhar corretamente o tabuleiro os números estão impressos em hexadecimal, ou seja, os valores válidos vão de 0 a f (15).

   from PIL import Image
   from PIL import ImageFont
   from PIL import ImageDraw
   from itertools import islice
   
   TilePositions = [
           [32, 216], [153, 216], [274, 216], [395, 216],
           [32, 339], [153, 339], [274, 339], [395, 339],
           [32, 461], [153, 461], [274, 461], [395, 461],
           [32, 584], [153, 584], [274, 584], [395, 584]
     ]
   TileSize = 106
   
   def LoadTemplate():
     img = Image.open('2048.png')
     draw= ImageDraw.Draw(img)
     return img, draw
   
   def DrawBoard(board):
     img, draw = LoadTemplate()
     bigFont = ImageFont.truetype('DejaVuSans-Bold.ttf', 48)
     smallFont = ImageFont.truetype('DejaVuSans-Bold.ttf', 24)
     dbgFont = ImageFont.truetype('DejaVuSans-Bold.ttf', 8)
     for r in range(len(board)):
       for c in range(len(board[r])):
         number = 2 ** board[r][c]
         if number > 1:
           tileX, tileY = TilePositions[r*4 +c][0], TilePositions[r*4 +c][1]
           font = smallFont if number > 64 else bigFont
           text = str(number)
           textW, textH = draw.textsize(text, font=font)
           x, y = tileX + (TileSize - textW) / 2, tileY + (TileSize - textH) /2
           dbgText = str(tileX) + ' + (' + str(TileSize) + ' - ' + str(textW) + ') / 2'
                                   draw.text((x, y), text, (0,0,0), font=font)
     return img
   
   def ReadNextBoard(f):
     lines = [lines for lines in islice(f, 4)]
     if (len(lines)) == 4:
       board = [
         [ int(lines[0][0], 16), int(lines[0][1], 16), int(lines[0][2], 16), int(lines[0][3], 16) ],
         [ int(lines[1][0], 16), int(lines[1][1], 16), int(lines[1][2], 16), int(lines[1][3], 16) ],
         [ int(lines[2][0], 16), int(lines[2][1], 16), int(lines[2][2], 16), int(lines[2][3], 16) ],
         [ int(lines[3][0], 16), int(lines[3][1], 16), int(lines[3][2], 16), int(lines[3][3], 16) ]
         ]
       return board
     return None
   
   def ProcessGame(filePath):
       f = open(filePath)
       board = ReadNextBoard(f)
       boardNumber = 1
       while board:
               DrawBoard(board).save('2048-' + str(boardNumber) + '.png')
               board = ReadNextBoard(f)
               boardNumber = boardNumber + 1

A estratégia do programa de IA é ordenar as casas em um lado e, assim que acumular valores o suficiente, consolidar tudo na última casa. Nem sempre isso é possível, pois uma virada de jogo pode deixar a casa com o maior valor no meio de um dos lados. Nesse caso, é interessante ver como a I.A. se sai, já que com apenas uma execução ela foi até 8192 e mais um 4096. Dá-lhe, computador!


# Abel

Caloni, 2014-04-26 cinema movies [up] [copy]

Abel é um filme-fantasia que se deixa levar pela premissa que o garoto-título resgata a memória do pai ausente como sendo a dele mesmo. Aconteceu algo no passado que não sabemos, possivelmente o não-retorno do pai, que fez com que Abel fosse internado em um hospital e voltasse apenas dois anos depois com a mãe, seu irmão e sua irmã para uma casa em um condomínio abandonado.

A fotografia é belíssima, pois consegue trazer aquele ar pálido, seco e quente, de um futuro sem perspectivas para aquela família. O diretor/ator Diego Luna aparentemente não sabe deixar a câmera quieta, mas quando ela se move, parece querer captar todo aquele caos em uma só tomada, o que é admirável.

No entanto, o filme falha miseravelmente em tentar se aprofundar no drama, ficando apenas em sua superfície do "filho que pensa que é pai". Leva isso até as últimas consequências, é verdade, como a cena da "concepção", mas se o máximo que o roteiro consegue produzir de perigo são dois garotos andando no meio de contêineres e uma taxista e um vigia relapsos, a fábula se quebra facilmente.


# Capitão América 2: O Soldado Invernal

Caloni, 2014-04-27 cinema movies [up] [copy]

Chris Evans, ou Capitão América, seria o personagem mais carismático, mais querido e um líder natural dos Vingadores da Marvel (o que, já sabemos, não se concretiza). Tony Stark (Robert Downey Jr.) lhe tira uma parcela grande de popularidade, mas isso não é culpa dos atores nem dos personagens (originais), mas da nossa era de cinismo e sarcasmo, onde não é o mais bonzinho, o mais patriótico e muito menos o mais correto que irá se sobressair. O politicamente incorreto, ainda que maltratado pela esquerda, continua livre, leve e solto. Curiosamente, tornar esse herói organicamente anacrônico foi uma das poucas virtudes do longa original.

Porém, insistir em um herói carismático e ao mesmo tempo distante em seus pensamentos, um quase blasé, faz de "Capitão América 2: O Soldado Invernal" um filme de ação empolgante, com boas cenas, ótimos efeitos e muito pouco carisma. Os heróis do filme, não apenas um, mas três, ficam quase como um pano de fundo para que a adrenalina faça sua parte. Eles possuem uma ou outra história em seu passado que os unem e os movem contra o "mal". Se é que se pode chamar de mal um inimigo que tenta se tornar ideologicamente uma versão "Gangue do Magneto" (X-Men), mas empalidece tanto quanto as intenções terroristas de Mandarim no igualmente antipático Homem de Ferro 3.

Justiça seja feita ao diretores Anthony e Joe Russo, que respiram esse ar geek nova geração inspirando a velha, e ambos terem dirigido Community pode dizer muito sobre os questionamentos filosóficos de Steve Rogers sobre seu passado, além de um momento WTF em que vemos um dos personagens (nem digo ator) da série em uma brevíssima cena, e, além disso, parece tentar seguir os passos dos filmes antigos da série James Bond (incluindo o "e o Capitão América voltará em..."). A dupla de diretores aqui tenta fazer o que dá, mas um roteiro totalmente engessado escrito igualmente por uma dupla (a que escreveu o segundo Thor) parece querer agradar a todos ao mesmo tempo, fãs e amantes de efeitos visuais na telona, e não conseguem se desvencilhar da previsibilidade tosca que tem acompanhado os projetos da Marvel.

No entanto, mesmo que alguns maniqueísmos previsíveis acabem funcionando até mais do que seria esperado, como a perseguição a Nick Fury, eles têm um claro limite, e realizar a cena da morte de um personagem de maneira tão banal é quase como colocar um aviso luminoso no centro da tela avisando para a possibilidade de talvez tudo aquilo não se concretizar. Sabe como é, não queremos que você chore à toa.

E se o plot twist a respeito do tal Soldado Invernal seja um dos melhores ganchos da história, e algo que só ocorre na terceira parte do filme, ele é subaproveitado. Tanto que há uma cena pós-crédito (não a primeira, a segunda) que parece que não assistiu ao filme.

Bom, eu assisti, mas não lembro de muita coisa. Só que Capitão América estará de volta em Os Diamantes Têm Mais de 100 Anos.


# No Impact Man

Caloni, 2014-04-27 cinema movies [up] [copy]

Esse é daqueles documentários ecológicos que se baseia no escritor Colin Beavan e sua família, a esposa compradora compulsória Michelle Conlin e a pequena e inocente filha. Os três passarão um ano cuidando de suas vidas sem tentar causar qualquer impacto ambiental no meio de Nova York. Primeiramente, devo perguntar: o que seria um impacto ambiental para uma família dessas, e por quê?

Aliás, acho que o filme é que deveria fazer essa pergunta em primeiro lugar, já que ele se deixa levar pelas ambições de Colin e seu senso comum do que seria causar algum dano à natureza, como consumir carne, usar eletricidade e papel higiênico. É um ato de protesto, sem dúvida, mas a questão maior é como esse protesto poderia impactar em nossas decisões do dia-a-dia se não há conhecimento o suficiente para embasá-lo?

É muito fácil para Colin dizer que, para o leigo, a única coisa que ele precisa fazer para se juntar a essa causa é não consumir qualquer produto que ele não conheça seu produtor e/ou seus métodos de produção. Isso torna tudo muito mais romântico do que prático, e o homem que não causa impacto na natureza produz um filme que não causa impacto nenhum na natureza de nosso consumismo compulsivo.

Boa parte da culpa vem das decisões dos diretores Laura Gabbert e Justin Schein, que se entregam ao roteiro escrito por marido e esposa sem questionar qual é a grande história por trás desse maluco que quer voltar a viver como 100 anos atrás. O próprio documentário assume em diversos momentos a insanidade do projeto e talvez do protagonista, o que não ajuda em nada para sua mensagem.

Mesmo assim, em tempos de poluição e de catástrofes anunciadas, qualquer mensagem de esperança, qualquer sinal de como podemos melhorar nosso consumismo desenfreado, sempre será boa notícia. Por isso No Impact Man pode servir de ao menos uma breve reflexão sobre o que estamos fazendo nesse exato momento que pode estar impactando negativamente a nossa breve estadia nesse planeta.


# Que geleia de mocotó

Caloni, 2014-04-29 computer [up] [copy]

A primeira bateria de problemas da segunda fase do Code Jam me mostrou o porquê do seu nome: meu cérebro ficou feito geleia (ha ha ha). Não consegui resolver nenhum problema a tempo, mas não culpo o C++, que passei a usar para essa fase. É burrice aliada a pressão. Duas horas e meia para entender um problema é o tipo de coisa que me deixa pensando mais no tempo do que no problema. Tenho que melhorar isso.

De qualquer forma, esse final de semana que passou foi dedicado a resolver o primeiro problema e quem sabe escrever um post a respeito. Imagino que todos tenham acesso ao enunciado e aos casos de teste, mas, por via das dúvidas, aqui vai uma descrição adaptada:

Você é um fazendeiro hi-tech com uma vaca que tem um tablet. Não especifica se esse cowblet é um iPad, mas é uma possibilidade, já que como nenhum plugue parece encaixar nas tomadas de sua fazenda, é muito provável que você seja um Applemaníaco com um monte de gadgets que precisam de conversor vindos direto do eBay.

Através do eBay também veio um engenheiro chinês cuja missão é resolver esse gato que o Sr. Fazendeiro fez em sua fazenda. Tudo que ele precisa fazer é girar gigantescos switches (ou disjuntores) que invertem a polaridade binária de cada um dos pino dos conectores das tomadas. Quando um plugue de dispositivo e uma tomada possuem a mesma configuração de bits é possível conectá-los. O objetivo final é que todos os N plugues conectem nas N tomadas depois de virados Y switches, sendo que quanto menos switches melhor (afinal, eles são gigantescos, e o chinês supõe-se que seja pequeno).

O primeiro pensamento do programador preguiçoso (go, horse, go!) manda que usemos a velha força bruta e testemos todas as combinações possíveis de disjuntores, peguemos o com menor número de bits setados (inicialmente, todos estão em 0) e zás! Porém, o caso de teste tamanho _large_ pressupõe que o limite de pinos das tomadas pode chegar a 40, o que seria responsável por nada mais nada menos que 2^40 combinações diferentes, ou 1.099.511.627.776 para ser exato. Isso dá mais de 1 trilhão! Mesmo que nosso código seja extremamente rápido e demore apenas um milissegundo para cada combinação, serão mais de 34 anos desperdiçados, que poderiam estar melhor investidos minerando bitcoins.

Dessa forma, temos que traçar uma solução baseada nas combinações entre as tomadas e plugues, que, pelos limites da versão large dos casos de teste, podem ter a quantidade de 150, o que dá 150*150 = 22500 combinações de XOR.

Sim, de XOR. O XOR aqui pode ser usado para detectarmos qual a combinação de switches precisamos para que cada tomada encaixa em cada dispositivo. Esse é o nosso conjunto universo de giros de disjuntores. Com esse conjunto em mãos fica fácil saber quais combinações são possíveis de encaixar todos os dispositivos: basta contar!

#include "CodeJam.h"
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <string>
using namespace std;
static const int MAX_SWITCHES = 40;
__int64 StringToInt(const string& s, int L)
{
    __int64 ret = 0;
    for( int l = L; l; --l )
    {
      char c = s[L-l];
      if( c == '1' )
        ret |= ((__int64)1 << (l-1));
    }
    return ret;
}
int CountBits(__int64 value)
{
    int ret = 0;
    while( value )
    {
      if( value & 1 )
        ++ret;
      value >>= 1;
    }
    return ret;
}
void TestCase(std::istream& is, std::ostream& os)
{
    int N, L;
    is >> N >> L;
    vector<__int64> outlets;
    vector<__int64> devices;
    string eletricItem;
    for( int n = 0; n < N; ++n )
    {
      is >> eletricItem;
      outlets.push_back(StringToInt(eletricItem, L));
    }
    for( int n = 0; n < N; ++n )
    {
      is >> eletricItem;
      devices.push_back(StringToInt(eletricItem, L));
    }
    typedef map<__int64, set<int>> SwitchOcurrences;
    SwitchOcurrences switchOcurrences;
    
    for( int n = 0; n < N; ++n )
    {
      __int64 outlet = outlets[n];
      for( int n2 = 0; n2 < N; ++n2 )
      {
        __int64 device = devices[n2];
        __int64 connection = outlet ^ device;
        switchOcurrences[connection].insert(n);
      }
    }
    for(auto it = switchOcurrences.begin(); it != switchOcurrences.end(); )
    {
      if( it->second.size() != N )
        it = switchOcurrences.erase(it);
      else
        ++it;
    }
    if( switchOcurrences.size() )
    {
      int switches = MAX_SWITCHES + 1;
      for_each(switchOcurrences.begin(), switchOcurrences.end(), [&](const SwitchOcurrences::value_type& ocurrence)
      {
        int bits = CountBits(ocurrence.first);
        switches = min(switches, bits);
      });
      os << switches << endl;
    }
    else os << "NOT POSSIBLE\n";
}

_Observação: note que retirei o wrapper costumeiro dos exercícios do Code Jam para não poluir demais o exemplo com código. E, na verdade, essa parte do código está compartilhada com todas as soluções (reuse!)._

O que aprendi dessa pequena aventura foi: não importa o quanto um problema pareça fácil, anotar em um pedaço de papel é o caminho mais curto entre a mente e o código.

Que venha a segunda bateria de problemas!


[2014-03] [2014-05]