tag:blogger.com,1999:blog-82034444599016091082024-03-05T22:02:15.929-03:00Yo no lo conozco, señor!!Em todos esses anos nessa indústria vital, essa é a primeira vez que isso me acontece!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.comBlogger33125tag:blogger.com,1999:blog-8203444459901609108.post-36285212371723740332013-01-07T21:04:00.001-02:002013-01-07T21:04:31.042-02:00Como passa rápido!Outro ano vai, mais um ano vem... E eu passei 2012 sem escrever nada aqui! Estive enrolado com meu doutorado e até planejei mudar o nome do meu blog, mas não pude priorizar nada disso. Bom, já estamos em 2013 e nada melhor que escrever algo completamente novo!<br />
<br />
Quase todo domingo, preparamos um almoço especial para nós dois. Nesse final de semana, a <a href="http://patydocedesign.blogspot.com/" rel="nofollow">Paty</a> resolveu preparar um risoto cremoso de aspargos para acompanhar um filé mignon em molho de vinho. A combinação não é inteiramente nossa criação: havíamos almoçado isso em um restaurante, no início de dezembro, mas a preparação deixou um pouco a desejar. O prato além de gostoso, ficou bonito; tão bonito que resolvemos postar nas redes sociais que participamos; todo mundo queria saber a receita, só que a Paty não faz nada com medidas. É tudo no "olhômetro" mesmo.<br />
<br />
Para atender todos nossos amigos que pediram, tentei compilar uma receita com a ajuda dela. Recomendo a todos que pretendem fazê-la, que leiam até o final; uma vez começado o risoto, não tem como parar! Deixem todos os ingredientes a mão, picados, medidos e separados. Tudo fica pronto muito rápido!<br />
<br />
Então, vamos em frente!<br />
<br />
Para o risoto (rendeu bastante...):<br />
<br />
4 ou 5 hastes de aspargos frescos<br />
2 xícaras cheias de arroz para risoto (usamos Carnaroli)<br />
1 1/2 xícaras de vinho branco<br />
2 tabletes de caldo de legumes<br />
3 colheres de sopa de manteiga sem sal <br />
1 litro de água<br />
100g de alho-poró<br />
100g de queijo Gruyère ralado<br />
80ml de creme de leite fresco<br />
sal e pimenta-do-reino a gosto<br />
cebolete picada a gosto<br />
<br />
Para a carne (duas pessoas):<br />
<br />
5 escalopes de 150g<br />
manteiga para grelhar<br />
geléia de vinho (Casa da Madeira) <br />
vinagre balsâmico<br />
sal e pimenta-do-reino para temperar<br />
<br />
Preparação do risoto<br />
<br />
Lave os aspargos e corte as pontas que servirão para a decoração; pique os talos em pequenas rodelas, descartando a parte dura do final e reserve. Pique o alho-poró e a cebolete e reserve. Dissolva os dois tabletes de caldo de legumes em um litro de água quente; mantenha esse caldo em fogo baixo, pois será usado durante todo o cozimento do risoto. Em uma panela grande, derreta duas colheres de sopa de manteiga e refogue o alho-poró picado; quando estiver transparente, acrescente as rodelas de aspargos. Refogue mais um pouco e adicione as duas xícaras de arroz, seguidas das uma e meia xícaras de vinho branco. Deixe o álcool evaporar um pouco e acrescente uma concha do caldo de legumes. Adicione um pouco de sal e pimenta-do-reino e duas colheres de creme de leite fresco. A medida que o arroz for cozinhando, ele vai liberar bastante amido, e por isso é necessário mexer constantemente em fogo baixo, acrescentando um concha de caldo de legumes sempre que ele começar a absorver muito líquido.<br />
<br />
Agora é uma questão de sentir o cozimento do arroz; prove de vez em quando para acertar o sal e ver se o arroz já está cozido. Leva uns 15 a 20 minutos, mas nunca deixe de mexer!<br />
<br />
Você deve estar se perguntando: o que faço com as pontas dos aspargos que separei para decorar? Antes de terminar o cozimento, coloque-as por cinco minutos no caldo de legumes que você está usando para preparar o risoto. Tem que acertar o tempo para que elas não fiquem cozidas demais, e nem prontas muito antes do risoto.<br />
<br />
Preparação do escalope:<br />
<br />
Enquanto o marido (ou esposa) mexe o risoto, separe uma frigideira anti-aderente, coloque um pouco de manteiga e frite os bifes previamene temperados, ao seu ponto. Assim que terminar de fritá-los, acrescente na frigideira, em fogo baixo, duas a três colheres de sopa de geléia de vinho Casa da Madeira. Usamos Malbec, mas a Paty acha que Cabernet Sauvignon ficaria mais saborosa. Acrescente uma colher de sobremesa de vinagre balsâmico e deixe reduzir. Quem não achar a geléia, pode preparar uma redução com vinho tinto (1 xícara), açúcar (+/- 1 colher de sopa) e vinagre balsâmico (1 colher de sobremesa).<br />
<br />
Finalização do risoto:<br />
<br />
Assim que o arroz estiver cozido, ele deverá estar úmido e cremoso. Acrescente mais uma colher do creme de leite fresco, uma colher de sopa de manteiga (não muito cheia) e o queijo Gruyère ralado, mexa bem, apague o fogo, coloque a cebolete e sirva imediatamente!<br />
<br />
Decore o prato com as pontas dos aspargos e com o molho do escalope! Sucesso garantido!!<br />
<br />
Acreditem: parece complicado, mas é bem simples de fazer, e não leva meia hora. Ao longo do preparo fique atento ao sal: ao acrescentar o creme de leite e o caldo, o arroz certamente precisará de mais sal. Seja cuidadoso, no entanto, pois não há nada pior que risoto salgado!<br />
<br />
Bon Appétit!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-90269932465954658302011-12-14T14:46:00.000-02:002011-12-24T10:04:22.711-02:00Energia e matériaCientistas do CERN envolvidos nos projetos Atlas e CMS informaram ao mundo que restringiram a faixa onde o boson de Higgs pode estar se escondendo. Esta é a dita "partícula de Deus". Pouca gente sabe, mas a origem deste apelido vem de um livro que se chamaria "The goddamned particle", mas os editores não deixaram o autor usar este nome. Ele então mudou para "The God's Particle", e a moda pegou...<br />
<br />
O bóson de Higgs parece estar "escondido" em uma faixa de 115 a 127GeV.
Toda vez que vemos o prefixo giga-, pensamos em algo grande, gigante,
mas um gigaelétron-volt (GeV) corresponde a uma energia de dois
centésimos de milésimos de joule, quase cinco bilionésimos de caloria!
Não dá nem para esquentar uma gota de água! Na verdade, a quantidade de energia é imensa quando pensamos na massa
estimada destas partículas. Por serem pouco massivas, para as levarmos a
velocidades próximas a da luz precisamos de muito pouca energia, mas a
eficiência nesta transferência de energia é muito baixa e acabamos
precisando de uma verdadeira usina de força para atingir os objetivos.
No caso do LHC, são quase 50MW, entre acelerador e resfriamento
(criogenia). É um décimo do que se produz, por exemplo em Angra 1, mas
o suficiente para alimentar, digamos, Petrópolis! <br />
<br />
Com essa onda toda, os publicitários de araque estão fazendo a festa. Hoje passando em uma banca de jornal no Largo da Carioca, vi uma propaganda que dizia: "Curso (...), um salto quântico no ensino de inglês". Imediatamente pensei: "Claro! Uma energia imensa para um deslocamento infinitesimal". Como diz um colega meu, o publicitário é um cara pago para mentir, e que ganha prêmio para isso!!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-16027844597191714622011-07-28T08:50:00.005-03:002011-08-23T20:25:17.151-03:00Não morri...Pois é...Percebi hoje que faz 6 meses desde a minha última postagem. Não foi por falta de tempo, pelo menos não apenas. <br />
<br />
Passei os últimos seis meses procrastinando a escrita dos artigos sobre eletrônica que prometi em meu último post, simplesmente por falta de paciência de fazer as figurinhas. Já defini que antes de escrever sobre diodos e transistores, escreverei sobre os teoremas menos conhecidos da eletrônica (superposição, Thevènin, Norton e Tellegen), até por que isso reduzirá consideravelmente as ditas "figurinhas". Eu ia escrever um pouco sobre capacitores e indutores, mas acho que vou falar deles quando for oportuno, pois o divertido na eletrônica são os semicondutores. <br />
<br />
Nesses seis meses, acabei reacendendo um hobby meio abandonado: a fotografia. Sempre gostei desse hobby, mas desde a explosão das câmeras digitais não brincava com isso. O motivo: as cameras DSLR eram muito caras, e o que eu conseguia fazer com a minha Sony DSC-P51 e minha Casio Z-120 era muito limitado. <br />
<br />
Esse ano, nas minhas férias, finalmente comprei minha DSLR, uma <a href="http://www.nikonusa.com/Nikon-Products/Product/Digital-SLR-Cameras/25472/D3100.html">Nikon D3100 </a>como essa:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://www.kenrockwell.com/nikon/d3100/D3S_8285-0600.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img height="312" src="http://www.kenrockwell.com/nikon/d3100/D3S_8285-0600.jpg" width="400" /></a></div><br />
<span style="font-size: xx-small;">(foto de <a href="http://www.kenrockwell.com/nikon/d3100.htm">Ken Rockwell</a>)</span><br />
<br />
O kit foi completo. Além do corpo da câmera, com uma lente 18-55mm, comprei uma 55-200mm e um flash Nikon SB400. Além disso, comprei alguns livros, para melhorar o nível de minhas fotos, e para ajudar a Paty a <a href="http://patydocedesign.blogspot.com/">publicar suas pequenas criações</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjebPDwqef2KXII1KZQbqETw14w1kx8zyRCIbh0TkFXZWLG58_uxh2h_ldUGVruQ7msF1WRtbLoabNYwnH08FEHZZATX8SiVLdtSK7MqrFAAkyJBXC6Hmr8-6OVY3Wnlt6l12P5gpKdZXM/s1600/livros.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjebPDwqef2KXII1KZQbqETw14w1kx8zyRCIbh0TkFXZWLG58_uxh2h_ldUGVruQ7msF1WRtbLoabNYwnH08FEHZZATX8SiVLdtSK7MqrFAAkyJBXC6Hmr8-6OVY3Wnlt6l12P5gpKdZXM/s400/livros.jpg" width="400" /></a></div><br />
<br />
Bom, quem quiser ver algumas fotos, estou as colocando na lista do meu <a href="http://www.flickr.com/photos/rafaelpinto/">Flickr</a>. Vou tentar postar alguma coisa no Blog antes de dezembro, para não deixar mais ninguém orfão!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-16030036079119837112010-12-20T22:13:00.001-02:002010-12-20T22:14:35.276-02:00Principiantes na eletrônicaUm tempo atrás um colega contou que estava tentado a brincar com microcontroladores PIC, mas que nunca se aventurou muito por não conhecer grandes coisas sobre eletrônica. Uns dias atrás, eu estava expressando minhas opiniões sobre o Arduino (vide post anterior!), e esse mesmo colega me falou que estava tentado a testar um, pois seria uma forma de brincar com microcontroladores, sem ter que se "iniciar" na eletrônica.<br />
<br />
De certa forma, acho que ele tem razão, pois o Arduino oferece tudo que um iniciante precisa para fazer algo mais interessante que medir a corrente em um resistor (acreditem, isso é chato pra caramba). Seguindo a conversa, falei para ele: "...o chato é que não dá para fazer muito mais que piscar um LED". A conversa então enveredou para as pequenas experiências que ele já havia feito, e eu perguntei: "você já acendeu um LED, mas já usou um transistor para isso?". A resposta foi negativa, e me senti compelido a ensiná-lo, como uma dívida para mim mesmo...<br />
<br />
Eu e <a href="http://hardypinto.blogspot.com/">meu irmão</a> começamos cedo na eletrônica, quando compramos uma revista atrativamente chamada "Bê-a-bá da Eletrônica", aos 9 anos de idade! A revista não cumpria propriamente o que prometia no título, mas tinha circuitos relativamente simples, fáceis de executar, e que, até certo ponto, funcionavam! Todos os exemplares traziam uma parte teórica, mas essa teoria era simplificada demais para atingir pessoas absolutamente iniciantes.<br />
<br />
Na verdade, mais tarde (há 22 anos!), na Escola Técnica Federal de Pernambuco, na primeira disciplina de Eletrônica,fomos apresentados a física dos semicondutores, o que deveria seria capaz de nos explicar o funcionamento mágico desses componentes. Infelizmente, ainda não foi dessa vez... A frustração foi até o quinto período da Escola de Engenharia (agora Escola Politécnica) da Universidade Federal do Rio de Janeiro, em 1992, onde finalmente o que faltava apareceu: a ligação da física dos semicondutores com a teoria eletrostática, acrescida à geometria destes componentes explica todos a mágica da eletrônica. O que é mais incrível (e chocante) veio logo em seguida: quase nunca precisamos nos preocupar com esses "detalhes". Os circuitos eletrônicos funcionam em pequenas faixas, conhecidas como ponto de operação, onde podemos considerar que todo o sistema opera segundo as regras da linearidade.<br />
<br />
Muita gente não acredita, mas a eletrônica, na grande maioria das vezes, se resume nas quatro operações básicas, acrescida de um pouco de experiência, bom-senso, e simulação; e isso é o que não se aprende em escola nenhuma!<br />
<br />
Para repassar um pouco desse conhecimento e um pouco da minha experiência, vou tentar postar alguns artigos sobre eletrônica e seus fundamentos. Vou fazer em <i>double-post</i>, aqui e em um <i>wiki</i>, para que possa servir como referência para outros colegas <i>hobbyistas</i>, como eu comecei, ainda sou e sempre serei!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com1tag:blogger.com,1999:blog-8203444459901609108.post-82536725920390578422010-12-15T20:08:00.018-02:002010-12-16T08:28:04.720-02:00Por que o Arduino não é essas coisas todasUm conhecido de <span style="font-style: italic;">twitter</span>, o @technoberto, apontou <a href="http://techberto.wordpress.com/2010/08/25/leptoniando-toda-computacao-e-sempre-fisica-2/">um artigo no blog Leptoniando </a>criticando a subcultura Arduino e da "computação física". Resumindo o artigo, a "computação física" não passa da mesma tecnologia embarcada da década de 1960, utilizando um microcontrolador da família AVR, que existe desde 1996.<br /><br />Para quem não conhece, o Arduino, sucessor do <span style="font-style: italic;">Wiring</span>, é uma placa mãe que contém o microcontrolador, o circuito de <span style="font-style: italic;">clock</span>, um botão de reset e uma interface USB (que na verdade é uma RS232C). Essa placa foi desenhada como controlador de baixo custo para a automação de pequenas "obras de arte" ou para permitir o sensoreamento do mundo físico com nossos computadores de uma forma simples.<br /><br />Para quem não se lembra, houve uma época que um computador pessoal não era muito diferente de um microcontrolador atual. Veja bem: um ZX80, de 1981, tinha 4KB de ROM e 1KB de RAM; seu processador, o Z80A, era de uma arquitetura <span style="font-style: italic;">CISC</span>, cujas instruções podiam ocupar até quatro bytes; seu clock de 3.25MHz era calculado para que a geração de uma linha vídeo coincidisse com um número certo de instruções. Um microcontrolador PIC16F ou AVR facilmente supera estas especificações: podem ter até 64KB de ROM em <span style="font-style: italic;">flash </span>para instruções, cada instrução ocupa especificamente 2 bytes (nestas arquiteturas) e podem ter até 8KB de RAM, executando programas em <span style="font-style: italic;">clocks </span>de até 20MHz. É bem verdade que podíamos colocar programas em linguagem de máquina diretamente na RAM de um ZX80, mas a memória <span style="font-style: italic;">flash</span> compensa isto, permitindo que tudo seja reprogramado rapidamente. Outra vantagem é o tamanho: em um DIP de 28 pinos, temos tudo (e mais) que um computador que pesava quase um quilo! Além da RAM e ROM, um microcontrolador também inclui diversos periféricos, como geradores de sinal PWM, conversores A/D e interfaces de comuicação em série, além de I/O direto pino a pino!<br /><br />Uma das atrações destes computadores de 8 bits da década de 1980 era a facilidade que podia-se construir uma placa de expansão, para, por exemplo, controlar um sistema de alarme doméstico. Os manuais traziam diagramas detalhados de todas as portas de I/O, incluindo, às vezes, diagramas de tempo das memórias e das portas.<br /><br />O leitor deve então estar imaginando que eu sou daqueles que não sente saudades dos velhos micros de 8 bits, que tenho Java correndo nas veias, e que nem quero saber de sistemas de baixo nível. Não é nada disso. O que me incomoda é ver um bando de gente vendo o Arduino, e imaginando que é algo revolucionário; mais grave ainda é alguém imaginar que pode automatizar uma grande indústria com um sistema destes. Para um Arduino servir industrialmente, deve ser imune a ruído e intrinsecamente robusto (dois processadores em <span style="font-style: italic;">fail-over</span> é o mínimo).<br /><br />O Arduino é um "brinquedo", no máximo uma ferramenta educativa; e mesmo nestas funções, é apenas mediano. A base em que a plataforma se apoia é sua principal fraqueza. Primeiramente, o Arduino, para dispensar ferramentas de programação específicas, se vale de um <span style="font-style: italic;">bootloader</span> que ocupa 2KB da memória. Hoje, com 32KB de flash, isto já não representa uma fraqueza tão grande, mas até a última versão o processador tinha apenas 8KB. Ou seja: um quarto da memória era apenas usada para carregar o programa na memória! O <span style="font-style: italic;">bootloader </span> também afeta a latência da interrupção, pois, em controladores tão simples como os AVR, é necessário identificar qual programa estamos executando e fazer um <span style="font-style: italic;">jump</span> para o tratamento correto. A segunda fraqueza diz respeito a linguagem <span style="font-style: italic;">Wiring</span> usada. Levei um tempo para sacar, mas essa linguagem é essencialmente o C! O Arduino utiliza o GCC-AVR com uma <span style="font-style: italic;">libc</span> simplificada e com rotinas especializadas para acessar os periféricos embutidos do microcontrolador. O problema: quando ligamos a rotina principal à biblioteca, o <span style="font-style: italic;">loader</span> do GCC não separa o código não utilizado, e a memória efetivamente disponível para programas ainda é menor. A terceira, e última fraqueza também tem a ver com o <span style="font-style: italic;">Wiring</span>: como não podemos editar o <span style="font-style: italic;">assembly</span> diretamente, não podemos tratar as interrupções. O Arduino resolve isso com variáveis globais que são preenchidas em uma rotina de tratamento da interrupção na biblioteca do <span style="font-style: italic;">Wiring</span>. O código então tem que fazer <span style="font-style: italic;">polling</span> nessas variáveis para poder obter os valores dos sensores conectados aos seus pinos de I/O. <span style="font-style: italic;">Hard real-time</span> se torna impossível.<br /><br />Não posso encerrar só com críticas: o sucesso do Arduino é sua arquitetura de <span style="font-style: italic;">hardware</span>. Os conectores posicionados de uma forma padronizada facilitaram a construção de inúmeras placas de expansão (os <span style="font-style: italic;">shields</span>) que simplificam o acesso da plataforma a pessoas com apenas um mínimo de conhecimento de eletrônica. O uso do C também é um ponto alto, apesar das limitações que citei; ele permite que o usuário não sofra com uma programação em baixo nível, mesmo sacrificando algumas capacidades do processador.<br /><br />Fiz este <span style="font-style: italic;">post</span>, pois não aguento ouvir coisas do tipo "Cara, você fala isso por que nunca viu um!" toda vez que digo que não acho que o Arduino seja grande coisa. Explicar tudo isso em uma conversa rápida é impossível. De agora em diante, posso passá-lo<span style="font-style: italic;"></span> para quem quiser saber meus motivos!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com1tag:blogger.com,1999:blog-8203444459901609108.post-45061418792238194532010-02-11T08:37:00.006-02:002010-02-11T19:37:07.336-02:00Se não puder convencê-los, confunda-os!<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8u3F6CB-uZ_afCjWRsyQ4rK3v0DJdDswWiEoNqn4tae7o00SQ7PIw36uVtkphHhZczM001NOxrvVr2LvJEFAkiHoRZM5bZ414zaW_yuJKD5mcRNYGy-iwwuAjCtAPd4YVg9go7_0D7vg/s1600-h/Detalhe_trafo.JPG"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 181px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8u3F6CB-uZ_afCjWRsyQ4rK3v0DJdDswWiEoNqn4tae7o00SQ7PIw36uVtkphHhZczM001NOxrvVr2LvJEFAkiHoRZM5bZ414zaW_yuJKD5mcRNYGy-iwwuAjCtAPd4YVg9go7_0D7vg/s320/Detalhe_trafo.JPG" alt="" id="BLOGGER_PHOTO_ID_5436934601275046370" border="0" /></a><br /><br />Uma das melhores formas de esconder problemas é generalizar, e, neste ponto, a Light S.A. tem se mostrado especialista.<br /><br />Ao declarar que as quedas constantes de luz em diversos bairros do Rio de Janeiro são devidas apenas ao excesso de consumo ela generaliza, e esconde problemas de planejamento de médio prazo e na manutenção de equipamentos.<br /><br />O problema causado por falta de manutenção pode ser facilmente visto na rua Carlos Vasconcelos, na Tijuca, entre as esquinas das ruas dos Araújos e Moura Brito. Neste local, um reparo mal-feito (mostrado na foto) encontra-se prestes a causar um novo curto-circuito na rede.<br /><br />Na noite do dia 18 para 19 de janeiro, uma forte chuva atingiu o Rio de Janeiro. Logo após a chuva, o suporte de um dos cabos do transformador que alimenta este quarteirão se rompeu, fazendo com que este cabo caísse sobre os outros provocando um curto-circuito. A equipe de emergência foi acionada e, por volta de 2:00 do dia 19, a Light começou o serviço de reparos, que terminou as 7:00.<br /><br />O reparo, no entanto, não substituiu o suporte dos cabos, e, na madrugada do dia 4 de fevereiro, as emendas feitas cederam e o cabo caiu por sobre os outros, provocando novamente um forte curto-circuito.<br /><br />A equipe de emergência foi novamente acionada, chegando ao local por volta de 3:00. Às 4:00, tendo considerado o reparo feito, o técnico religou o fusível, mas como o cabo ainda se encontrava em contato com os cabos abaixo, houve novamente um grande curto. O reparo reiniciou, terminando por volta de 6:00.<br /><br />Ainda no dia 4 de fevereiro, por volta de 15:00, o reparo cedeu, e mais um curto-circuito pode ser ouvido nas ruas do bairro. Uma equipe de manutenção com dois carros e três técnicos chegou as 18:00, terminando o reparo por volta de 20:30.<br /><br />Na noite do dia 5, ocorreu um novo curto-circuito. A emergência foi acionada as 23:50, mas só chegou ao local por volta de 8:15 da manhã do dia 6.<br /><br />Enquanto aguardava a equipe, uma boa parte dos moradores da região (inclusive este que vos escreve) notou algo errado no conserto: o cabo estava sendo sustentado por uma corda, amarrada no transformador do poste.<br /><br />Ao questionar sobre o motivo do cabo ser sustentado por uma corda e não por isoladores, fui informado, primeiramente, que "não era da minha conta", e depois, ao me identificar como engenheiro eletrônico, que se tratava de um reparo de emergência, e que seria colocado no relatório para que uma equipe de manutenção corrigisse o problema.<br /><br />Hoje, 11 de fevereiro de 2010, o cabo continua lá, sustentado por um pedaço de corda de algodão que cede um pouco todo dia, em uma contagem regressiva para um novo curto-circuito.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMT-w9dh2IScP7NUJKKlWgBb8GrsrYPAkR_YDDB2ZVj_8sAJMJB63FjVJAx3MaCJTDA9o0Qc5O7oYwAhqok_YOiSrn_lM5e30Q9Ata1JrBP3-sgl84FUv-QdfHP9tvsC22tYqMySvGRV8/s1600-h/trafo6_2.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 92px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMT-w9dh2IScP7NUJKKlWgBb8GrsrYPAkR_YDDB2ZVj_8sAJMJB63FjVJAx3MaCJTDA9o0Qc5O7oYwAhqok_YOiSrn_lM5e30Q9Ata1JrBP3-sgl84FUv-QdfHP9tvsC22tYqMySvGRV8/s320/trafo6_2.jpg" alt="" id="BLOGGER_PHOTO_ID_5436933583689011842" border="0" /></a><br /><br /><span style="font-weight: bold;">UPDATE</span> (11/2, 19:34): A corda cedeu totalmente, e agora o cabo encontra-se praticamente encostado no outro. Prevejo mais uma noite de calor, assando no forno que é o verão do Rio de Janeiro sem ar-condicionado! Amanhã tiro fotos e coloco aqui!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-80245618327952262882009-11-17T10:44:00.001-02:002009-11-17T19:44:23.205-02:00Camel case stripperEstava conversando com o Chico e ele me falou da implementação do <i><a href="http://chicoary.wordpress.com/2009/11/01/camel-case-stripper/">camel case stripper</a></i> que ele fez em Smalltalk.<br /><br />Enquanto ele me explicava o algoritmo, pensei em como seria simples uma versão funcional e acabei escrevendo este código.<br /><br /><pre><br /><span class="hs-definition">isUpper</span> <span class="hs-keyglyph">=</span> <span class="hs-layout">(</span><span class="hs-varid">flip</span> <span class="hs-varid">elem</span><span class="hs-layout">)</span> <span class="hs-keyglyph">[</span><span class="hs-chr">'A'</span><span class="hs-keyglyph">..</span><span class="hs-chr">'Z'</span><span class="hs-keyglyph">]</span><br /><br /><span class="hs-definition">stripCamel</span> <span class="hs-layout">(</span><span class="hs-varid">x</span><span class="hs-conop">:</span><span class="hs-varid">xs</span><span class="hs-layout">)</span><span class="hs-keyglyph">=</span> <span class="hs-varid">stripCamel'</span> <span class="hs-varid">xs</span> <span class="hs-keyglyph">[</span><span class="hs-varid">x</span><span class="hs-keyglyph">]</span> <span class="hs-conid">[]</span><br /><br /><span class="hs-definition">stripCamel'</span> <span class="hs-conid">[]</span> <span class="hs-conid">[]</span> <span class="hs-varid">b</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">reverse</span> <span class="hs-varid">b</span><br /><span class="hs-definition">stripCamel'</span> <span class="hs-conid">[]</span> <span class="hs-varid">a</span><span class="hs-keyglyph">@</span><span class="hs-layout">(</span><span class="hs-varid">x</span><span class="hs-conop">:</span><span class="hs-varid">xs</span><span class="hs-layout">)</span> <span class="hs-varid">b</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">stripCamel'</span> <span class="hs-conid">[]</span> <span class="hs-conid">[]</span> <span class="hs-layout">(</span><span class="hs-layout">(</span><span class="hs-varid">reverse</span> <span class="hs-varid">a</span><span class="hs-layout">)</span><span class="hs-conop">:</span><span class="hs-varid">b</span><span class="hs-layout">)</span><br /><span class="hs-definition">stripCamel'</span> <span class="hs-layout">(</span><span class="hs-varid">x</span><span class="hs-conop">:</span><span class="hs-varid">xs</span><span class="hs-layout">)</span> <span class="hs-varid">a</span> <span class="hs-varid">b</span> <span class="hs-keyglyph">|</span> <span class="hs-varid">isUpper</span> <span class="hs-varid">x</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">stripCamel'</span> <span class="hs-varid">xs</span> <span class="hs-keyglyph">[</span><span class="hs-varid">x</span><span class="hs-keyglyph">]</span> <span class="hs-layout">(</span><span class="hs-layout">(</span><span class="hs-varid">reverse</span> <span class="hs-varid">a</span><span class="hs-layout">)</span><span class="hs-conop">:</span><span class="hs-varid">b</span><span class="hs-layout">)</span> <br /> <span class="hs-keyglyph">|</span> <span class="hs-varid">otherwise</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">stripCamel'</span> <span class="hs-varid">xs</span> <span class="hs-layout">(</span><span class="hs-varid">x</span><span class="hs-conop">:</span><span class="hs-varid">a</span><span class="hs-layout">)</span> <span class="hs-varid">b</span><br /></pre><br /><br />Sei lá... Parece mais simples! :-)Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com1tag:blogger.com,1999:blog-8203444459901609108.post-29537219191605719752009-11-10T13:09:00.004-02:002009-11-10T13:16:22.255-02:00IFCP 2009 - O finalDesculpe desapontá-los, mas abandonei o projeto de terminar o problema do ICFP2009 antes do final do ano. Na verdade, fiquei um pouco aborrecido pois queria ter implementado um visualizador das órbitas, e não estou com tempo de aprender OpenGL.<br /><br />Coloco aqui a última versão do código de transferência entre órbitas. O algoritmo é bastante simples: uma outra mônada RWS que envolve o IO, apenas para escrever a saída na tela. Ainda não critico o final da execução e nem escrevo o arquivo de saída no formato do problema, mas dá para se divertir vendo a distância entre o satélite e a órbita destino diminuindo!! Aproveitem!<br /><br /><br /><pre><span class='hs-keyword'>module</span> <span class='hs-conid'>Main</span> <span class='hs-keyword'>where</span><br /><br /><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span> <br /><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Environment</span><br /><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>RWS</span><br /><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Lazy</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>BL</span><br /><span class='hs-keyword'>import</span> <span class='hs-conid'>OBFFile</span><br /><span class='hs-keyword'>import</span> <span class='hs-conid'>Vector</span><br /><span class='hs-keyword'>import</span> <span class='hs-conid'>OBFProgram</span><br /><span class='hs-keyword'>import</span> <span class='hs-conid'>OBFData</span><br /><span class='hs-keyword'>import</span> <span class='hs-conid'>OVM</span><br /><br /><span class='hs-comment'>-- Read Write State </span><br /><span class='hs-comment'>-- Program Time,Input Time,VMInput,Memory</span><br /><span class='hs-keyword'>type</span> <span class='hs-conid'>SimVM</span> <span class='hs-varid'>a</span><span class='hs-keyglyph'>=</span><span class='hs-conid'>RWST</span> <span class='hs-layout'>(</span><span class='hs-conid'>OVM</span><span class='hs-conid'>()</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>Integer</span><span class='hs-layout'>,</span><span class='hs-conid'>OBFData</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span> <span class='hs-layout'>(</span><span class='hs-conid'>Integer</span><span class='hs-layout'>,</span><span class='hs-conid'>OBFData</span><span class='hs-layout'>,</span><span class='hs-conid'>OBFData</span><span class='hs-layout'>)</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span><br /><br /><br /><span class='hs-definition'>main</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><br /><span class='hs-definition'>main</span><span class='hs-keyglyph'>=</span><span class='hs-keyword'>do</span> <br /> <span class='hs-layout'>(</span><span class='hs-varid'>fn</span><span class='hs-conop'>:</span><span class='hs-varid'>scene</span><span class='hs-conop'>:</span><span class='hs-varid'>args</span><span class='hs-layout'>)</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>getArgs</span><br /> <span class='hs-varid'>withBinaryFile</span> <span class='hs-varid'>fn</span> <span class='hs-conid'>ReadMode</span> <span class='hs-layout'>(</span><span class='hs-varid'>readAndRun</span> <span class='hs-layout'>(</span><span class='hs-varid'>read</span> <span class='hs-varid'>scene</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><br /> <br /><br /><span class='hs-definition'>readAndRun</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>Double</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>Handle</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><br /><span class='hs-definition'>readAndRun</span> <span class='hs-varid'>s</span> <span class='hs-varid'>h</span><span class='hs-keyglyph'>=</span><br /> <span class='hs-keyword'>do</span><br /> <span class='hs-layout'>(</span><span class='hs-varid'>p</span><span class='hs-layout'>,</span><span class='hs-varid'>d</span><span class='hs-layout'>)</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>readOBFFile</span> <span class='hs-varid'>h</span><br /> <span class='hs-keyword'>let</span> <span class='hs-varid'>i</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>singleton</span> <span class='hs-num'>0x3e80</span> <span class='hs-varid'>s</span><br /> <span class='hs-varid'>dum</span><span class='hs-keyglyph'><-</span><span class='hs-keyword'>case</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span><br /> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>s</span><span class='hs-varop'>>=</span><span class='hs-num'>1000</span> <span class='hs-varop'>&&</span> <span class='hs-varid'>s</span><span class='hs-varop'><</span><span class='hs-num'>2000</span> <span class='hs-keyglyph'>-></span><span class='hs-varid'>print</span> <span class='hs-str'>"Hohmann"</span><br /> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>s</span><span class='hs-varop'>>=</span><span class='hs-num'>2000</span> <span class='hs-varop'>&&</span> <span class='hs-varid'>s</span><span class='hs-varop'><</span><span class='hs-num'>3000</span> <span class='hs-keyglyph'>-></span><span class='hs-varid'>print</span> <span class='hs-str'>"Meet and Greet"</span><br /> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>s</span><span class='hs-varop'>>=</span><span class='hs-num'>3000</span> <span class='hs-varop'>&&</span> <span class='hs-varid'>s</span><span class='hs-varop'><</span><span class='hs-num'>4000</span> <span class='hs-keyglyph'>-></span><span class='hs-varid'>print</span> <span class='hs-str'>"Eccentric Meet and Greet"</span><br /> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>s</span><span class='hs-varop'>>=</span><span class='hs-num'>4000</span> <span class='hs-varop'>&&</span> <span class='hs-varid'>s</span><span class='hs-varop'><</span><span class='hs-num'>5000</span> <span class='hs-keyglyph'>-></span><span class='hs-varid'>print</span> <span class='hs-str'>"Operation Clear Skies"</span><br /> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>s</span><span class='hs-varop'>>=</span><span class='hs-num'>5000</span> <span class='hs-varop'>&&</span> <span class='hs-varid'>s</span><span class='hs-varop'><</span><span class='hs-num'>6000</span> <span class='hs-keyglyph'>-></span><span class='hs-varid'>print</span> <span class='hs-str'>"Operation Dance with Stars"</span><br /> <span class='hs-varid'>ret</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>execSim</span> <span class='hs-varid'>hohmannSim</span> <span class='hs-varid'>p</span> <span class='hs-varid'>i</span> <span class='hs-varid'>d</span><br /> <span class='hs-varid'>print</span> <span class='hs-varid'>ret</span><br /><br /><span class='hs-definition'>execSim</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>SimVM</span><span class='hs-conid'>()</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>OVM</span><span class='hs-conid'>()</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>OBFData</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>OBFData</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>IO</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>Integer</span><span class='hs-layout'>,</span><span class='hs-conid'>OBFData</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span><br /><span class='hs-definition'>execSim</span> <span class='hs-varid'>s</span> <span class='hs-varid'>p</span> <span class='hs-varid'>i</span> <span class='hs-varid'>d</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>liftM</span> <span class='hs-varid'>snd</span> <span class='hs-varop'>$</span> <span class='hs-varid'>execRWST</span> <span class='hs-varid'>s</span> <span class='hs-varid'>p</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span><span class='hs-layout'>,</span><span class='hs-varid'>i</span><span class='hs-layout'>,</span><span class='hs-varid'>d</span><span class='hs-layout'>)</span><br /><br /><span class='hs-definition'>hohmannSim</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>SimVM</span> <span class='hs-conid'>()</span><br /><span class='hs-definition'>hohmannSim</span><span class='hs-keyglyph'>=</span> <br /> <span class='hs-keyword'>do</span> <br /> <span class='hs-varid'>i</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>gets</span> <span class='hs-layout'>(</span><span class='hs-varid'>input</span><span class='hs-layout'>)</span><br /> <span class='hs-layout'>(</span><span class='hs-varid'>co</span> <span class='hs-layout'>,</span><span class='hs-varid'>v</span><span class='hs-layout'>,</span> <span class='hs-varid'>tgt</span> <span class='hs-layout'>)</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>getPositionSpeedTarget</span><br /> <span class='hs-keyword'>let</span> <span class='hs-layout'>(</span><span class='hs-varid'>dv1</span><span class='hs-layout'>,</span><span class='hs-varid'>dv2</span><span class='hs-layout'>,</span><span class='hs-varid'>tof_d</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>calcHohmann</span> <span class='hs-varid'>co</span> <span class='hs-varid'>tgt</span><br /> <span class='hs-keyword'>let</span> <span class='hs-varid'>tof</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>floor</span> <span class='hs-varid'>tof_d</span> <span class='hs-keyglyph'>::</span><span class='hs-conid'>Int</span><br /> <br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"targetOrbit="</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>tgt</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>tgt</span><span class='hs-varop'>></span><span class='hs-varid'>co</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"currentSpeed="</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>v</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"dV1="</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>dv1</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"dV2="</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>dv2</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"tof_d="</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>tof_d</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"tof="</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>tof</span><span class='hs-layout'>)</span><br /> <span class='hs-keyword'>let</span> <span class='hs-layout'>(</span><span class='hs-varid'>dx1</span><span class='hs-layout'>,</span><span class='hs-varid'>dy1</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>colinearVector</span> <span class='hs-varid'>dv1</span> <span class='hs-varid'>v</span> <br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"deltaVector="</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>dx1</span><span class='hs-layout'>,</span><span class='hs-varid'>dy1</span><span class='hs-layout'>)</span><br /> <span class='hs-keyword'>let</span> <span class='hs-varid'>i'</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>i</span> <span class='hs-varop'>`union`</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromList</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-num'>2</span><span class='hs-layout'>,</span><span class='hs-varid'>dx1</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-layout'>(</span><span class='hs-num'>3</span><span class='hs-layout'>,</span><span class='hs-varid'>dy1</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>applyInput</span> <span class='hs-varid'>i'</span><br /> <span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>)</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>stepOVM</span><br /> <span class='hs-varid'>applyInput</span> <span class='hs-varid'>i</span><br /> <span class='hs-varid'>replicateM_</span> <span class='hs-layout'>(</span><span class='hs-varid'>tof</span><span class='hs-comment'>-</span><span class='hs-num'>4</span><span class='hs-layout'>)</span> <span class='hs-varid'>stepOVM</span><br /> <span class='hs-layout'>(</span><span class='hs-varid'>co</span> <span class='hs-layout'>,</span><span class='hs-varid'>v</span><span class='hs-layout'>,</span> <span class='hs-varid'>tgt</span> <span class='hs-layout'>)</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>getPositionSpeedTarget</span><br /> <span class='hs-keyword'>let</span> <span class='hs-layout'>(</span><span class='hs-varid'>dx2</span><span class='hs-layout'>,</span><span class='hs-varid'>dy2</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>colinearVector</span> <span class='hs-varid'>dv2</span> <span class='hs-varid'>v</span><br /> <span class='hs-keyword'>let</span> <span class='hs-varid'>i'</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>i</span> <span class='hs-varop'>`union`</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromList</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-num'>2</span><span class='hs-layout'>,</span><span class='hs-varid'>dx2</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-layout'>(</span><span class='hs-num'>3</span><span class='hs-layout'>,</span><span class='hs-varid'>dy2</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>applyInput</span> <span class='hs-varid'>i'</span><br /> <span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>)</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>stepOVM</span><br /> <span class='hs-varid'>applyInput</span> <span class='hs-varid'>i</span><br /> <span class='hs-varid'>replicateM_</span> <span class='hs-layout'>(</span><span class='hs-num'>1000</span><span class='hs-layout'>)</span> <span class='hs-varid'>stepOVM</span><br /> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span><br /> <span class='hs-keyword'>where</span><br /> <span class='hs-varid'>input</span> <span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-layout'>,</span><span class='hs-varid'>i</span><span class='hs-layout'>,</span><span class='hs-varid'>d</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>i</span><br /> <span class='hs-varid'>time</span> <span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-layout'>,</span><span class='hs-varid'>i</span><span class='hs-layout'>,</span><span class='hs-varid'>d</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>t</span><br /> <span class='hs-varid'>memory</span><span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-layout'>,</span><span class='hs-varid'>i</span><span class='hs-layout'>,</span><span class='hs-varid'>d</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>d</span><br /><br /> <br /><span class='hs-definition'>getPositionSpeedTarget</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>SimVM</span> <span class='hs-layout'>(</span><span class='hs-conid'>Double</span><span class='hs-layout'>,</span> <span class='hs-conid'>Vector</span> <span class='hs-conid'>Double</span><span class='hs-layout'>,</span><span class='hs-conid'>Double</span><span class='hs-layout'>)</span><br /><span class='hs-definition'>getPositionSpeedTarget</span><span class='hs-keyglyph'>=</span><span class='hs-keyword'>do</span><br /> <span class='hs-layout'>(</span><span class='hs-varid'>t</span> <span class='hs-layout'>,</span><span class='hs-varid'>o</span> <span class='hs-layout'>)</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>stepOVM</span><br /> <span class='hs-layout'>(</span><span class='hs-varid'>t</span> <span class='hs-layout'>,</span><span class='hs-varid'>o'</span><span class='hs-layout'>)</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>stepOVM</span><br /> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>currOrbit</span> <span class='hs-varid'>o'</span><span class='hs-layout'>,</span> <span class='hs-varid'>currSpeed</span> <span class='hs-varid'>o</span> <span class='hs-varid'>o'</span><span class='hs-layout'>,</span> <span class='hs-varid'>o'</span><span class='hs-varop'>!-!</span><span class='hs-num'>4</span><span class='hs-layout'>)</span><br /><br /><br /><span class='hs-definition'>stepOVM</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>SimVM</span> <span class='hs-layout'>(</span><span class='hs-conid'>Integer</span><span class='hs-layout'>,</span><span class='hs-conid'>OBFData</span><span class='hs-layout'>)</span><br /><span class='hs-definition'>stepOVM</span><span class='hs-keyglyph'>=</span><span class='hs-keyword'>do</span><br /> <span class='hs-varid'>p</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>ask</span><br /> <span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-layout'>,</span><span class='hs-varid'>i</span><span class='hs-layout'>,</span><span class='hs-varid'>d</span><span class='hs-layout'>)</span><span class='hs-keyglyph'><-</span><span class='hs-varid'>get</span><br /> <span class='hs-keyword'>let</span> <span class='hs-layout'>(</span><span class='hs-varid'>d'</span><span class='hs-layout'>,</span><span class='hs-varid'>o</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>execOVM</span> <span class='hs-varid'>p</span> <span class='hs-varid'>d</span> <span class='hs-varid'>i</span><br /> <span class='hs-varid'>put</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-varop'>+</span><span class='hs-num'>1</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-varid'>i</span><span class='hs-layout'>,</span><span class='hs-varid'>d'</span><span class='hs-layout'>)</span><br /> <span class='hs-keyword'>let</span> <span class='hs-varid'>co</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>currOrbit</span> <span class='hs-varid'>o</span><br /> <span class='hs-keyword'>let</span> <span class='hs-varid'>tgto</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>o</span><span class='hs-varop'>!-!</span><span class='hs-num'>4</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"-------------- At time "</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span> <span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-varop'>+</span><span class='hs-num'>1</span><span class='hs-layout'>)</span><span class='hs-varop'>++</span><span class='hs-str'>" --------------"</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"Score: "</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>o</span><span class='hs-varop'>!-!</span><span class='hs-num'>0</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"Fuel: "</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>o</span><span class='hs-varop'>!-!</span><span class='hs-num'>1</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"Position: "</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>myPosition</span> <span class='hs-varid'>o</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"Current Orbit: "</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>co</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"Target Orbit: "</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>tgto</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-str'>"Distance to go: "</span><span class='hs-varop'>++</span><span class='hs-varid'>show</span><span class='hs-layout'>(</span><span class='hs-varid'>tgto</span><span class='hs-comment'>-</span><span class='hs-varid'>co</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-varop'>+</span><span class='hs-num'>1</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span><span class='hs-varid'>o</span><span class='hs-layout'>)</span><br /><br /><span class='hs-definition'>applyInput</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>OBFData</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>SimVM</span><span class='hs-conid'>()</span><br /><span class='hs-definition'>applyInput</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>modify</span><span class='hs-varop'>.</span><span class='hs-varid'>changeInput</span><br /> <span class='hs-keyword'>where</span> <br /> <span class='hs-varid'>changeInput</span> <span class='hs-varid'>i</span> <span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-varid'>d</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>=</span><span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-layout'>,</span><span class='hs-varid'>i</span><span class='hs-layout'>,</span><span class='hs-varid'>d</span><span class='hs-layout'>)</span><br /> <br /><span class='hs-definition'>myPosition</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>OBFData</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>Vector</span> <span class='hs-conid'>Double</span><br /><span class='hs-definition'>myPosition</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftM2</span> <span class='hs-conid'>(,)</span> <span class='hs-layout'>(</span><span class='hs-varop'>!-!</span><span class='hs-num'>2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varop'>!-!</span><span class='hs-num'>3</span><span class='hs-layout'>)</span><br /> <br /><span class='hs-definition'>currOrbit</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>OBFData</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>Double</span><br /><span class='hs-definition'>currOrbit</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>magnitude</span><span class='hs-varop'>.</span><span class='hs-varid'>myPosition</span><br /><br /><span class='hs-definition'>currSpeed</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>OBFData</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>OBFData</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>Vector</span> <span class='hs-conid'>Double</span><br /><span class='hs-definition'>currSpeed</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>diff</span> <span class='hs-layout'>(</span><span class='hs-varid'>myPosition</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>myPosition</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span><br /><br /><span class='hs-comment'>{- Helpful constants -}</span><br /><span class='hs-definition'>earthMu</span><span class='hs-keyglyph'>=</span> <span class='hs-varid'>constG</span> <span class='hs-varop'>*</span> <span class='hs-varid'>earthM</span> <br /><span class='hs-definition'>constG</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>6.67428e-11</span> <span class='hs-keyglyph'>::</span><span class='hs-conid'>Double</span><br /><span class='hs-definition'>earthM</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>6.00000e24</span> <span class='hs-keyglyph'>::</span><span class='hs-conid'>Double</span><br /><span class='hs-definition'>earthR</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>6.357e6</span> <span class='hs-keyglyph'>::</span><span class='hs-conid'>Double</span><br /><br /><br /><br /><br /><span class='hs-comment'>{- returns the delta-vs and time of flight of a hohmann transfer<br /> between two circular orbits. -}</span><br /><span class='hs-definition'>calcHohmann</span><span class='hs-keyglyph'>::</span><span class='hs-conid'>Double</span><span class='hs-keyglyph'>-></span><span class='hs-conid'>Double</span><span class='hs-keyglyph'>-></span><span class='hs-layout'>(</span><span class='hs-conid'>Double</span><span class='hs-layout'>,</span><span class='hs-conid'>Double</span><span class='hs-layout'>,</span><span class='hs-conid'>Double</span><span class='hs-layout'>)</span><br /><span class='hs-definition'>calcHohmann</span> <span class='hs-varid'>r1</span> <span class='hs-varid'>r2</span><span class='hs-keyglyph'>=</span><span class='hs-layout'>(</span><span class='hs-varid'>dv1</span><span class='hs-layout'>,</span><span class='hs-varid'>dv2</span><span class='hs-layout'>,</span><span class='hs-varid'>tof</span><span class='hs-layout'>)</span><br /> <span class='hs-keyword'>where</span><br /> <span class='hs-varid'>dv1</span><span class='hs-keyglyph'>=</span><span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varid'>r1</span><span class='hs-layout'>)</span><span class='hs-varop'>*</span><span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>g</span> <span class='hs-varid'>r2</span><span class='hs-layout'>)</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>dv2</span><span class='hs-keyglyph'>=</span><span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-varid'>r2</span><span class='hs-layout'>)</span><span class='hs-varop'>*</span><span class='hs-layout'>(</span><span class='hs-num'>1</span><span class='hs-comment'>-</span><span class='hs-layout'>(</span><span class='hs-varid'>g</span> <span class='hs-varid'>r1</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>tof</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>pi</span><span class='hs-varop'>*</span><span class='hs-varid'>sqrt</span><span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-varop'>^</span><span class='hs-num'>3</span><span class='hs-layout'>)</span><span class='hs-varop'>/</span><span class='hs-varid'>earthMu</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>a</span><span class='hs-keyglyph'>=</span><span class='hs-layout'>(</span><span class='hs-varid'>r1</span><span class='hs-varop'>+</span><span class='hs-varid'>r2</span><span class='hs-layout'>)</span><span class='hs-varop'>/</span><span class='hs-num'>2</span><br /> <span class='hs-varid'>f</span> <span class='hs-varid'>x</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>sqrt</span> <span class='hs-layout'>(</span><span class='hs-varid'>earthMu</span><span class='hs-varop'>/</span><span class='hs-varid'>x</span><span class='hs-layout'>)</span><br /> <span class='hs-varid'>g</span> <span class='hs-varid'>x</span><span class='hs-keyglyph'>=</span><span class='hs-varid'>sqrt</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>/</span><span class='hs-varid'>a</span><span class='hs-layout'>)</span><br /><br /><br /><br /></pre><br /><br />PS: Vector é um <i>type synonim</i> para (Int,Int)!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-87522642159623168482009-08-16T18:02:00.018-03:002009-08-17T14:09:43.558-03:00Um cruzeiro ao som de Roberto Carlos<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibwh-tDCbc65h4DjHc3nFfdJhJHaxtv46cR_-PjEw0DrlNX190O4CtPZD8gXcxmPHFaoQTA5fzsZpex0_JwmMII8zh4MAgz8l0UJ2epXdlhTF2anvm1IeQBvBVK_HIi4rEdbixhwU-Un0/s1600-h/14-08-09_1222.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 240px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibwh-tDCbc65h4DjHc3nFfdJhJHaxtv46cR_-PjEw0DrlNX190O4CtPZD8gXcxmPHFaoQTA5fzsZpex0_JwmMII8zh4MAgz8l0UJ2epXdlhTF2anvm1IeQBvBVK_HIi4rEdbixhwU-Un0/s320/14-08-09_1222.jpg" alt="" id="BLOGGER_PHOTO_ID_5370670319194023922" border="0" /></a>Pois é pessoal! Ainda estou devendo a parte final do meu programa do ICFP2009. O programa ainda está muito mal estruturado, e enquanto não o arrumar, não pretendo colocar aqui. Além disso, comecei a brincar com o OpenGL em Haskell, pois quero visualizar as órbitas traçadas.<br /><br />Mudando de assunto, semana que vem é meu aniversário de casamento, e como diria o Roberto, "São tantas emoções". Estava passeando no Shopping Avenida Central com um colega, quando me deparei com o cartaz ao lado. Imediatamente tive a idéia de fotografá-lo e convidar a Paty para comemorar o nosso aniversário de casamento em um cruzeiro ao som de Roberto Carlos. Após alguma desconfiança ("você? Roberto Carlos?") e questionamentos ("mas esse cruzeiro é uma nota..."), mostrei para ela o cartaz de Carlos Evanney, o <span style="font-style: italic;">cover</span> oficial do Rei, que fará o seu terceiro cruzeiro pela Baía de Guanabara. Claro que a Paty caiu na risada, e achou uma excelente idéia (para não dizer o contrário)!<br /><br />O cartaz informa que o cruzeiro tem duração de 6 horas, saindo da Marina da Glória, passando por Niterói, Ilha Fiscal, Urca, Botafogo e Flamengo. Durante o passeio serão servidos cerveja, refrigerante, água mineral, pizza, salgadinhos e frutas. E tem diversão para todo mundo, pois o videokê está liberado!<br /><br />Agora, imagine você, leitor, fazendo aquele cruzeiro, em uma lanchinha, pela Baía de Guanabara com seu aroma típico, comendo uma coxinha de galinha e tomando um Baré-cola ou um Paquera, tudo ao som de um <span style="font-style: italic;">cover</span> do Roberto Carlos. Além disso, quando a música parar, poder fazer aquele dueto com sua amada no <span style="font-style: italic;">karaokê</span>. Pode ser mais romântico?Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com3tag:blogger.com,1999:blog-8203444459901609108.post-27137242174958170582009-08-01T22:26:00.009-03:002009-08-07T13:42:58.537-03:00O funk e a liberdade de expressãoEm 13 de julho de 2009 a Revista Época publicou uma reportagem onde criticava a truculência da PM que, ao coibir bailes <span style="font-style: italic;">funk</span> irregulares em algumas favelas cariocas, acabava por cercear a liberdade de expressão dos moradores, ao proibir qualquer tipo de <span style="font-style: italic;">funk</span> em qualquer tipo de evento.<br /><br />A PM se vale da Lei Estadual 5265/2008 que exige, para a realização de bailes <span style="font-style: italic;">funk</span>, uma série de requisitos, como banheiros, câmeras de vigilância, controle de entrada de menores, e, principalmente, autorização do Batalhão de Polícia Militar responsável pela área aonde o baile se realizará. Nem preciso comentar aqui que quase nenhum baile se adequa, se adequou, ou se adequará a essa Lei.<br /><br />Escrevi, na noite de 3 de julho, uma carta aonde expunha minha indignação com o baile <span style="font-style: italic;">funk</span> que não me deixava dormir. Versões dessa carta foram enviadas ao jornal O Globo, a editoria do programa Profissão Repórter e, finalmente, para a Revista Época. Esta última, demonstrando o seu caráter democrático, publicou-a na edição do dia 27 de Julho, mas por razões editoriais a resumiu, talvez até em demasia.<br /><br />Valendo-me da minha garantia constitucional de liberdade de expressão, reproduzo abaixo, <span style="font-weight: bold;">na íntegra</span>, a carta enviada a Revista Época.<br /><br /><hr /><br /><span style="font-style: italic;">"Prezados repórteres,</span><br /><br /><br /><span style="font-style: italic;">Lendo a revista Época desta semana, me deparei com a reportagem "Um 'créu' no funk" aonde o jornalista Nelito Fernandes questiona até que ponto a Lei Estadual 5265 é uma ameaça a liberdade de expressão. Desta forma sinto-me compelido a expor a minha visão de morador da Tijuca no Rio de Janeiro.</span><br /><br /><span style="font-style: italic;">A cada sexta-feira, sinto que Tim Lopes morreu em vão, em sua tentativa de mostrar a ligação dos bailes funk com a prostituição e exploração sexual de menores!</span><br /><br /><span style="font-style: italic;">Na sexta, dia 3 de julho, a noite, após uma semana exaustiva no trabalho, desligamos o despertador e nos deitamos mais cedo. O que seria, para alguns, a receita perfeita para começar o final de semana, para nós representou o início de uma noite de tortura, que vem se repetindo semana após semana. Por volta de 1:45 e eu e minha esposa fomos acordados abruptamente, como toda a sexta-feira nas últimas semanas, por um baile funk no morro do Salgueiro, com uma música tão alta que parecia haver um rádio ligado dentro de nossa casa.</span><br /><br /><span style="font-style: italic;">O baile funk no morro do Salgueiro, conhecido como o Caldeirão, começa toda a sexta, por volta de meia-noite, e vai até as cinco horas da manhã. Tudo ao som de uma música violentamente alta, ouvida perfeitamente a distância pelos moradores da Tijuca. Música que proclama o tráfico, e, principalmente, a pedofilia e a violência sexual. Em uma das músicas tocadas nesta madrugada, o DJ, que se identificava como Adriano, da equipe Pitbull, "declamava em versos" o que gostava de fazer (sexualmente) com "a novinha de 15 anos".</span><br /><br /><span style="font-style: italic;">O baile do Salgueiro é objeto de diversas comunidades da rede de relacionamentos Orkut. Não fica difícil identificar menores adolescentes que consultam horários e rotas para chegar ao morro, e que contam suas experiências.</span><br /><br /><span style="font-style: italic;">Moro em uma região em que há três hospitais e fico imaginando como deve ser estressante para os pacientes destas instituições. Imagino que mais estressante ainda é a vida do morador do morro, trabalhador, e que pega cedo no batente na manhã de sábado. Não acredito que todos no morro compactuem com esse baile, e nem que seja a minoria.</span><br /><br /><span style="font-style: italic;">A cada sexta-feira o baile começa mais tarde, com um som mais alto, e com letras de mais baixo calão, que colocam a mulher como prostituta e nós, cidadãos de bem, como otários. Como começa mais tarde, acaba mais tarde, mas nunca antes das 5:00 da manhã.</span><br /><br /><span style="font-style: italic;">Já tentei Polícia e Disque-denúncia. Os primeiros me informaram que sem um endereço completo, não há como deslocar a viatura para averiguação. O segundo, que foi aberta uma denúncia e que esta vai ser investigada. Concreto mesmo só os tampões de ouvido que eu e minha esposa compramos,</span> <span style="font-style: italic;">mas cuja eficiência, quando posta a prova, mostrou-se muito baixa.</span><br /><br /><span style="font-style: italic;">O síndico do prédio, em contato com uma das associações de moradores da Tijuca, descobriu uma denúncia feita ao Ministério Público e prontamente aderiu a lista de denunciantes. Nada ocorreu!</span><br /><br /><span style="font-style: italic;">Face a estes bailes, penso que, como tantas outras leis, a Lei Estadual 5265 demonstrou-se apenas mais um texto bonito tramitado em nossas Assembléias. Nem a Polícia e nem qualquer outro orgão público Estadual age para cumprí-la, seja por falta de pessoal, ineficiência ou pura</span> <span style="font-style: italic;">burocracia.</span><br /><br /><span style="font-style: italic;">As 2:50h da referida sexta-feira, o DJ avisava: "Desentoca aí galera! O baile está só começando, com muita putaria e orgia!". Durma-se com esse barulho!</span><br /><br /><span style="font-style: italic;">Na sexta-feira passada, dia 10 de julho, o baile funk teve um nível sonoro aceitável, percebido ao longe apenas com as janela bem abertas. Acredito que a mudança de comportamento tenha sido oriunda da presença da Polícia Militar no morro, após o assassinato do cabo Ênio Santiago,</span> <span style="font-style: italic;">do BOpE. Isto prova que o nível sonoro dos bailes só é alto como forma de provocação e intimidação por parte do tráfico que o organiza.</span><br /><br /><span style="font-style: italic;">De forma alguma quero discriminar pessoas que gostam, fazem ou frequentam bailes funk, mas é importante que tudo isto seja feito dentro dos limites legais, com respeito ao próximo.</span><br /><br /><br /><span style="font-style: italic;">Atenciosamente,</span><br /><br /><br /><span style="font-style: italic;">Rafael Gustavo da Cunha Pereira Pinto"</span><br /><hr /><br />De um ano para cá, dormir na sexta-feira vinha sendo apenas um sonho, enquanto a realidade se mostrava através do baile <span style="font-style: italic;">funk</span> aqui perto de casa. Infelizmente, a vida de um cabo da PM (mais especificamente do BOpE) precisou ser ceifada para que minhas noites de sono voltassem. Há três semanas o baile <span style="font-style: italic;">funk</span> ocorre em níveis sonoros aceitáveis, e me questiono constantemente da correlação entre os fatos.<br /><br />De qualquer forma, reafirmo: não sou contra o funk. Cada um ouve o que gosta! Entretanto, o <span style="font-weight: bold;">direito</span> a liberdade de expressão acaba exatamente onde o <span style="font-weight: bold;">dever</span> de respeitar às leis e ao próximo começa.<br /><br />Há um Projeto de Lei tramitando na Assembléia Legislativa do Rio de Janeiro, que pretende anular os efeitos da Lei Estadual 5265, e transformar o <span style="font-style: italic;">funk</span> carioca em patrimônio cultural.<br /><br />Para mim, tanto faz, pois não pretendo organizar bailes de qualquer espécie, mas gostaria muito que meu direito de dormir sossegado (garantido pela Lei do Silêncio, Lei Estadual 126/1977) fosse garantido, independente da música, da localidade.<br /><br />Afinal, nem todo <span style="font-style: italic;">funk</span> é criminoso e ruim: vide a letra de "Eu fico assim sem você", de Claudinho e Bochecha, regravado por Adriana Calcanhoto.Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-80819783344141813502009-07-20T08:41:00.002-03:002009-07-20T09:04:31.979-03:00ICFP 2009 - a máquina virtual - parte IIComo prometido, vou explicar a segunda mônada existente no código da máquina virtual. Observem o código abaixo:<br /><br /><pre> <span class="hs-varid">dType</span> <span class="hs-varid">op</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span> <span class="hs-layout">(</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varid">mem</span><span class="hs-layout">)</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">let</span> <span class="hs-varop">!</span><span class="hs-varid">result</span><span class="hs-keyglyph">=</span><span class="hs-layout">(</span><span class="hs-varid">liftM2</span> <span class="hs-varid">op</span> <span class="hs-layout">(</span><span class="hs-varop">!-!</span> <span class="hs-varid">r1</span><span class="hs-layout">)</span> <span class="hs-layout">(</span><span class="hs-varop">!-!</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span><span class="hs-layout">)</span> <span class="hs-varid">mem</span> <span class="hs-keyword">in</span><br /> <span class="hs-layout">(</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varid">insert</span> <span class="hs-varid">ip</span> <span class="hs-varid">result</span> <span class="hs-varid">mem</span><span class="hs-layout">)</span><br /></pre><br />Esta função implementa as instruções de dois operandos da máquina virtual. Essencialmente, essa função deve ler os dois valores da memória endereçados por <span style="font-style: italic;">r1</span> e <span style="font-style: italic;">r2</span>, executar a operação e escrever o resultado na posição <span style="font-style: italic;">ip</span>.<br /><br />A parte de escrever na memória é, simplesmente, uma chamada a <span style="font-style: italic;">insert</span>. Mas notem a declaração de <span style="font-style: italic;">result</span>. A par de usar o <span style="font-style: italic;">bang-pattern</span> (redundante, visto que <span style="font-style: italic;">insert</span> já é estrito nos parâmetros), estou usando <span style="font-style: italic;">liftM2</span>. Essa função possui como tipo:<br /><br /><pre><span class="hs-definition">liftM2</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Monad</span> <span class="hs-varid">m</span> <span class="hs-keyglyph">=></span> <span class="hs-layout">(</span><span class="hs-varid">a1</span> <span class="hs-keyglyph">-></span> <span class="hs-varid">a2</span> <span class="hs-keyglyph">-></span> <span class="hs-varid">r</span><span class="hs-layout">)</span> <span class="hs-keyglyph">-></span> <span class="hs-varid">m</span> <span class="hs-varid">a1</span> <span class="hs-keyglyph">-></span> <span class="hs-varid">m</span> <span class="hs-varid">a2</span> <span class="hs-keyglyph">-></span> <span class="hs-varid">m</span> <span class="hs-varid">r</span><br /></pre><br />ou seja: dada uma função de dois argumentos, <span style="font-style: italic;">liftM2</span> a transforma em uma função de duas mônadas, com comportamento equivalente. Vamos olhar rápidamente a declaração de (!-! r1), segundo parâmetro usado em <span style="font-style: italic;">liftM2</span>.<br /><br /><pre><span class="hs-layout">(</span><span class="hs-varop">!-!</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-conid">IntMap</span> <span class="hs-conid">Double</span> <span class="hs-keyglyph">-></span> <span class="hs-conid">Double</span><br /></pre>Peraí, mas <span style="font-style: italic;">Data.IntMap</span> não é uma mônada! O que <span style="font-style: italic;">liftM2</span> está fazendo então? Se olharmos rapidamente <span style="font-style: italic;">Control.Monad.Instances</span>, encontraremos que existe uma instância de mônada definida para <span style="font-style: italic;">((->) r)</span>, ou seja, funções que recebem parâmetro do tipo <span style="font-style: italic;">r</span> e retornam alguma outra coisa!<br /><br />Analisando então a função, vemos que <span style="font-style: italic;">liftM2 op (!-! r1) (!-!r2)</span> é uma mônada contendo um Double, e essa mônada é uma função que recebe um <span style="font-style: italic;">Data.IntMap</span>. Ou seja, o tipo de <span style="font-style: italic;">liftM2 op (!-! r1) (!-! r2)</span> é <span style="font-style: italic;">Data.IntMap->Double</span>! Não é lindo??<br /><br />No próximo <span style="font-style:italic;">post</span>, vou, finalmente, mostrar meu simulador de transferência de órbitas. Até lá!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-17087181273994819172009-07-17T08:00:00.004-03:002009-07-18T17:16:25.438-03:00ICFP 2009 - a máquina virtual - parte IFinalmente chegamos a máquina virtual! Vou analizá-la passo a passo pois se trata do código mais monádico que fiz até agora. Na verdade, esse é o código mais modificado até o momento! Começamos como sempre importando os módulos necessários.<br /><br /><pre><span class="hs-comment">{-# LANGUAGE BangPatterns #-}</span><br /><span class="hs-keyword">module</span> <span class="hs-conid">OVM</span> <span class="hs-keyword">where</span><br /><br /><span class="hs-keyword">import</span> <span class="hs-conid">Control</span><span class="hs-varop">.</span><span class="hs-conid">Arrow</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">Control</span><span class="hs-varop">.</span><span class="hs-conid">Monad</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">Control</span><span class="hs-varop">.</span><span class="hs-conid">Monad</span><span class="hs-varop">.</span><span class="hs-conid">RWS</span><span class="hs-varop">.</span><span class="hs-conid">Strict</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">OBFProgram</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">OBFData</span><br /></pre><br /><br />Podemos imaginar a máquina virtual como algo que recebe uma entrada, escreve uma saída, guardando na memória as etapas intermediárias. Isso é, por definição, o que a mônada <span style="font-style: italic;">RWS </span>faz. Uma mônada <span style="font-style: italic;">RWS </span>é a composição de 3 mônadas<br /><ol><br /><li><span style="font-weight: bold;">Reader</span>: definida como as funções que recebem um valor e retornam outro. Hã?! Sim, isso mesmo. O lance é que o parâmetro passado para a mônada na chamada de runReader é levado até o final, como uma espécie de "variável de ambiente". Essa variável pode ser lida a qualquer momento com a chamada a <span style="font-style: italic;">ask</span>. Como em toda mônada, o desenvolvedor não precisa se preocupar com a passagem dessa variável: a passagem é toda através do operador <span style="font-style: italic;">(>>=)</span></li><br /><li><span style="font-weight: bold;">Writer</span>: definida pelo par de um valor e um monóide. Monóides são objetos de uma categoria que implementa o vazio e a concatenação, algo como uma lista. Usando a chamada <span style="font-style: italic;">tell</span>, executamos a concatenação do parâmetro a esse monóide. A passagem do monóide entre chamadas é, também, feita pelo operador <span style="font-style: italic;">(>>=)</span>.</li><br /><li><span style="font-weight: bold;">State</span>: definida como as funções que recebem um valor e retornam um par, cujo segundo tipo é igual ao recebido. É como uma mônada Reader aonde, ao invés de apenas podemos consultar o ambiente, podemos alterá-lo. A consulta é feita pela chamada get, e a atualização com a chamada <span style="font-style: italic;">put</span>. Nem preciso falar como o estado é levado de uma chamada a outra...</li><br /></ol><br /><br />A mônada <span style="font-style: italic;">RWS </span>faz tudo isso ao mesmo tempo. Para iniciar a execução da mônada, diversas funções, como <span style="font-style: italic;">runRWS</span>, <span style="font-style: italic;">execRWS </span>e <span style="font-style: italic;">evalRWS</span>. Cada uma delas retorna uma parte diferente. Para nós, a versão interessante é a <span style="font-style: italic;">execRWS</span>, que recebe a mônada RWS, a entrada e o estado inicial, e responde com a saída e o estado final. O valor da mônada, nesse caso específico, é sempre <span style="font-style: italic;">()</span>.<br /><br /><pre><br /><span class="hs-comment">-- Read Write State </span><br /><span class="hs-comment">-- Input Output Status+Memory</span><br /><span class="hs-keyword">type</span> <span class="hs-conid">OVM</span> <span class="hs-varid">a</span><span class="hs-keyglyph">=</span><span class="hs-conid">RWS</span> <span class="hs-conid">OBFData</span> <span class="hs-conid">OBFData</span> <span class="hs-layout">(</span><span class="hs-conid">Bool</span><span class="hs-layout">,</span><span class="hs-conid">OBFData</span><span class="hs-layout">)</span> <span class="hs-varid">a</span><br /><br /><span class="hs-definition">execOVM</span><span class="hs-keyglyph">::</span><span class="hs-conid">OVM</span> <span class="hs-conid">()</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFData</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFData</span><span class="hs-keyglyph">-></span><span class="hs-layout">(</span><span class="hs-conid">OBFData</span><span class="hs-layout">,</span><span class="hs-conid">OBFData</span><span class="hs-layout">)</span><br /><span class="hs-definition">execOVM</span> <span class="hs-varop">!</span><span class="hs-varid">program</span> <span class="hs-varid">memory</span> <span class="hs-varid">input</span><span class="hs-keyglyph">=</span><br /> <span class="hs-keyword">let</span> <span class="hs-layout">(</span><span class="hs-layout">(</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varid">mem</span><span class="hs-layout">)</span><span class="hs-layout">,</span><span class="hs-varid">out</span><span class="hs-layout">)</span><span class="hs-keyglyph">=</span><span class="hs-varid">execRWS</span> <span class="hs-varid">program</span> <span class="hs-varid">input</span> <span class="hs-layout">(</span><span class="hs-conid">False</span><span class="hs-layout">,</span><span class="hs-varid">memory</span><span class="hs-layout">)</span> <span class="hs-keyword">in</span><br /> <span class="hs-layout">(</span><span class="hs-varid">mem</span><span class="hs-layout">,</span><span class="hs-varid">out</span><span class="hs-layout">)</span><br /></pre><br /><br />Mas como construímos a mônada? No caso do problema do ICFP, como não temos jumps, é fácil: é só fazer um <span style="font-style: italic;">foldM </span>sobre a lista de instruções retornada da leitura do arquivo:<br /><br /><pre><br /><span class="hs-definition">toOVM</span><span class="hs-keyglyph">::</span><span class="hs-conid">OBFProgram</span><span class="hs-keyglyph">-></span><span class="hs-conid">OVM</span> <span class="hs-conid">()</span><br /><span class="hs-definition">toOVM</span><span class="hs-keyglyph">=</span><span class="hs-varid">foldM</span> <span class="hs-layout">(</span><span class="hs-keyglyph">\</span><span class="hs-conid">()</span> <span class="hs-varop">!</span><span class="hs-varid">inst</span><span class="hs-keyglyph">-></span><span class="hs-varid">runInst</span> <span class="hs-varid">inst</span><span class="hs-layout">)</span> <span class="hs-conid">()</span><br /></pre><br /><br />Agora, o "problema" está em como tratar cada uma das operações. A mônada <span style="font-style: italic;">RWS </span>possui uma função chamada <span style="font-style: italic;">modify</span>, que recebe uma função responsável por modificar o estado. Então, tudo que temos que fazer é identificar a instrução e modificar o estado de forma apropriada. Há dois casos especiais: para Input, usamos diretamente a função <span style="font-style: italic;">ask </span>e gravamos no estado com <span style="font-style: italic;">put</span>, e para o Output, usamos o <span style="font-style: italic;">get </span>e chamamos <span style="font-style: italic;">tell </span>para escrever na saída.<br /><br /><pre><br /><span class="hs-definition">runInst</span><span class="hs-keyglyph">::</span><span class="hs-layout">(</span><span class="hs-conid">Int</span><span class="hs-layout">,</span><span class="hs-conid">OBFInst</span><span class="hs-layout">)</span><span class="hs-keyglyph">-></span><span class="hs-conid">OVM</span><span class="hs-conid">()</span><br /><span class="hs-definition">runInst</span> <span class="hs-varid">inst</span><span class="hs-keyglyph">@</span><span class="hs-layout">(</span><span class="hs-varid">ip</span><span class="hs-layout">,</span><span class="hs-varid">i</span><span class="hs-layout">)</span><span class="hs-keyglyph">=</span><br /> <span class="hs-keyword">case</span> <span class="hs-varid">i</span> <span class="hs-keyword">of</span><br /> <span class="hs-conid">Add</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">dType</span> <span class="hs-layout">(</span><span class="hs-varop">+</span><span class="hs-layout">)</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Sub</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">dType</span> <span class="hs-layout">(</span><span class="hs-comment">-</span><span class="hs-layout">)</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Mult</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">dType</span> <span class="hs-layout">(</span><span class="hs-varop">*</span><span class="hs-layout">)</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Div</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">dType</span> <span class="hs-layout">(</span><span class="hs-varop">//</span><span class="hs-layout">)</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Phi</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">dTypePhi</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Out</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span> <span class="hs-layout">(</span><span class="hs-varid">dTypeOutput</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span> <br /> <span class="hs-conid">Noop</span> <span class="hs-keyglyph">-></span><span class="hs-varid">return</span> <span class="hs-conid">()</span><br /> <span class="hs-conid">Cmpz</span> <span class="hs-conid">LTZ</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">sTypeCmpz</span> <span class="hs-layout">(</span><span class="hs-varop"><</span><span class="hs-num">0</span><span class="hs-layout">)</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Cmpz</span> <span class="hs-conid">LEZ</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">sTypeCmpz</span> <span class="hs-layout">(</span><span class="hs-varop"><=</span><span class="hs-num">0</span><span class="hs-layout">)</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Cmpz</span> <span class="hs-conid">EQZ</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">sTypeCmpz</span> <span class="hs-layout">(</span><span class="hs-varop">==</span><span class="hs-num">0</span><span class="hs-layout">)</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Cmpz</span> <span class="hs-conid">GEZ</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">sTypeCmpz</span> <span class="hs-layout">(</span><span class="hs-varop">>=</span><span class="hs-num">0</span><span class="hs-layout">)</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Cmpz</span> <span class="hs-conid">GTZ</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">sTypeCmpz</span> <span class="hs-layout">(</span><span class="hs-varop">></span><span class="hs-num">0</span><span class="hs-layout">)</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Sqrt</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">sType</span> <span class="hs-varid">sqrt</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Copy</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span><span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">sType</span> <span class="hs-varid">id</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span><span class="hs-layout">)</span><br /> <span class="hs-conid">Inp</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">-></span> <span class="hs-layout">(</span><span class="hs-varid">sTypeInput</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span><span class="hs-layout">)</span><br /> <span class="hs-keyword">where</span> <br /> <span class="hs-layout">(</span><span class="hs-varop">//</span><span class="hs-layout">)</span> <span class="hs-varid">v1</span> <span class="hs-varid">v2</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">if</span> <span class="hs-varid">v2</span><span class="hs-varop">==</span><span class="hs-num">0.0</span> <span class="hs-keyword">then</span> <span class="hs-num">0.0</span> <span class="hs-keyword">else</span> <span class="hs-varid">v1</span><span class="hs-varop">/</span><span class="hs-varid">v2</span><br /> <span class="hs-varid">dType</span> <span class="hs-varid">op</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span> <span class="hs-layout">(</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varid">mem</span><span class="hs-layout">)</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">let</span> <span class="hs-varop">!</span><span class="hs-varid">result</span><span class="hs-keyglyph">=</span><span class="hs-layout">(</span><span class="hs-varid">liftM2</span> <span class="hs-varid">op</span> <span class="hs-layout">(</span><span class="hs-varop">!-!</span> <span class="hs-varid">r1</span><span class="hs-layout">)</span> <span class="hs-layout">(</span><span class="hs-varop">!-!</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span><span class="hs-layout">)</span> <span class="hs-varid">mem</span> <span class="hs-keyword">in</span><br /> <span class="hs-layout">(</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varid">insert</span> <span class="hs-varid">ip</span> <span class="hs-varid">result</span> <span class="hs-varid">mem</span><span class="hs-layout">)</span><br /> <span class="hs-varid">sType</span> <span class="hs-varid">op</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span> <span class="hs-layout">(</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varid">mem</span><span class="hs-layout">)</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">let</span> <span class="hs-varop">!</span><span class="hs-varid">result</span><span class="hs-keyglyph">=</span><span class="hs-layout">(</span><span class="hs-varid">op</span> <span class="hs-varop">.</span> <span class="hs-layout">(</span><span class="hs-varop">!-!</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span><span class="hs-layout">)</span> <span class="hs-varid">mem</span> <span class="hs-keyword">in</span><br /> <span class="hs-layout">(</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varid">insert</span> <span class="hs-varid">ip</span> <span class="hs-varid">result</span> <span class="hs-varid">mem</span><span class="hs-layout">)</span><br /> <span class="hs-varid">sTypeCmpz</span> <span class="hs-varid">op</span> <span class="hs-varid">r2</span> <span class="hs-layout">(</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varid">mem</span><span class="hs-layout">)</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">let</span> <span class="hs-varop">!</span><span class="hs-varid">result</span><span class="hs-keyglyph">=</span><span class="hs-layout">(</span><span class="hs-varid">op</span> <span class="hs-varop">.</span> <span class="hs-layout">(</span><span class="hs-varop">!-!</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span><span class="hs-layout">)</span> <span class="hs-varid">mem</span> <span class="hs-keyword">in</span><br /> <span class="hs-layout">(</span><span class="hs-varid">result</span><span class="hs-layout">,</span><span class="hs-varid">mem</span><span class="hs-layout">)</span> <br /> <span class="hs-varid">dTypePhi</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span> <span class="hs-layout">(</span><span class="hs-varop">!</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varid">mem</span><span class="hs-layout">)</span><span class="hs-keyglyph">=</span><span class="hs-keyword">let</span> <span class="hs-varid">ix</span><span class="hs-keyglyph">=</span><span class="hs-layout">(</span><span class="hs-keyword">if</span> <span class="hs-varid">st</span> <span class="hs-keyword">then</span> <span class="hs-varid">r1</span> <span class="hs-keyword">else</span> <span class="hs-varid">r2</span><span class="hs-layout">)</span> <span class="hs-keyword">in</span><br /> <span class="hs-layout">(</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-layout">(</span><span class="hs-varid">insert</span> <span class="hs-varid">ip</span> <span class="hs-layout">(</span><span class="hs-varid">mem</span><span class="hs-varop">!-!</span><span class="hs-varid">ix</span><span class="hs-layout">)</span> <span class="hs-varid">mem</span><span class="hs-layout">)</span><span class="hs-layout">)</span><br /> <br /> <span class="hs-varid">sTypeInput</span> <span class="hs-varid">r2</span> <span class="hs-varid">ip</span><span class="hs-keyglyph">=</span><span class="hs-keyword">do</span><br /> <span class="hs-varop">!</span><span class="hs-varid">inp</span><span class="hs-keyglyph"><-</span><span class="hs-varid">asks</span> <span class="hs-layout">(</span><span class="hs-varop">!-!</span><span class="hs-varid">r2</span><span class="hs-layout">)</span><br /> <span class="hs-varid">modify</span> <span class="hs-layout">(</span><span class="hs-varid">second</span> <span class="hs-layout">(</span><span class="hs-varid">insert</span> <span class="hs-varid">ip</span> <span class="hs-varid">inp</span><span class="hs-layout">)</span><span class="hs-layout">)</span><br /> <br /> <span class="hs-varid">dTypeOutput</span> <span class="hs-varid">r1</span> <span class="hs-varid">r2</span><span class="hs-keyglyph">=</span><span class="hs-keyword">do</span><br /> <span class="hs-layout">(</span><span class="hs-varop">!</span><span class="hs-varid">st</span><span class="hs-layout">,</span><span class="hs-varop">!</span><span class="hs-varid">mem</span><span class="hs-layout">)</span><span class="hs-keyglyph"><-</span><span class="hs-varid">get</span><br /> <span class="hs-varid">tell</span> <span class="hs-layout">(</span><span class="hs-varid">singleton</span> <span class="hs-varid">r1</span> <span class="hs-layout">(</span><span class="hs-varid">mem</span><span class="hs-varop">!-!</span><span class="hs-varid">r2</span><span class="hs-layout">)</span><span class="hs-layout">)</span><br /></pre><br /><br />Como falei antes, não me interessa como o operador <span style="font-style:italic;">(>>=)</span> está implementado. O que me interessa é apenas o que é levado de uma função para outra por ele. <br /><br />Como a explicação é um pouco extensa, no próximo <span style="font-style:italic;">post</span> vou mostrar alguns detalhes adicionais de como uma das funções que modifica o estado também é monádica. Não percam!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-83260594371986326702009-07-16T08:07:00.006-03:002009-07-16T16:31:28.460-03:00ICFP2009 - estrutura de dadosUma das partes mais importantes em um programa em linguagem funcional é a escolha da estrutura de dados. Isto, principalmente, pois acesso direto a memória fere a pureza da linguagem.<br /><br />Para o ICFP2009, escolhi um <span style="font-style: italic;">IntMap</span> como estrutura de dados. A escolha foi baseada no fato que a implementação do IntMap possui busca e inserção (que também funciona como modificação) em <span style="font-style: italic;">O(n)</span>, mas limitado por um fator constante <span style="font-style: italic;">O(32)</span>.<br /><br />Se tivesse usado um <span style="font-style: italic;">Map</span> comum, teria inserções e buscas em <span style="font-style: italic;">O(log n)</span>. Um <span style="font-style: italic;">array</span>, mutável ou não, ofereceria inserção em <span style="font-style: italic;">O(n)</span> e busca em <span style="font-style: italic;">O(1)</span>. Como temos 2 vezes mais buscas que inserções (a maior parte das instruções é binária), teriamos O(n+2), que é sempre pior que o <span style="font-style: italic;">O(3 log n)</span> do <span style="font-style: italic;">Map</span>, e muito pior que o <span style="font-style: italic;">O(32)</span> do pior caso do IntMap.<br /><br /><br /><pre><span class="hs-comment">{-# LANGUAGE BangPatterns #-}</span><br /><span class="hs-keyword">module</span> <span class="hs-conid">OBFData</span> <span class="hs-keyword">where</span><br /><br /><span class="hs-keyword">import</span> <span class="hs-keyword">qualified</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">IntMap</span> <span class="hs-keyword">as</span> <span class="hs-conid">M</span><br /><br /><br /><span class="hs-keyword">type</span> <span class="hs-conid">OBFData</span><span class="hs-keyglyph">=</span><span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-conid">IntMap</span> <span class="hs-conid">Double</span><br /><br /><span class="hs-definition">singleton</span><span class="hs-keyglyph">::</span><span class="hs-conid">Int</span><span class="hs-keyglyph">-></span><span class="hs-conid">Double</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFData</span><br /><span class="hs-definition">singleton</span><span class="hs-keyglyph">=</span><span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-varid">singleton</span><br /><br /><span class="hs-definition">insert</span><span class="hs-keyglyph">::</span><span class="hs-conid">Int</span><span class="hs-keyglyph">-></span><span class="hs-conid">Double</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFData</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFData</span><br /><span class="hs-definition">insert</span> <span class="hs-varop">!</span><span class="hs-varid">k</span> <span class="hs-varop">!</span><span class="hs-varid">a</span> <span class="hs-varop">!</span><span class="hs-varid">m</span><span class="hs-keyglyph">=</span><span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-varid">insert</span> <span class="hs-varid">k</span> <span class="hs-varid">a</span> <span class="hs-varid">m</span><br /><br /><span class="hs-definition">union</span><span class="hs-keyglyph">::</span><span class="hs-conid">OBFData</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFData</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFData</span><br /><span class="hs-definition">union</span><span class="hs-keyglyph">=</span><span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-varid">union</span><br /><br /><span class="hs-definition">fromList</span><span class="hs-keyglyph">::</span><span class="hs-keyglyph">[</span><span class="hs-layout">(</span><span class="hs-conid">Int</span><span class="hs-layout">,</span><span class="hs-conid">Double</span><span class="hs-layout">)</span><span class="hs-keyglyph">]</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFData</span><br /><span class="hs-definition">fromList</span><span class="hs-keyglyph">=</span><span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-varid">fromList</span><br /><br /><span class="hs-definition">toList</span><span class="hs-keyglyph">=</span><span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-varid">toList</span><br /><br /><span class="hs-layout">(</span><span class="hs-varop">!-!</span><span class="hs-layout">)</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-conid">IntMap</span> <span class="hs-conid">Double</span> <span class="hs-keyglyph">-></span> <span class="hs-conid">Int</span> <span class="hs-keyglyph">-></span> <span class="hs-conid">Double</span><br /><span class="hs-layout">(</span><span class="hs-varop">!-!</span><span class="hs-layout">)</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">flip</span> <span class="hs-layout">(</span><span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-varid">findWithDefault</span> <span class="hs-num">0.0</span><span class="hs-layout">)</span><br /><span class="hs-keyword">infixl</span> <span class="hs-num">9</span> <span class="hs-varop">!-!</span><br /></pre><br /><br />Peço ao leitor que note algumas coisas:<br /><br /><ol><li>Estou forçando os tipos da estrutura de dados. Faço isso pois não tenho a necessidade de que essa estrutura de dados permaneça polimórfica. Se assim fosse, poderia usar <span style="font-style: italic;">IntMap</span> diretamente.</li><li>Uso <span style="font-style: italic;">bang patterns</span> nos argumentos da chamada de <span style="font-style: italic;">insert</span>. Faço isso para que não se acumulem <span style="font-style: italic;">thunks</span> dentro do <span style="font-style: italic;">IntMap</span>, o que seria péssimo para o desempenho</li><li>Implementei um operador que retorna 0.0 caso acesse uma posição de memória não inicializada. Isto evita que eu tenha que criar o <span style="font-style: italic;">IntMap</span> com as 16384 entradas preenchidas de cara.<br /></li></ol><br />Espero ter surpreendido, sim, pela simpliciade. Muito pior que fazer a estrutura, é a escolha de qual utilizar. A programação funcional força o programador a pensar no algoritmo mais eficiente, ao invés de pensar em <span style="font-style: italic;">hacks</span> para tornar o código mais rápido.<br />Para quem quiser se aprofundar em estruturas de dados funcionais, sugiro dar uma lida no livro <span style="font-style: italic;">"Purely functional data structures"</span> de Chris Okasaki, que desbrava as estruturas de dados neste universo imutável.<br /><br /><span style="font-weight: bold;">PS</span>: Pensei também em amortizar o custo das inserções, mas acho que não é possível, pois todos os acessos de consulta são intercalados às buscas.Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-82671756232580305632009-07-15T08:03:00.009-03:002009-07-16T16:34:29.286-03:00ICFP2009 - decodificando o programaLinguagens funcionais são fantásticas quando sabemos aproveitá-las. Uma das coisas mais legais de se fazer em uma linguagem funcional é outra linguagem! Na tarefa do ICFP Contest 2009, uma das etapas é construir a VM para executar o binário fornecido.<br /><br />Poderíamos decodificar as instruções apenas na hora de executá-las, mas em Haskell (ou qualquer linguagem funcional), é bem mais simples aplicar um <span style="font-style: italic;">map</span> na lista de <span style="font-style: italic;">Word32</span> lida, convertendo-a em uma lista de dados do tipo instrução.<br /><br />Começamos isso definindo o tipo:<br /><br /><pre><span class="hs-keyword">module</span> <span class="hs-conid">OBFProgram</span> <span class="hs-keyword">where</span><br /><br /><span class="hs-keyword">import</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Word</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Bits</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">OBFData</span><br /><br /><br /><span class="hs-keyword">type</span> <span class="hs-conid">OBFProgram</span><span class="hs-keyglyph">=</span><span class="hs-keyglyph">[</span><span class="hs-layout">(</span><span class="hs-conid">Int</span><span class="hs-layout">,</span><span class="hs-conid">OBFInst</span><span class="hs-layout">)</span><span class="hs-keyglyph">]</span><br /><br /><span class="hs-keyword">data</span> <span class="hs-conid">OBFInst</span><span class="hs-keyglyph">=</span> <span class="hs-conid">Add</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Sub</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Mult</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Div</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Out</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Phi</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Noop</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Cmpz</span> <span class="hs-conid">CmpzType</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Sqrt</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Copy</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">Inp</span> <span class="hs-varop">!</span><span class="hs-conid">Int</span><br /> <span class="hs-keyword">deriving</span> <span class="hs-layout">(</span><span class="hs-conid">Show</span><span class="hs-layout">,</span><span class="hs-conid">Eq</span><span class="hs-layout">)</span><br /><br /><span class="hs-keyword">data</span> <span class="hs-conid">CmpzType</span><span class="hs-keyglyph">=</span> <span class="hs-conid">LTZ</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">LEZ</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">EQZ</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">GEZ</span> <span class="hs-keyglyph">|</span><br /> <span class="hs-conid">GTZ</span><br /> <span class="hs-keyword">deriving</span><span class="hs-layout">(</span><span class="hs-conid">Show</span><span class="hs-layout">,</span> <span class="hs-conid">Enum</span><span class="hs-layout">,</span><span class="hs-conid">Eq</span><span class="hs-layout">)</span><br /></pre><br />Haskell é uma linguagem de avaliação tardia, mas nem sempre isso é bom. O <span style="font-style: italic;">map</span> utilizado em <span style="font-style: italic;">decode</span> só vai ser executado quando pegarmos o primeiro item da nova lista. Mas se cada elemento dentro do map também for tardio, significa que iremos ler o arquivo também nessa primeira execução, o que pode tornar tudo muito lento. Outro problema é que, a medida que vamos "acumulando" execuções atrasadas (<span style="font-style: italic;">thunks</span>), elas vão se juntando em memória, criando um enorme bloco. Para reduzir isso, coloquei os <span style="font-style: italic;">!</span> antes de cada elemento dentro da declaração do tipo. Esse <span style="font-style: italic;">!</span> (também conhecido como <span style="font-style: italic;">bang</span>) identifica um <span style="font-style: italic;">placeholder</span> onde o dado só pode entrar depois de computado. Desta forma, quando crio, por exemplo, <span style="font-style: italic;">Add x y</span>, a execução dos <span style="font-style: italic;">thunks</span> que geram <span style="font-style: italic;">x</span> e <span style="font-style: italic;">y</span> vai ser forçada, e o elemento irá guardar efetivamente um inteiro em cada uma das posições.<br /><pre><br /><span class="hs-definition">decode</span><span class="hs-keyglyph">::</span><span class="hs-keyglyph">[</span><span class="hs-conid">Word32</span><span class="hs-keyglyph">]</span><span class="hs-keyglyph">-> </span><span class="hs-conid">OBFProgram</span><br /><span class="hs-definition">decode</span> <span class="hs-varid">x</span><span class="hs-keyglyph">=</span><span class="hs-varid">filter</span> <span class="hs-layout">(</span><span class="hs-layout">(</span><span class="hs-varop">/=</span><span class="hs-conid">Noop</span><span class="hs-layout">)</span><span class="hs-varop">.</span><span class="hs-varid">snd</span><span class="hs-layout">)</span> <span class="hs-layout">(</span><span class="hs-varid">zip</span> <span class="hs-keyglyph">[</span><span class="hs-num">0</span><span class="hs-keyglyph">..</span><span class="hs-keyglyph">]</span> <span class="hs-layout">(</span><span class="hs-varid">map</span> <span class="hs-varid">decodeInstruction</span> <span class="hs-varid">x</span><span class="hs-layout">)</span><span class="hs-layout">)</span><br /></pre><br />O restante do código é bastante básico. Mastigamos os bits de cada <span style="font-style: italic;">Word32</span> e, utilizando <span style="font-style: italic;">case</span>, convertemos cada elemento da lista em uma instrução.<br /><pre><br /><span class="hs-definition">decodeInstruction</span><span class="hs-keyglyph">::</span><span class="hs-conid">Word32</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFInst</span><br /><span class="hs-definition">decodeInstruction</span> <span class="hs-varid">x</span><span class="hs-keyglyph">=</span><br /> <span class="hs-keyword">case</span> <span class="hs-varid">opcode</span> <span class="hs-keyword">of</span><br /> <span class="hs-num">0</span> <span class="hs-keyglyph">-></span> <span class="hs-varid">decodeSType</span> <span class="hs-varid">par1</span> <span class="hs-varid">par2</span><br /> <span class="hs-num">1</span> <span class="hs-keyglyph">-></span> <span class="hs-conid">Add</span> <span class="hs-varid">par1</span> <span class="hs-varid">par2</span><br /> <span class="hs-num">2</span> <span class="hs-keyglyph">-></span> <span class="hs-conid">Sub</span> <span class="hs-varid">par1</span> <span class="hs-varid">par2</span><br /> <span class="hs-num">3</span> <span class="hs-keyglyph">-></span> <span class="hs-conid">Mult</span> <span class="hs-varid">par1</span> <span class="hs-varid">par2</span><br /> <span class="hs-num">4</span> <span class="hs-keyglyph">-></span> <span class="hs-conid">Div</span> <span class="hs-varid">par1</span> <span class="hs-varid">par2</span><br /> <span class="hs-num">5</span> <span class="hs-keyglyph">-></span> <span class="hs-conid">Out</span> <span class="hs-varid">par1</span> <span class="hs-varid">par2</span><br /> <span class="hs-num">6</span> <span class="hs-keyglyph">-></span> <span class="hs-conid">Phi</span> <span class="hs-varid">par1</span> <span class="hs-varid">par2</span> <br /> <span class="hs-keyword">where</span><br /> <span class="hs-varid">opcode</span><span class="hs-keyglyph">=</span><span class="hs-varid">fromIntegral</span><span class="hs-layout">(</span> <span class="hs-layout">(</span><span class="hs-varid">x</span> <span class="hs-varop">`shiftR`</span> <span class="hs-num">28</span><span class="hs-layout">)</span> <span class="hs-varop">.&.</span> <span class="hs-num">15</span> <span class="hs-layout">)</span><br /> <span class="hs-varid">par1</span> <span class="hs-keyglyph">=</span><span class="hs-varid">fromIntegral</span><span class="hs-layout">(</span> <span class="hs-layout">(</span><span class="hs-varid">x</span> <span class="hs-varop">`shiftR`</span> <span class="hs-num">14</span><span class="hs-layout">)</span> <span class="hs-varop">.&.</span> <span class="hs-num">16383</span> <span class="hs-layout">)</span><br /> <span class="hs-varid">par2</span> <span class="hs-keyglyph">=</span><span class="hs-varid">fromIntegral</span><span class="hs-layout">(</span> <span class="hs-varid">x</span> <span class="hs-varop">.&.</span> <span class="hs-num">16383</span> <span class="hs-layout">)</span><br /><br /><span class="hs-definition">decodeSType</span><span class="hs-keyglyph">::</span><span class="hs-conid">Int</span><span class="hs-keyglyph">-></span><span class="hs-conid">Int</span><span class="hs-keyglyph">-></span><span class="hs-conid">OBFInst</span><br /><span class="hs-definition">decodeSType</span> <span class="hs-varid">par1</span> <span class="hs-varid">par2</span><span class="hs-keyglyph">=</span><br /> <span class="hs-keyword">case</span> <span class="hs-varid">opcode</span> <span class="hs-keyword">of</span><br /> <span class="hs-num">0</span><span class="hs-keyglyph">-></span><span class="hs-conid">Noop</span><br /> <span class="hs-num">1</span><span class="hs-keyglyph">-></span><span class="hs-conid">Cmpz</span> <span class="hs-layout">(</span><span class="hs-varid">toEnum</span> <span class="hs-varid">imm</span><span class="hs-layout">)</span> <span class="hs-varid">par2</span><br /> <span class="hs-num">2</span><span class="hs-keyglyph">-></span><span class="hs-conid">Sqrt</span> <span class="hs-varid">par2</span><br /> <span class="hs-num">3</span><span class="hs-keyglyph">-></span><span class="hs-conid">Copy</span> <span class="hs-varid">par2</span><br /> <span class="hs-num">4</span><span class="hs-keyglyph">-></span><span class="hs-conid">Inp</span> <span class="hs-varid">par2</span><br /> <span class="hs-keyword">where</span><br /> <span class="hs-varid">opcode</span> <span class="hs-keyglyph">=</span> <span class="hs-layout">(</span><span class="hs-varid">par1</span> <span class="hs-varop">`shiftR`</span> <span class="hs-num">10</span><span class="hs-layout">)</span><span class="hs-varop">.&.</span><span class="hs-num">15</span><br /> <span class="hs-varid">imm</span> <span class="hs-keyglyph">=</span> <span class="hs-layout">(</span><span class="hs-varid">par1</span> <span class="hs-varop">`shiftR`</span> <span class="hs-num">7</span><span class="hs-layout">)</span><span class="hs-varop">.&.</span> <span class="hs-num">7</span><br /></pre><br />No próximo post, vou apresentar a minha versão da representação dos dados. Essa sim, vai surpreender.Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-16301988953953224872009-07-14T13:12:00.007-03:002009-07-15T08:02:46.853-03:00ICFP2009 - lendo o arquivoEssa é a primeira parte da tarefa do ICFP2009: ler o arquivo. Nada demais, uma vez que você conheça a Data.Binary e a Data.Binary.IEEE754! Vou percorrer um pouco desse código.<br /><br />Inicialmente, declaramos o módulo e importamos as <span style="font-style: italic;">libraries</span>:<br /><br /><pre><span class="hs-keyword">module</span> <span class="hs-conid">OBFFile</span> <span class="hs-keyword">where</span><br /><br /><span class="hs-keyword">import</span> <span class="hs-keyword">qualified</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span><span class="hs-varop">.</span><span class="hs-conid">Lazy</span> <span class="hs-keyword">as</span> <span class="hs-conid">BL</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">Control</span><span class="hs-varop">.</span><span class="hs-conid">Arrow</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Binary</span><span class="hs-varop">.</span><span class="hs-conid">Get</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Binary</span><span class="hs-varop">.</span><span class="hs-conid">IEEE754</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">System</span><span class="hs-varop">.</span><span class="hs-conid">IO</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Word</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">OBFProgram</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">OBFData</span><br /><span class="hs-keyword">import</span> <span class="hs-conid">OVM</span><br /></pre><br /><br />A função principal é dividida em duas partes: primeiro, lemos o conteúdo inteiro em um <span style="font-style: italic;">ByteString</span> e o passamos para a segunda parte. Na segunda parte, abusando da notação <span style="font-style: italic;">point-free</span>, lemos todos os frames do arquivo, usando uma mônada Get do pacote Data.Binary. Em seguida, convertemos a lista de tuplas em uma tuplas de listas. Com a primeira lista, decodificamos as instruções do programa e convertemos em uma mônada OVM, que descreverei mais tarde. A segunda lista é convertida em um IntMap, e corresponde a inicialização da memória. O <span style="font-style: italic;">return</span> está aí somente para empacotar o resultado em uma mônada <span style="font-style: italic;">IO</span>.<br /><br /><pre><br /><span class="hs-definition">readOBFFile</span><span class="hs-keyglyph">::</span><span class="hs-conid">Handle</span><span class="hs-keyglyph">-></span><span class="hs-conid">IO</span> <span class="hs-layout">(</span><span class="hs-conid">OVM</span><span class="hs-conid">()</span><span class="hs-layout">,</span><span class="hs-conid">OBFData</span><span class="hs-layout">)</span><br /><span class="hs-definition">readOBFFile</span> <span class="hs-varid">h</span><span class="hs-keyglyph">=</span><span class="hs-conid">BL</span><span class="hs-varop">.</span><span class="hs-varid">hGetContents</span> <span class="hs-varid">h</span> <span class="hs-varop">>>=</span> <span class="hs-varid">readOBFFile'</span><br /><br /><span class="hs-definition">readOBFFile'</span><span class="hs-keyglyph">::</span> <span class="hs-conid">BL</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span><span class="hs-keyglyph">-></span><span class="hs-conid">IO</span> <span class="hs-layout">(</span><span class="hs-conid">OVM</span><span class="hs-conid">()</span><span class="hs-layout">,</span><span class="hs-conid">OBFData</span><span class="hs-layout">)</span><br /><span class="hs-definition">readOBFFile'</span><span class="hs-keyglyph">=</span><span class="hs-varid">return</span><span class="hs-varop">.</span><span class="hs-layout">(</span><span class="hs-varid">toOBFProgram</span> <span class="hs-varop">***</span> <span class="hs-varid">toOBFData</span><span class="hs-layout">)</span><span class="hs-varop">.</span> <span class="hs-varid">unzip</span> <span class="hs-varop">.</span> <span class="hs-varid">runGet</span> <span class="hs-varid">getFrames</span><br /><span class="hs-keyword"> where</span><br /><span class="hs-varid"> toOBFData</span><span class="hs-keyglyph">=</span><span class="hs-varid">fromList</span> <span class="hs-varop">.</span><span class="hs-layout">(</span><span class="hs-varid">filter</span> <span class="hs-layout">(</span><span class="hs-layout">(</span><span class="hs-varop">/=</span><span class="hs-num">0.0</span><span class="hs-layout">)</span><span class="hs-varop">.</span><span class="hs-varid">snd</span><span class="hs-layout">)</span><span class="hs-layout">)</span><span class="hs-varop">.</span> <span class="hs-layout">(</span><span class="hs-varid">zip</span> <span class="hs-keyglyph">[</span><span class="hs-num">0</span><span class="hs-keyglyph">..</span><span class="hs-keyglyph">]</span><span class="hs-layout">)</span><br /><span><span class="hs-varid"> </span></span><span class="hs-varid">toOBFProgram</span><span class="hs-keyglyph">=</span><span class="hs-varid">toOVM</span><span class="hs-varop">.</span><span class="hs-varid">decode</span><br /></pre><br /><br />Finalmente a leitura propriamente dita funciona como um <span style="font-style: italic;">fold</span> em duas etapas. Se a entrada não está vazia, lemos o <span style="font-style: italic;">frame </span>par, que tem o formato (memória, instrução) e chamamos a função do <span style="font-style: italic;">frame </span>ímpar, com o formato invertido. A cada operação, concatenamos o resultado na cabeça de uma lista acumuladora. Finalmente, quando a entrada está vazia, retornamos a lista acumuladora revertida, nos valendo da amortização da operação.<br /><br /><pre><br /><span class="hs-definition">getFrames</span><span class="hs-keyglyph">::</span><span class="hs-conid">Get</span> <span class="hs-keyglyph">[</span><span class="hs-layout">(</span><span class="hs-conid">Word32</span><span class="hs-layout">,</span><span class="hs-conid">Double</span><span class="hs-layout">)</span><span class="hs-keyglyph">]</span><br /><span class="hs-definition">getFrames</span><span class="hs-keyglyph">=</span><span class="hs-varid">getEvenFrames</span> <span class="hs-conid">[]</span><br /><br /><span class="hs-definition">getEvenFrames</span><span class="hs-keyglyph">::</span><span class="hs-keyglyph">[</span><span class="hs-layout">(</span><span class="hs-conid">Word32</span><span class="hs-layout">,</span><span class="hs-conid">Double</span><span class="hs-layout">)</span><span class="hs-keyglyph">]</span><span class="hs-keyglyph">-></span><span class="hs-conid">Get</span> <span class="hs-keyglyph">[</span><span class="hs-layout">(</span><span class="hs-conid">Word32</span><span class="hs-layout">,</span><span class="hs-conid">Double</span><span class="hs-layout">)</span><span class="hs-keyglyph">]</span><br /><span class="hs-definition">getEvenFrames</span> <span class="hs-varid">acc</span><span class="hs-keyglyph">=</span><br /><span class="hs-keyword"> do</span><br /><span><span class="hs-varid"> </span></span><span class="hs-varid">b</span><span class="hs-keyglyph"><-</span><span class="hs-varid">isEmpty</span><br /><span><span class="hs-varid"> </span></span><span class="hs-keyword">if</span> <span class="hs-varid">b</span> <span class="hs-keyword">then</span> <span class="hs-varid">return</span> <span class="hs-layout">(</span><span class="hs-varid">reverse</span> <span class="hs-varid">acc</span><span class="hs-layout">)</span><br /><span><span class="hs-varid"> </span></span> <span class="hs-keyword">else</span> <span class="hs-keyword">do</span><br /><span><span class="hs-varid"> </span></span> <span class="hs-varid">d</span><span class="hs-keyglyph"><-</span><span class="hs-varid">getFloat64le</span><br /><span><span class="hs-varid"> </span></span> <span class="hs-varid">i</span><span class="hs-keyglyph"><-</span><span class="hs-varid">getWord32le</span><br /><span><span class="hs-varid"> </span></span> <span class="hs-varid">getOddFrames</span> <span class="hs-layout">(</span><span class="hs-layout">(</span><span class="hs-varid">i</span><span class="hs-layout">,</span><span class="hs-varid">d</span><span class="hs-layout">)</span><span class="hs-conop">:</span><span class="hs-varid">acc</span><span class="hs-layout">)</span><br /><br /><br /><span class="hs-definition">getOddFrames</span><span class="hs-keyglyph">::</span><span class="hs-keyglyph">[</span><span class="hs-layout">(</span><span class="hs-conid">Word32</span><span class="hs-layout">,</span><span class="hs-conid">Double</span><span class="hs-layout">)</span><span class="hs-keyglyph">]</span><span class="hs-keyglyph">-></span><span class="hs-conid">Get</span> <span class="hs-keyglyph">[</span><span class="hs-layout">(</span><span class="hs-conid">Word32</span><span class="hs-layout">,</span><span class="hs-conid">Double</span><span class="hs-layout">)</span><span class="hs-keyglyph">]</span><br /><span class="hs-definition">getOddFrames</span> <span class="hs-varid">acc</span><span class="hs-keyglyph">=</span><br /><span class="hs-keyword"> do</span><br /><span><span class="hs-varid"> </span></span><span class="hs-varid">b</span><-<span class="hs-varid">isEmpty</span><br /><span><span class="hs-varid"> </span></span><span class="hs-keyword">if</span> <span class="hs-varid">b</span> <span class="hs-keyword">then</span> <span class="hs-varid">return</span> <span class="hs-layout">(</span><span class="hs-varid">reverse</span> <span class="hs-varid">acc</span><span class="hs-layout">)</span><br /><span><span class="hs-varid"> </span></span> <span class="hs-keyword">else</span> <span class="hs-keyword">do</span><br /><span><span class="hs-varid"> </span></span> <span class="hs-varid">i</span><-<span class="hs-varid">getWord32le</span><br /><span><span class="hs-varid"> </span></span> <span class="hs-varid">d</span><span class="hs-keyglyph"><-</span><span class="hs-varid">getFloat64le</span><br /><span><span class="hs-varid"> </span></span> <span class="hs-varid">getEvenFrames</span> <span class="hs-layout">(</span><span class="hs-layout">(</span><span class="hs-varid">i</span><span class="hs-layout">,</span><span class="hs-varid">d</span><span class="hs-layout">)</span><span class="hs-conop">:</span><span class="hs-varid">acc</span><span class="hs-layout">)</span><br /></pre><br /><br />Se não fossem os <span style="font-style: italic;">do</span>s e eu ter citado, o leitor provavelmente não notaria o uso da mônada Get, e imaginaria que Get é uma composição de funções. O segredo está na definição do Get:<br /><br /><br /><pre><span class="hs-keyword">newtype</span> <span class="hs-conid">Get</span> <span class="hs-varid">a</span> <span class="hs-keyglyph">=</span> <span class="hs-conid">Get</span> <span class="hs-layout">{</span> <span class="hs-varid">unGet</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">S</span> <span class="hs-keyglyph">-></span> <span class="hs-layout">(</span><span class="hs-varid">a</span><span class="hs-layout">,</span> <span class="hs-conid">S</span><span class="hs-layout">)</span> <span class="hs-layout">}</span></pre><br />Na verdade, a poderosa mônada Get não passa de uma função que leva um estado a uma saída e outro estado. A função <span style="font-style: italic;">runGet </span>chama <span style="font-style: italic;">unGet</span> (a implementação do Get) com a inicialização do estado, obtida a partir do <span style="font-style: italic;">Lazy ByteString</span> que é passado como parametro.<br /><br />Quando combinamos mônadas, usando os <span style="font-style: italic;">getWord32le </span>e <span style="font-style: italic;">getFloat64le</span>, estamos gerando uma composição de função aonde não precisamos nos importar em costurar o estado de uma chamada para outra. Toda essa composição é feita na implementação do operador (>>=) e se torna irrelevante para o "usuário" da mônada.<br /><br />Mas o leitor pode perguntar: "Legal, mas aonde esse operador foi usado?? Não o vejo em lugar nenhum, depois de <span style="font-style: italic;">readOBFFile</span>". Fácil! Nesse ponto entra o maior <span style="font-style: italic;">syntatic sugar</span> do Haskell, destinado a transfomar as mônadas em <span style="font-style: italic;">warm, fuzzy things</span>: a notação <span style="font-style: italic;">do</span>! Podemos subentender cada linha como separada por um >>= e cada "retorno" como uma definição lambda. Assim, <span style="font-style: italic;">i<-getWord32le</span> poderia ser escrito "<span style="font-style: italic;">getWord32le >>= \i-></span>" (em pseudo-Haskell).<br /><br />Foi por isso que falei que as mônadas não são coisa de outro mundo! Continuarei dissecando meu código nos próximos posts!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-50686376894677351992009-07-07T12:44:00.007-03:002009-07-07T13:19:09.047-03:00Tutoriais sobre mônadasPensei bem no último <span style="font-style: italic;">post</span> e não quero construir mais um tutorial de mônadas. Acho que não consigo atingir a mesma profundidade, mantendo a mesma simplicidade apresentada nos dois tutoriais abaixo:<br /><br /><ul><li><a href="http://pages.cpsc.ucalgary.ca/%7Erobin/class/521/monadGuide.pdf">The Haskell Programmer’s Guide to the IO Monad - Don't Panic</a> - Um tutorial bastante teórico, ligando a teoria das categorias a linguagem Haskell. Apesar de toda a matemática <span style="font-style: italic;">hardcore</span>, é interessante para aprender que as mônadas não são um mecanismo de computação ou de sequenciamento, e sim que esses mecanismos podem ser emulados por uma mônada. Vale a pena também olhar o que a <a href="http://en.wikipedia.org/wiki/Monad_%28category_theory%29">Wikipedia tem a dizer</a>.<br /></li><li><a href="http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf">Monads for functional programming</a> - Este artigo de Philip Wadler é exatamente o oposto do anterior: trata as mônadas apenas nos seus aspectos relacionados a implementação dos efeitos colaterais da linguagem, sem se preocupar com as questões matemático-filosóficas da teoria das categorias.<br /></li></ul><br />Os piores exemplos de mônadas são os tipos Maybe e as listas. Esses tipos, apesar de poderem ser monadicos, não demonstram o poderio dessa abstração. Wadler apresenta exemplos muito mais úteis, baseados em funções monadicas (Reader e State) e em monóides (Writer e Error). Vale a pena dar uma olhada, pois é exatamente isto que estou usando no código do concurso do ICFP 2009.Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-33086195830090788522009-07-03T11:12:00.012-03:002009-07-06T07:44:09.711-03:00Haskell, as mônadas e o ICFPMônadas (<span style="font-style: italic;">monads</span> em inglês) são o ponto alto da programação funcional. Em Haskell, uma linguagem que se proclama puramente funcional, elas são a saída honrosa para os efeitos colaterais inexoráveis, também conhecidos como E/S.<br /><br />Segundo Simon Peyton-Jones, um dos pais do Haskell, um programa puramente funcional é como uma caixa fechada. Não temos como saber se ela está funcionando, pois nem esquenta. O E/S é fundamental, mas quebra o conceito da pureza, por alterar "todo o universo" cada vez que ocorre. Para isolar os efeitos colaterais do corpo da linguagem, os criadores do Haskell utilizaram o conceito das mônadas. O grande problema surge então quando vamos tentar entendê-las: mônadas são entes matemáticos oriundos da teoria das categorias, um ramo tresloucado da álgebra abstrata. É uma piada recorrente dizer que o rito de iniciação do neófito em Haskell é escrever um tutorial sobre mônadas!<br /><br />Após ler cerca de uma dúzia de tutoriais, que incluem desde o mais mão-na-massa a um tutorial sobre teoria das categorias, não consegui, de forma alguma, entender como essas mônadas poderiam me ajudar em alguma coisa. Para piorar, por ser uma linguagem com avaliação tardia, toda ação que exigia sequência se tornava tediosamente complexa. No concurso do ICFP 2009, finalmente entendi uma frase famosa de Simon Peyton Jones: "O grande erro foi usarmos o nome mônadas. Deveríamos ter chamado de 'coisas fofinhas' (<span style="font-style: italic;">warm, fuzzy things</span>, no original)".<br /><br />Na verdade, toda a teoria das categorias serve apenas para explicar por que as mônadas funcionam. O programador que vai criar uma mônada precisa de um conhecimento mínimo sobre elas, e o programador que vai usar precisa saber apenas como as funções expostas para a mônada interagem com ela, ignorando o funcionamento interno. Com este ponto de vista, o mais importante é entender o funcionamento do operador (>>=), que, inclusive, é a logomarca atual do Haskell.<br /><br />Nas próximas postagens, vou colocar exemplos retirados do código que estou escrevendo para solução do problema do ICFP 2009, procurando demonstrar esta minha tese.<br /><br />Alias, talvez até possamos considerar isto um tutorial de mônadas. Aí, quem sabe, deixo de ser um neófito!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com2tag:blogger.com,1999:blog-8203444459901609108.post-61916437663747665422009-07-02T11:36:00.010-03:002009-07-06T07:43:46.291-03:00ICFP2009 ContestMais um ICFP, mais uma tentativa, mais uma vez em Haskell... Só que desta vez não foi uma tentativa tão frustrada quanto <a href="http://rafaelgcpp.blogspot.com/2008/07/veni-vidi-voltei.html">a do ano passado</a>! Diversos motivos me levam a crer isso:<br /><br /><ol><li>A linguagem Haskell deixou de ser uma barreira: as mônadas não são mais tão complexas para mim. Começo a entender por que Simon Peyton-Jones considera o nome <span style="font-style: italic;">warm, fuzzy thing</span> mais apropriado<br /></li><li>Apesar de mais complexa (ninguém discorda que mecânica orbital é difícil) , os arquivos de entradas eram mais tratáveis, e não envolviam conexões com rede, comunicação entre processos, e outras coisas que nem são tão funcionais assim</li><li>Tá certo que apanhei muito na elaboração da máquina virtual, mas muito mais por não consultar o HackageDB do que por não saber a linguagem. A quantidade de bibliotecas lá é consideravelmente grande, cobrindo diversas áreas de conhecimento</li></ol>Não concluí por falta de tempo, e por ter tropeçado em algumas bobagens. Acho que a pior delas foi ter me atrapalhado na leitura do arquivo usando a biblioteca Data.Binary, pois não percebi que ela tinha algumas funções especializadas nos tipos nativos do Haskell e outras destinadas a leitura de tipos genéricos como o word32le (inteiro sem sinal de 32 bits em <span style="font-style: italic;">little-endian</span>). Pra completar, depois que descobri essas funções acabei escrevendo uma função que lia um word64le e o tratava como número de ponto flutuante IEEE-754. Só que o tratamento de números de ponto flutuante estava em outra biblioteca, a Data.Binary.IEEE754, que só descobri na manhã de segunda-feira. Com todos os tropeços, só consegui concluir a máquina virtual na noite de quarta-feira, dois dias depois do prazo.<br /><br />Pelo lado positivo, eu concluí a máquina virtual! Além disso, usei a mônada RWS sem grandes dificuldades, e meu código não tem <span style="font-style: italic;">space leak</span> pois consegui que todas as rotinas iterativas fossem <span style="font-style: italic;">tail-recursive</span>.<br /><br />Semana que vem devo começar a tentar resolver os problemas. Coloquei como meta terminar as tarefas do concurso até o final deste ano, e sinto que vou conseguir bem antes disso.Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com2tag:blogger.com,1999:blog-8203444459901609108.post-88297350624555822412009-05-13T22:46:00.003-03:002009-05-14T08:13:31.735-03:00EcoNerd ou NerdSport??Ontem peguei meu carro novo: uma EcoSport. O carro é muito bacana, e é muito legal dirigir olhando por cima do engarrafamento. Aliás, com o câmbio automático, nem sinto o engarrafamento!<br /><br />O que me chamou atenção na entrega do carro, e me motivou a escrever este post, foi o kit de manuais, mais especificamente o do radio MyConnection: ele tem a mesma espessura do manual do proprietário do veículo!<br /><br />Nesse manual, encontramos informações muito interessantes, que qualquer pessoa sabe, como:<br /><br /><ul><li>O dispositivo conectado ao MyConnection deve suportar protocolo USB 2.0 Full Speed, classe de dispositivo de armazenamento em disco, suportar o conjunto primário de comandos SCSI-3 e modo de transferência de massa (Bulk transfer)</li><li>Suporte a sistemas de arquivo FAT 12/16/32</li><li>Os CDs devem estar formatados como ISO9660 níveis 1 ou 2, podendo incluir extensão Joliet.</li><li>Os arquivos MP3 podem ser padrão MPEG 1, 2 ou 2.3 em nível 3 com taxa de 8 a 320kbps e frequencias de amostragem de 8, 11.025, 12, 16, 22.05, 24, 32, 44.1 ou 48 kHz</li></ul>Como é fácil notar, qualquer <span style="text-decoration: line-through;">nerd</span> pessoa conseque operar esse rádio com facilidade.<br /><br />A Paty já me informou que quem pilota o rádio sou eu...Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-44052536814830774752009-02-09T20:56:00.002-02:002009-02-09T21:13:29.655-02:00Joule Thief<div style="MARGIN: 0px auto 10px; TEXT-ALIGN: center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidavJQrk1U8c18wkOoFGYaGu6fctoB8Z9c7p4X7_2QPL8mCgkcxot2ckniQaBquaxAxty9jPquBwq_AoKCVSNcE2a3D9qx2-loa94ICzrhdPXwYCTNOioJTB7ASEdUybnMGhNl_J9z_q0/s1600-h/CIMG1241.JPG"><img alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidavJQrk1U8c18wkOoFGYaGu6fctoB8Z9c7p4X7_2QPL8mCgkcxot2ckniQaBquaxAxty9jPquBwq_AoKCVSNcE2a3D9qx2-loa94ICzrhdPXwYCTNOioJTB7ASEdUybnMGhNl_J9z_q0/s400/CIMG1241.JPG" border="0" /></a> </div><p><br />Havia visto esse circuito há um tempo no instructables.org e fiquei curioso em entender como ele funcionava. Esse final de semana acabei montando e testando.</p><p>Há muita controvérsia na Internet sobre o seu funcionamento. Uns dizem que ele é um oscilador de relaxação, enquanto outros dizem que se trata de um oscilador de bloqueio ou oscilador Hartley. Muita especulação inclusive sobre o valor da indutância do transformador (ou seria uma bobina com <em>tap </em>central?).</p><p>O circuito, em carga, é, na verdade, um oscilador astável, controlado por um transformador de pulso entre o coletor e a base. O lado do coletor opera como um conversor <em>boost</em> em modo <em>fly-back</em> de corrente descontínua.</p><p>Sabendo disso, fiz algumas melhorias no circuito básico:</p><ol><li>Coloquei um retificador, feito com diodo <em>schottky</em> e um capacitor, para melhorar o <em>ripple</em>.</li><li>Coloquei um capacitor de 1n em paralelo com o resistor da base, para melhorar o tempo de transição do transistor.</li></ol><p>O resultado pode ser visto abaixo, com 4 LEDs em série sendo iluminados por uma única pilha NiMH (que estava descarregada!). Muito legal!!</p><div style="CLEAR: both; TEXT-ALIGN: center"><a href="http://picasa.google.com/blogger/" target="ext"><img style="BORDER-RIGHT: 0px; PADDING-RIGHT: 0px; BORDER-TOP: 0px; PADDING-LEFT: 0px; BACKGROUND: 0% 50%; PADDING-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: 0px; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial" alt="Posted by Picasa" src="http://photos1.blogger.com/pbp.gif" align="middle" border="0" /></a></div><br /><br /><div style="MARGIN: 0px auto 10px; TEXT-ALIGN: center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4NBckEUAy_bXmVLPNrFos08z7O-imWU6GfYQQxoNQG5BduUpAe5-9CsTpPvMuO9UGLCezSfV7lBPMX0uXEqR9arlbWBpfSzrip5Pkhfi5ktpDQmCgPtEfyZPBp7YigNhOyL8GTSlYt0M/s1600-h/CIMG1243.JPG"><img alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4NBckEUAy_bXmVLPNrFos08z7O-imWU6GfYQQxoNQG5BduUpAe5-9CsTpPvMuO9UGLCezSfV7lBPMX0uXEqR9arlbWBpfSzrip5Pkhfi5ktpDQmCgPtEfyZPBp7YigNhOyL8GTSlYt0M/s400/CIMG1243.JPG" border="0" /></a> </div><div style="CLEAR: both; TEXT-ALIGN: center"><a href="http://picasa.google.com/blogger/" target="ext"><img style="BORDER-RIGHT: 0px; PADDING-RIGHT: 0px; BORDER-TOP: 0px; PADDING-LEFT: 0px; BACKGROUND: 0% 50%; PADDING-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-TOP: 0px; BORDER-BOTTOM: 0px; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial" alt="Posted by Picasa" src="http://photos1.blogger.com/pbp.gif" align="middle" border="0" /></a></div>Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com1tag:blogger.com,1999:blog-8203444459901609108.post-15414765339768856632009-02-09T08:25:00.004-02:002009-02-09T08:44:58.702-02:00Decomposição LU funcionalSemana passada escrevi um código para a decomposição LU puramente funcional.<br /><br /><span style=";font-family:courier new;font-size:85%;" ><br /><pre><br />{-<br /> This program is free software: you can redistribute it and/or modify<br /> it under the terms of the GNU Lesser General Public License as published by<br /> the Free Software Foundation, either version 3 of the License, or<br /> (at your option) any later version.<br /><br /> This program is distributed in the hope that it will be useful,<br /> but WITHOUT ANY WARRANTY; without even the implied warranty of<br /> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br /> GNU General Public License for more details.<br /><br /> You should have received a copy of the GNU General Public License<br />.<br /><br />-}<br /><br />import Data.Array.IArray<br /><br />type Dim=(Int,Int)<br /> <br />lu::Array Dim Double -> (Array Dim Double,Array Dim Double)<br />lu a =(aa l,aa u)<br /> where<br /> (l,u)=lu' a [] []<br /> aa = accumArray (+) 0 (bounds a)<br /> lu'::(Floating e) => Array Dim e<br /> -> [(Dim,e)]<br /> -> [(Dim,e)]<br /> -> ([(Dim,e)],[(Dim,e)])<br /> lu' a l u=if (ui==li)<br /> then ( ((ui,uj),1.0):l,((ui,uj),a!(<wbr>ui,uj)):u)<br /> else (lu' an (l++ln) (u++un))<br /> where<br /> k=li<br /> ((li,lj),(ui,uj))=bounds a<br /> lik i=(a!(i,k)/a!(k,k))<br /> un=[((k,j),a!(k,j)) | j<-[lj..uj]]<br /> ln=((lj,lj),1.0):[((i,k),lik i) | i <- [li+1..ui] ] <br /> an=array ((li+1,lj+1),(ui,uj))<br /> [((i,j),e_an i j) | i <- [li+1..ui] , j <- [lj+1..uj] ]<br /> e_an i j=a!(i,j)-(lik i)*a!(k,j)<br /></pre><br /></span><br /><br />Esse código usa a forma KIJ (ver Matrix Computations, de Gene Golub), que atualiza todos os valores de forma imediata. Essa forma permite a implemntação recursiva que eu usei, e permite que seja implementado o pivotamento parcial.<br /><br />Um cara chamando Matt implementou algo semelhante em uma biblioteca de DSP (<a href="http://haskelldsp.sourceforge.net/">Matt's Haskell DSP Library</a>), mas ele usou uma versão de produtos internos (IJK) que torna o pivotamento mais complicado. De qualquer forma, vale a pena dar uma olhada, pois é um dos códigos mais elegantes que já vi em Haskell...<br /><br /><span style=";font-family:courier new;font-size:85%;" ><br /><pre><br />lu a = a'<br /> where <br /> a' = array bnds [ ((i,j), luij i j) | (i,j) <- range bnds ] <br /> luij i j | i>j = (a!(i,j) - sum [ a'!(i,k) * a'!(k,j) | k <- [1 ..(j-1)] ]) / a'!(j,j) <br /> | i<=j = a!(i,j) - sum [ a'!(i,k) * a'!(k,j) | k <- [1 ..(i-1)]]<br /> bnds = bounds a </pre><br /></span>Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-26410583423930122952009-01-07T09:13:00.002-02:002009-01-07T09:19:53.188-02:00A bola da vezA bola da vez é o OCaml. Estou um pouco cansado do Haskell, e o Erlang, apesar de muito legal, é mais interessante para sistemas distribuídos.<br /><br />Enquanto lia o livro do Chris Okasaki, me deparei com o ML e vi que o OCaml não é tão complicado como pensei. Por enquanto, a única deficiência que vi na linguagem é a falta de polimorfismo para os operadores mais básicos, como os aritméticos, mas que tem como ser contornada.<br /><br />Vamos ver aonde chego! Quem sabe acabo no Lisp?? (Já andei paquerando o Scheme!)Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com1tag:blogger.com,1999:blog-8203444459901609108.post-32501573433935361992008-09-18T20:22:00.003-03:002009-07-06T07:44:43.209-03:00Notícias do frontTem um tempo que não coloco nada nesse blog, então aí vão várias notícias de uma só vez:<br /><br /><ol><li>Haskell é sem dúvida muito legal, mas a <span style="font-style: italic;">lazy evaluation</span> pode pregar algumas peças. Implementei o "decodificador de DNA" do ICFP2007, e tenho certeza que o processamento está errado pois nem sempre uma das funções é avaliada. Tentei colocar <span style="font-style: italic;">bang patterns</span> e o resultado foi bem diferente, condizente com essa suposição. Tenho para mim que a implementação "correta" deveria utilizar mônadas transformadoras de estado, mas ainda tenho que estudá-las para entender como funcionam.</li><li>Recentemente comprei quatro livros, mas o que eu mais gostei foi o "Purely Functional Data Structures", por Chris Okasaki. Alem desses, comprei um de algoritmos (para completar a biblioteca!), um sobre Haskell e um sobre o Erlang.</li><li>Erlang continua a me chamar a atenção... Acho que vou brincar um pouco com ele, para relaxar um pouco do Haskell.</li></ol>Por hoje é só pessoal!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com1tag:blogger.com,1999:blog-8203444459901609108.post-16498949311728702002008-07-23T11:04:00.005-03:002009-07-02T12:41:43.481-03:00Veni, Vidi, Voltei...Esse ano comecei a trabalhar no problema do <a href="http://www.icfpcontest.org/">ICFP </a>contest, mas acabei jogando a toalha. O problema era bastante simples, e tinhamos 72 horas para terminar. Um colega de trabalho até começou a me ajudar, pois havia decidido fazer em C++.<br /><br />Ainda não tenho proficiência suficiente em Haskell, e ele também não conhecia Python para poder me ajudar. O problema é que, em C++, levei quase 3 horas só para implementar o <span style="font-style: italic;">I/O</span> via rede, e estimava levar mais umas horas tratando a entrada para quebrar as strings. Definitivamente C++ não serve para o <span style="font-style: italic;">lightining round</span>, a menos que você tenha um <span style="font-style: italic;">framework</span> para isso. Usando Python ou Haskell, há dezenas de bibliotecas prontas para essas funções.<br /><br />Tudo bem... Estou estudando Haskell e acho que ano que vem vou poder participar melhor. A linguagem tem me surpreendido, e sua curva de aprendizagem não é tão lenta quanto eu imaginava. Ainda vou olhar o Erlang e o OCaml, mas o Haskell ganhou minha atenção!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0tag:blogger.com,1999:blog-8203444459901609108.post-24677864457969447542008-07-10T07:41:00.004-03:002008-07-10T07:47:34.688-03:00É amanhã!Amanhã, as 16:00 de Brasília começa o <a href="http://www.icfpcontest.org/">ICFP Programming Contest</a>. Esse ano limitaram as equipes à 5 membros, o que parece indicar uma tarefa menos trabalhosa. Gostaria de tentar fazer a tarefa em Haskell, mas como ainda não peguei o jeito da linguagem, devo acabar no C++ mesmo. Dependendo da tarefa, pode ser que use até Python mesmo...<br />Devo comprar 2 CD-RW para gravar duas imagens do LiveCD, pois pretendo usar meu micro e o da Paty na tarefa. No meu micro devo estar com o Ubuntu, e com o LiveCD no da Paty mapeando um diretório via NFS. Espero que dê certo!Rafael Gustavohttp://www.blogger.com/profile/04509485078505005220noreply@blogger.com0