<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Grifo &#187; code</title>
	<atom:link href="http://www.grifotecnologia.com.br/blog/tag/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.grifotecnologia.com.br/blog</link>
	<description>Desenvolvimento client-side com inteligência.</description>
	<lastBuildDate>Mon, 31 Oct 2011 21:23:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Solucionando o Code Golf + Maratona IG com Javascript</title>
		<link>http://www.grifotecnologia.com.br/blog/javascript/solucionando-o-code-golf-maratona-ig-com-javascript/</link>
		<comments>http://www.grifotecnologia.com.br/blog/javascript/solucionando-o-code-golf-maratona-ig-com-javascript/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 21:21:53 +0000</pubDate>
		<dc:creator>Ricardo Tomasi</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[CodeGolf]]></category>
		<category><![CDATA[FISL]]></category>
		<category><![CDATA[golf]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.grifotecnologia.com.br/blog/?p=139</guid>
		<description><![CDATA[Semana passada Porto Alegre recebeu o FISL, que reuniu mais de 8 mil pessoas no campus da PUC. Estivemos lá pra conferir as palestras envolvendo HTML5, CSS, Javascript, acessibilidade e novas tecnologias/projetos. No meio tempo entre trabalho e palestras resolvi participar do Code Golf do IG: resolver os 5 problemas dados com o menor código]]></description>
			<content:encoded><![CDATA[<p>Semana passada Porto Alegre recebeu o <a href="http://fisl.softwarelivre.org/" target="_blank"><abbr title="Fórum Internacional de Software Livre">FISL</abbr></a>, que reuniu mais de 8 mil pessoas no campus da PUC. Estivemos lá pra conferir as palestras envolvendo HTML5, CSS, Javascript, acessibilidade e novas tecnologias/projetos.</p>
<p>No meio tempo entre trabalho e palestras resolvi participar do <a title="FAQ do Code Golf" href="http://ignofisl.ig.com.br/2010/07/21/faq-do-code-golf/" target="_blank">Code Golf</a> do IG: resolver <a href="http://ignofisl.ig.com.br/2010/07/22/problemas-do-code-golf/" target="_blank">os 5 problemas</a> dados com o menor código possível. O ganhador de cada categoria levou um iPod touch. Já que Javascript não era um opção, foi PHP mesmo. Depois de uma disputa acirrada e de ter ficado em segundo lugar até meia hora antes do final, a <a href="http://ignofisl.ig.com.br/2010/07/23/ranking-code-golf/" target="_blank">pontuação</a> foi atualizada e acabei terminando em primeiro lugar :]</p>
<p>Neste post vamos ver como ficaram as soluções em <strong>PHP</strong>, e também em <strong>Javascript. </strong>Pra isso vamos utilizar o <a href="http://www.jsdb.org/" target="_blank">JSDB</a>, que interpreta Javascript usando a engine <a href="http://www.mozilla.org/js/spidermonkey/" target="_blank">SpiderMonkey da Mozilla</a> e nos dá acesso ao sistema de arquivos, DBs e web. Roda em Linux, Mac e Windows e não exige instalação, é só baixar, descompactar e começar a usar. Vamos resolver também o problema da <a href="http://ignofisl.ig.com.br/2010/07/22/desafio-maratona-ig/" target="_blank">Maratona IG</a> em menos de 15 minutos usando Javascript.</p>
<div style="width: 30%; padding: 8px; font-size: 0.9em; background: none repeat scroll 0% 0% #efefef; border: 1px solid #eeeeee;">S<em>oluções </em><a href="#q1"><em>1</em></a><em>, </em><a href="#q2"><em>2</em></a><em>, </em><a href="#q3"><em>3</em></a><em>, </em><a href="#q4"><em>4</em></a><em> e </em><em><a href="#q5">5</a> do Code Golf</em><br />
<a href="#maratona"><em>Solução da Maratona </em></a></div>
<p>Vamos ao código:</p>
<h3><strong>Questão 1</strong></h3>
<p><strong>Dado o número de iterações exibir a sequência de Fibonacci até aquela iteração</strong></p>
<p style="padding-left: 30px;"><strong><span style="color: #3366ff;"><span style="color: #3366ff;">entrada: <span style="font-weight: normal;">6</span></span><br />
<span style="color: #ff0000;">saida: <span style="font-weight: normal;">1, 1, 2, 3, 5, 8</span></span></span></strong></p>
<h4><span style="font-weight: normal;">PHP</span></h4>
<p>Esse foi o código final (pra economizar espaço, colocamos tudo dentro de um <em>for</em> loop):</p>
<pre class="brush: php; light: true; wrap-lines: false;">

&lt;?php for($a=$c=0,$b=1;$c&lt;$argv[1];
$x=$a,$a=$b,$b+=$x)echo(!$c++?'':', ').$b;
</pre>
<p>Começamos com 0 e 1 e somamos o último com o anterior até atingir o número de iterações. Em PHP é impossível fazer isso sem utilizar uma terceira variável. A solução mais simples em Javascript é utilizar um array:</p>
<h4><span style="font-weight: normal;">Javascript</span></h4>
<pre class="brush: jscript;">
var
	a = 0,
	b = 1,
	i = 0,
	numeros = [1];
while(++i &lt; jsArguments[0])
{
	numeros.push( b=a+(a=b) );
	// isto é possível porque a variável &quot;a&quot; à esquerda
	// da expressão (a=b) continua com o valor antigo,
 	// o que não acontece no PHP
}
writeln(o);
// $ ./jsdb q1.js 6 &gt; 1, 1, 2, 3, 5, 8
</pre>
<p>Deixando o array &#8211; e a legibilidade do código &#8211; de lado, o resultado final é um pouco mais compacto:</p>
<pre class="brush: jscript; light: true; wrap-lines: false;">
for(a=c=b=1;c++&lt;=jsArguments[0];print((b=a+(a=b))-a+' '));
</pre>
<p class="divider">
<h3 id="q2"><strong>Questão 2</strong></h3>
<p><strong>Dado uma frase retornar se é um palíndrome ou não e listar os caracteres em ordem decrescente de número de incidências na mesma</strong></p>
<p style="padding-left: 30px;"><strong><span style="color: #3366ff;">entrada: <span style="font-weight: normal;">“A mala nada na lama”</span></span><br />
<span style="color: #ff0000;">saída:<br />
<span style="font-weight: normal;"> Palíndrome<br />
8 a<br />
2 m<br />
2 n<br />
2 l<br />
1 d</span></span></strong></p>
<h4><span style="font-weight: normal;">PHP</span></h4>
<p>As funções <em>count_chars</em> e <em>strrev</em> tornam o trabalho fácil:</p>
<pre class="brush: php; light: true; wrap-lines: false;">
&lt;?php $s=str_replace(' ','',$argv[1]);
echo($s!=strrev($s)?&quot;Não é &quot;:&quot;&quot;).&quot;Palíndrome&quot;;$c=count_chars($s,1);
arsort($c);foreach($c as $i=&amp;gt;$v)echo&quot;\n$v &quot;.chr($i);
</pre>
<h4><span style="font-weight: normal;">Javascript</span></h4>
<p>Já em Javascript a coisa é mais complicada. O método <em>reverse()</em> só existe para arrays. Temos que fazer a inversão da string e a contagem por nossa conta:</p>
<pre class="brush: jscript;">
// removemos espaços e outros caracteres da string
var str=jsArguments[0].toLowerCase().replace(/\W/g,'');

// verificamos se o inverso é igual
println( (str!=str.split('').reverse().join('') ? &quot;Não é &quot; : &quot;&quot;)+&quot;Palíndrome&quot;);

// contamos os caracteres usando um array
var chars = [];
for(var i in str){ // não façam isso em casa
	var key = str[i];
	chars[key] = chars[key]+1 || 1;
}

// exibimos a contagem pra cada letra
for(var n in chars){
	println(chars[n]+&quot; &quot;+n);
}
</pre>
<p>E depois transformamos de novo isso tudo em uma linha ininteligível:</p>
<pre class="brush: jscript; light: true; wrap-lines: false;">
s=jsArguments[0].toLowerCase().replace(/\W/g,'');
println((s!=s.split('').reverse().join('')?&quot;Não é &quot;:&quot;&quot;)+&quot;Palíndrome&quot;);
c=[];for(i in s){k=s[i];c[k]=c[k]+1||1;}for(n in c)println(c[n]+&quot; &quot;+n);
</pre>
<p class="divider">
<h3 id="q3"><strong>Questão 3</strong></h3>
<p><strong>Dado um endereço IP e uma máscara de rede, retornar o endereço de broadcast e a conotação CIDR da rede</strong></p>
<p style="padding-left: 30px;"><strong><span style="color: #3366ff;">entrada:<span style="font-weight: normal;"> 201.94.10.19 255.255.255.0</span></span><br />
<span style="color: #ff0000;">saída: <span style="font-weight: normal;">201.94.10.255 /24</span></span></strong></p>
<p>Essa é assustadora. Mas depois de <a title="Wikipedia: Broadcast Address" href="http://en.wikipedia.org/wiki/Broadcast_address" target="_blank">consultar a Wikipedia</a> sobre o assunto se descobre que a matemática é simples, e que <a title="Wikipedia: Classless Inter-Domain Routing" href="http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing" target="_blank">CIDR</a> é uma gambiarra que inventaram pra usar um mesmo IP em mais de uma máquina, em redes internas. Temos que fazer o seguinte:</p>
<ol>
<li>Descobrir o complemento de cada pedaço da subnet mask (255.255.255.0), no caso do exemplo 0.0.0.255</li>
<li>Aplicar o operador <a title="Wikipedia: Bitwise Operators" href="http://en.wikipedia.org/wiki/Bitwise_operation#OR" target="_blank">bitwise OR</a> à cada parte do IP e o complemento da máscara (ex: 255|0)</li>
</ol>
<p>O resultado disso é o endereço de broadcast. Depois, precisamos transformar o IP resultante em binário, e contar quantos bits &#8220;1&#8243; ele contém. Essa é a <em>conotação CIDR</em>. Vamos ao código:</p>
<h4><span style="font-weight: normal;">PHP</span></h4>
<pre class="brush: php; light: true; wrap-lines: false;">
&lt;?php $b='';$c=0;$m=explode(&quot;.&quot;,$argv[2]);
foreach(explode('.',$argv[1]) as $k=&gt;$v){$b.=($k?'.':'').($v|255-$m[$k]);
$c+=substr_count(decbin($m[$k]),1);}echo &quot;$b /$c&quot;;
</pre>
<h4><span style="font-weight: normal;">Javascript</span></h4>
<pre class="brush: jscript;">
var
	cidr = 0,
	ip = jsArguments[0].split('.'),
	mask = jsArguments[1].split('.');

// encontramos o broadcast address
// usando a fórmula descrita
var broadcast = ip.map(function(val,key){
	return val | (255-mask[key]);
}).join('.');

// e calculamos o CIDR por partes
mask.forEach(function(val){
	// primeiro convertemos o valor para Number
	// e depois para string usando base 2 (binário)
	// ex: 252 &gt; 11111100
	// e então contamos quantos &quot;1&quot;s na string
	cidr += (+val).toString(2).split('1').length-1;
});

//saida
writeln(broadcast+&quot; /&quot;+cidr);
</pre>
<p>O resultado final é muito mais longo do que em PHP pelas várias chamadas de função, mas ainda pode ser reduzido:</p>
<pre class="brush: jscript; light: true;">
c=0;i=jsArguments[0].split('.');m=jsArguments[1].split('.');
b=i.map(function(v,k){return v|(255-m[k])}).join('.');
m.forEach(function(v){c+=(+v).toString(2).split('1').length-1});
writeln(broadcast+&quot; /&quot;+cidr);
</pre>
<h3 id="q4"><strong>Questão 4</strong></h3>
<p><strong>Dados dois números naturais m e n e duas sequências ordenadas com m e n números inteiros, obter uma única sequência ordenada contendo todos os elementos das sequências originais sem repetição</strong></p>
<p><strong><span style="color: #3366ff;">entrada: <span style="font-weight: normal;">1,5,6,10,12  2,5,9,29</span></span></strong></p>
<p><span style="color: #ff0000;"><strong>saída</strong>: 1, 2, 5, 6, 9, 10, 12, 29</span></p>
<p>Mais uma vez as funções nativas do PHP fazem todo o trabalho. Em Javascript é mais divertido.</p>
<h4><span style="font-weight: normal;">PHP</span></h4>
<pre class="brush: php; light: true;">
&lt;?php $a=array_unique(explode(',',$argv[1].','.$argv[2]));
sort($a);echo implode(',',$a);
</pre>
<h4><span style="font-weight: normal;">Javascript</span></h4>
<pre class="brush: jscript;">
var
	resultado = [],
	a1 = jsArguments[0].split(',')
	a2 = jsArguments[1].split(','),
	arr = a1.concat(a2);

// inserir valor em unique somente se
// ainda não existe valor igual no array
arr.map(function(val){
	if (resultado.indexOf(+val)&lt;0)
		resultado.push(+val);
})
// pôr em ordem numérica (asc)
resultado = resultado.sort(function(a,b){
	return a&gt;b;
});

writeln(unique);
// saída:
// $ ./jsdb q4.js 1,4,2,5,6 1,2,6,3
// 1, 2, 3, 4, 5, 6
</pre>
<p>Dá pra pular algumas etapas pra encolher o código:</p>
<pre class="brush: jscript; light: true; wrap-lines: false;">
u=[];a=jsArguments.join().split(',');
a.map(function(v){u.indexOf(+v)&lt;0&amp;&amp;u.push(+v)});
u=u.sort(function(a,b){return a&gt;b});writeln(u);
</pre>
<h3 id="q3"><strong>Questão 5</strong></h3>
<p>Escreva uma função que recebe uma matriz de caracteres 8×8 representando um tabuleiro de xadrez e calcula o valor total das peças do jogo. Espaços vazios do tabuleiro são codificados como casas com ‘v’ e têm valor 0 (zero). O valor das demais peças é dado de acordo com a tabela: Peão (p): 1, Cavalo (c): 3, Bispo (b): 3, Torre (t): 5, Rainha (a): 10, Rei (r): 50, Vazio: (v)<br />
<span style="color: #3366ff;">entrada: <br />tcbarbct<br />
pppppppp<br />
vvvvvvvv<br />
vvvvvvvv<br />
vvvvvvvv<br />
vvvvvvvv<br />
pppppppp<br />
tcbarbct</span></p>
<p><span style="color: #ff0000;"><strong>saída</strong>: 180</span></p>
<p>Não se preocupe com a idéia do tabuleiro, só precisamos traduzir o valor de cada caractere válido na string e ignorar o resto. Solução simples: fazer um loop com todos os caracteres e usar como chave pra buscar no array de valores. Em PHP nem isso precisa, a função <em>count_chars() </em>já faz a contagem:</h3>
<h3>PHP</h3>
<pre class="brush: php;">&lt;?php $s=0;$v=Array('p'=&gt;1,'c'=&gt;3,'b'=&gt;3,'t'=&gt;5,'a'=&gt;10,'r'=&gt;50,'v'=&gt;0);
foreach(count_chars(preg_replace('/\W/','',$argv[1]),1) as $c=&gt;$n){
$s+=$v[chr($c)]*$n;};echo$s;
</pre>
<h3>Javascript</h3>
<pre class="brush: jscript;">
var
	valores = { p:1, c:3, b:3, t:5, a:10, r:50 },
	// remover todos os caractere não alfanuméricos
	pecas = jsArguments[0].replace(/\W/g,''),
	pontos = 0;

for(var i in pecas){
	pontos += valores[ pecas[i] ] || 0;
}
writeln(pontos);
</pre>
<p>E a versão condensada, usando o método <em>replace()</em> para o loop:</p>
<pre class="brush: jscript; light: true; wrap-lines: false;">
v={p:1,c:3,b:3,t:5,a:10,r:50};p=jsArguments[c=0].replace(/\w/g,function(a){c+=v[a]||0});writeln(c);
</pre>
<p class="divider">
<h3 id="maratona"><strong>Maratona IG</strong></h3>
<p>O <a href="http://ignofisl.ig.com.br/2010/07/22/desafio-maratona-ig/" target="_blank">desafio da Maratona</a> era o seguinte: a partir de um arquivo texto de 57Mb contendo tweets em JSON, fazer a contagem dos tweets contendo sentimentos &#8220;positivos&#8221; ou &#8220;negativos&#8221;. A contagem com a menor margem de erro vence. O problema maior aqui é deduzir qual o tipo de filtro utilizado como referência.</p>
<p>Uma olhada rápida no arquivo de dados nos mostra que as mensagens variam entre os termos <em>feliz/amo/adoro</em> e <em>triste/odeio</em>. Isso é tudo que precisamos saber, agora basta uma expressão regular. Como a chance de uma das palavras-chave aparecer em qualquer outro lugar do objeto é praticamente nula, nem precisamos interpretar o JSON.</p>
<pre class="brush: jscript;">
var
	positivo = /feliz|gosto|gostei|amo|amei|adoro|adorei/i,
	negativo = /triste|odeio|odiei/i,
	p = 0,
	n = 0,
	line, tweets;

// carregamos o arquivo como Stream
tweets = new Stream(jsArguments[0], 'rt');
// e lemos linha por linha
while (line = tweets.readLine())
{
	if(negativo.test(line))
		n++;
	else if(positivo.test(line))
		p++;
}

writeln(&quot;Tweets Positivos:&quot;+p);
writeln(&quot;Tweets Negativos:&quot;+n);
writeln(&quot;Tweets Negativos:&quot;+n);
</pre>
<p>E temos o resultado:</p>
<p style="padding-left: 30px;">Tweets Positivos: 35507<br />
Tweets Negativos: 4307</p>
<p>Pelo <a href="http://ignofisl.ig.com.br/2010/07/24/resultado-da-maratona/" target="_blank">resultado da maratona</a> podemos calcular os números ideais:</p>
<p style="padding-left: 30px;">Positivos: 35322<br />
Negativos: 4316</p>
<p>A margem de erro do código acima é de 0.005% e 0.003% (positivos/negativos), e o código foi desenvolvido em menos de 15 minutos. A execução também é muito rápida, leva pouco mais de 5 segundos, e isso com SpiderMonkey que não é das engines JS mais rápidas.</p>
<p>O prêmio que a dupla vencedora levou: <strong>dois iPads.</strong></p>
<p><strong><span style="font-weight: normal;">Encontrou algum bug no código ou sabe de uma maneira melhor? Também acha que javascript deve ser uma opção nesse tipo de competição? Deixe um comentário abaixo.</span></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.grifotecnologia.com.br/blog/javascript/solucionando-o-code-golf-maratona-ig-com-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

