<?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>Luciano&#039;s webpage &#187; python</title>
	<atom:link href="http://www.lucianobello.com.ar/category/geek/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lucianobello.com.ar</link>
	<description>Luciano Bello - My personal webpage</description>
	<lastBuildDate>Thu, 19 Jan 2012 14:37:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>alchemy: jugando a ser dios (ó cómo hacer trampa con Python)</title>
		<link>http://www.lucianobello.com.ar/post/jugando-a-ser-dios/</link>
		<comments>http://www.lucianobello.com.ar/post/jugando-a-ser-dios/#comments</comments>
		<pubDate>Sat, 04 Jun 2011 15:05:54 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[geek]]></category>
		<category><![CDATA[procrastination]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1597</guid>
		<description><![CDATA[Creo que esto de usar Python para hacer trampa se me está volviendo vicio. Es que hay veces que las cosas te piden a gritos que tomes un atajo. Y esto fue lo que me pasó esta semana. Primero un poco de contexto. La semana pasada conocí, a través de Microsiervos, un juego llamado Alchemy. [...]]]></description>
			<content:encoded><![CDATA[<p>Creo que esto de usar Python para hacer trampa <a href="/post/how-to-hack-a-h4ckc0nt3st/">se me está volviendo vicio</a>. Es que hay veces que las cosas te piden a gritos que tomes un atajo. Y esto fue lo que me pasó esta semana.</p>
<p>Primero un poco de contexto. La semana pasada conocí, a través de <a href="http://juegos.microsiervos.com/ingenio/alchemy.html">Microsiervos</a>, un juego llamado <a href="http://alchemy.l8r.pl/">Alchemy</a>. Consiste en combinar los cuatro elementos clásicos griegos (tierra, agua, fuego y aire) para generar nuevos elementos y a su vez, otros con estos.<br />
<img src="http://juegos.microsiervos.com/images/alchemy.jpg" alt="" /><br />
Se los comenté a varios conocidos y se engancharon. El tope (al menos de momento) es 200 elementos y, como se trata de un juego muy divertido y adictivo, en un tiempo razonable se puede superar los 100. Los elementos son cada vez más complejos, incluso uno se empieza a obsesionar con la idea de crear <em>human</em> :P</p>
<p>El problema llega cuando uno se estanca y la tentación de hacer trampa se hace inevitable.</p>
<p><strong>Atención: a partir de este momento el post es una especie de <a href="https://secure.wikimedia.org/wikipedia/es/wiki/Spoiler">spoiler</a> en donde se explica cómo llegar al final del juego sin <em>jugarlo</em>. Si estás jugándolo y lo disfrutas, deja de leer inmediatamente.</strong></p>
<p>Con mirar rápidamente el código de la página, uno puede descubrir cómo funciona. Parece haber un <a href="http://alchemy.l8r.pl/library.xml">archivo en donde se definen las relaciones de los elementos por un número identificador</a> y <a href="http://alchemy.l8r.pl/en_us.xml">otro donde está se mapean estos identificadores a nombres</a>. El siguiente script me ayudó a organizar la información muy rápidamente:<br />
<div id="wpshdo_1" class="wp-synhighlighter-outer"><div id="wpshdt_1" class="wp-synhighlighter-collapsed"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_1"></a><a id="wpshat_1" class="wp-synhighlighter-title" href="#codesyntax_1"  onClick="javascript:wpsh_toggleBlock(1)" title="Click to show/hide code block">alchemy.py</a></td><td align="right"><a href="#codesyntax_1" onClick="javascript:wpsh_code(1)" title="Show code only"><img border="0" style="border: 0 none" src="http://www.lucianobello.com.ar/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_1" onClick="javascript:wpsh_print(1)" title="Print code"><img border="0" style="border: 0 none" src="http://www.lucianobello.com.ar/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_1" class="wp-synhighlighter-inner" style="display: none;"><pre class="python" style="font-family:monospace;"><ol><li class="li1"><div class="de1"><span class="co1">#!/usr/bin/python</span></div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">urllib</span></div></li><li class="li1"><div class="de1"><span class="kw1">from</span> <span class="kw3">xml</span>.<span class="me1">dom</span> <span class="kw1">import</span> minidom</div></li><li class="li1"><div class="de1"><span class="kw1">from</span> <span class="kw3">optparse</span> <span class="kw1">import</span> OptionParser,OptionValueError</div></li><li class="li1"><div class="de1">library_xml = <span class="kw3">urllib</span>.<span class="me1">urlopen</span><span class="br0">&#40;</span><span class="st0">&quot;http://alchemy.l8r.pl/library.xml&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">relations = minidom.<span class="me1">parse</span><span class="br0">&#40;</span>library_xml<span class="br0">&#41;</span>.<span class="me1">documentElement</span>.<span class="me1">getElementsByTagName</span><span class="br0">&#40;</span><span class="st0">'entry'</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">name_xml = <span class="kw3">urllib</span>.<span class="me1">urlopen</span><span class="br0">&#40;</span><span class="st0">&quot;http://alchemy.l8r.pl/en_us.xml&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">names = minidom.<span class="me1">parse</span><span class="br0">&#40;</span>name_xml<span class="br0">&#41;</span>.<span class="me1">documentElement</span>.<span class="me1">getElementsByTagName</span><span class="br0">&#40;</span><span class="st0">'library'</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">getElementsByTagName</span><span class="br0">&#40;</span><span class="st0">'entry'</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">elementsID=<span class="kw2">dict</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">elementsNAME=<span class="kw2">dict</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw1">class</span> Element<span class="br0">&#40;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">    <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>,<span class="kw2">id</span>,name<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">        <span class="kw2">self</span>.<span class="kw2">id</span>=<span class="kw2">int</span><span class="br0">&#40;</span><span class="kw2">id</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        <span class="kw2">self</span>.<span class="me1">name</span>=<span class="kw2">str</span><span class="br0">&#40;</span>name<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        <span class="kw2">self</span>.<span class="me1">compoundBy</span>=<span class="br0">&#91;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">        <span class="kw2">self</span>.<span class="me1">compose</span>=<span class="br0">&#91;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">def</span> AddCompoundBy<span class="br0">&#40;</span><span class="kw2">self</span>,components<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">        components.<span class="me1">getElementsByTagName</span><span class="br0">&#40;</span><span class="st0">'parent'</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        compoundBy=<span class="br0">&#91;</span><span class="br0">&#40;</span><span class="kw2">int</span><span class="br0">&#40;</span>i.<span class="me1">getAttribute</span><span class="br0">&#40;</span><span class="st0">'id'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">for</span> i <span class="kw1">in</span> components.<span class="me1">getElementsByTagName</span><span class="br0">&#40;</span><span class="st0">'parent'</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">        <span class="kw2">self</span>.<span class="me1">compoundBy</span>.<span class="me1">append</span><span class="br0">&#40;</span>compoundBy<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">return</span> compoundBy</div></li><li class="li1"><div class="de1">    <span class="kw1">def</span> <span class="kw4">__str__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">        <span class="kw1">return</span> <span class="st0">&quot;%s (%i)&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">name</span>,<span class="kw2">self</span>.<span class="kw2">id</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw1">for</span> name <span class="kw1">in</span> names:</div></li><li class="li1"><div class="de1">    id_=name.<span class="me1">getAttribute</span><span class="br0">&#40;</span><span class="st0">'id'</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    name_=name._get_childNodes<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span>0<span class="br0">&#93;</span>.<span class="me1">data</span></div></li><li class="li1"><div class="de1">    element_=Element<span class="br0">&#40;</span>id_,name_<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    elementsID<span class="br0">&#91;</span><span class="kw2">int</span><span class="br0">&#40;</span>id_<span class="br0">&#41;</span><span class="br0">&#93;</span>=element_</div></li><li class="li1"><div class="de1">    elementsNAME<span class="br0">&#91;</span><span class="kw2">str</span><span class="br0">&#40;</span>name_<span class="br0">&#41;</span><span class="br0">&#93;</span>=element_</div></li><li class="li1"><div class="de1"><span class="kw1">for</span> rel <span class="kw1">in</span> relations:</div></li><li class="li1"><div class="de1">    element=elementsID<span class="br0">&#91;</span><span class="kw2">int</span><span class="br0">&#40;</span>rel.<span class="me1">getAttribute</span><span class="br0">&#40;</span><span class="st0">'id'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">for</span> parent <span class="kw1">in</span> rel.<span class="me1">getElementsByTagName</span><span class="br0">&#40;</span><span class="st0">'parents'</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">        childs=element.<span class="me1">AddCompoundBy</span><span class="br0">&#40;</span>parent<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        elementsID<span class="br0">&#91;</span>childs<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">compose</span>.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#91;</span>element.<span class="kw2">id</span>,elementsID<span class="br0">&#91;</span>childs<span class="br0">&#91;</span>1<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="kw2">id</span><span class="br0">&#93;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">if</span> childs<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="sy0">!</span>=childs<span class="br0">&#91;</span>1<span class="br0">&#93;</span>:</div></li><li class="li1"><div class="de1">            elementsID<span class="br0">&#91;</span>childs<span class="br0">&#91;</span>1<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">compose</span>.<span class="me1">append</span><span class="br0">&#40;</span><span class="br0">&#91;</span>element.<span class="kw2">id</span>,elementsID<span class="br0">&#91;</span>childs<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="kw2">id</span><span class="br0">&#93;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw1">def</span> default<span class="br0">&#40;</span><span class="kw3">parser</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">    <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw3">parser</span>.<span class="me1">rargs</span><span class="br0">&#41;</span> == 0 <span class="kw1">or</span> <span class="st0">&quot;all&quot;</span> <span class="kw1">in</span> <span class="kw3">parser</span>.<span class="me1">rargs</span>:</div></li><li class="li1"><div class="de1">        elements = elementsNAME.<span class="me1">keys</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">else</span>:</div></li><li class="li1"><div class="de1">        elements = <span class="kw3">parser</span>.<span class="me1">rargs</span></div></li><li class="li1"><div class="de1">    <span class="kw1">return</span> elements</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> forWhat<span class="br0">&#40;</span>option, opt_str, value, <span class="kw3">parser</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">    elements = default<span class="br0">&#40;</span><span class="kw3">parser</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">for</span> element_ <span class="kw1">in</span> elements:</div></li><li class="li1"><div class="de1">        <span class="kw1">try</span>:</div></li><li class="li1"><div class="de1">            element=elementsNAME<span class="br0">&#91;</span>element_<span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">for</span> compose <span class="kw1">in</span> element.<span class="me1">compose</span>:</div></li><li class="li1"><div class="de1">                <span class="kw1">print</span> <span class="st0">&quot;%s = %s + %s&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>elementsID<span class="br0">&#91;</span>compose<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">name</span>,elementsID<span class="br0">&#91;</span>compose<span class="br0">&#91;</span>1<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">name</span>,element.<span class="me1">name</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">except</span>:</div></li><li class="li1"><div class="de1">            <span class="kw1">raise</span> OptionValueError<span class="br0">&#40;</span><span class="st0">'element error: %s does not exist'</span> <span class="sy0">%</span> <span class="br0">&#40;</span>element_,<span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw1">def</span> how<span class="br0">&#40;</span>option, opt_str, value, <span class="kw3">parser</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">    <span class="kw1">if</span> <span class="kw2">len</span><span class="br0">&#40;</span><span class="kw3">parser</span>.<span class="me1">rargs</span><span class="br0">&#41;</span> == 0 <span class="kw1">or</span> <span class="st0">&quot;all&quot;</span> <span class="kw1">in</span> <span class="kw3">parser</span>.<span class="me1">rargs</span>:</div></li><li class="li1"><div class="de1">        elements = elementsNAME.<span class="me1">keys</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">else</span>:</div></li><li class="li1"><div class="de1">        elements=<span class="kw3">parser</span>.<span class="me1">rargs</span></div></li><li class="li1"><div class="de1">    <span class="kw1">for</span> element_ <span class="kw1">in</span> elements:</div></li><li class="li1"><div class="de1">        <span class="kw1">try</span>:</div></li><li class="li1"><div class="de1">            element=elementsNAME<span class="br0">&#91;</span>element_<span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">for</span> formula <span class="kw1">in</span> element.<span class="me1">compoundBy</span>:</div></li><li class="li1"><div class="de1">                <span class="kw1">print</span> <span class="st0">&quot;%s = %s + %s&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>element.<span class="me1">name</span>, elementsID<span class="br0">&#91;</span>formula<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">name</span>, elementsID<span class="br0">&#91;</span>formula<span class="br0">&#91;</span>1<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">name</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">except</span>:</div></li><li class="li1"><div class="de1">            <span class="kw1">raise</span> OptionValueError<span class="br0">&#40;</span><span class="st0">'element error: %s does not exist'</span> <span class="sy0">%</span> <span class="br0">&#40;</span>element_,<span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw1">def</span> myaddition<span class="br0">&#40;</span>a,b,c<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">    ret=<span class="kw2">set</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="co1"># a = b + c</span></div></li><li class="li1"><div class="de1">    addition=<span class="st0">&quot;%s%s%s&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>a,b,c<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    ret.<span class="me1">add</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span> [shape=point,style=filled,label=<span class="es0">\&quot;</span><span class="es0">\&quot;</span>,height=.1,width=.1]&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>addition,<span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    ret.<span class="me1">add</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span>-&gt;<span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span> [weight=1];<span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span>-&gt;<span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span> [weight=1];<span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span>-&gt;<span class="es0">\&quot;</span>%s<span class="es0">\&quot;</span> [weight=2]&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>b, addition,c,addition,addition,a<span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">return</span> ret</div></li><li class="li1"><div class="de1"><span class="kw1">def</span> graph<span class="br0">&#40;</span>option, opt_str, value, <span class="kw3">parser</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">    elements = default<span class="br0">&#40;</span><span class="kw3">parser</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    ret=<span class="st0">''</span><span class="st0">'digraph G {</span></div></li><li class="li1"><div class="de1"><span class="st0">        overlap=scale</span></div></li><li class="li1"><div class="de1"><span class="st0">        splines=true</span></div></li><li class="li1"><div class="de1"><span class="st0">        rankdir=TB<span class="es0">\n</span>'</span><span class="st0">''</span></div></li><li class="li1"><div class="de1">    connections=<span class="kw2">set</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">for</span> element_ <span class="kw1">in</span> elements:</div></li><li class="li1"><div class="de1">        element=elementsNAME<span class="br0">&#91;</span>element_<span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">try</span>:</div></li><li class="li1"><div class="de1">            <span class="kw1">for</span> formula <span class="kw1">in</span> element.<span class="me1">compoundBy</span>:</div></li><li class="li1"><div class="de1">                a=element.<span class="me1">name</span></div></li><li class="li1"><div class="de1">                b=elementsID<span class="br0">&#91;</span>formula<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">name</span></div></li><li class="li1"><div class="de1">                c=elementsID<span class="br0">&#91;</span>formula<span class="br0">&#91;</span>1<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">name</span></div></li><li class="li1"><div class="de1">                connections|=myaddition<span class="br0">&#40;</span>a,b,c<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">for</span> compose <span class="kw1">in</span> element.<span class="me1">compose</span>:</div></li><li class="li1"><div class="de1">                a=elementsID<span class="br0">&#91;</span>compose<span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">name</span></div></li><li class="li1"><div class="de1">                b=element.<span class="me1">name</span></div></li><li class="li1"><div class="de1">                c=elementsID<span class="br0">&#91;</span>compose<span class="br0">&#91;</span>1<span class="br0">&#93;</span><span class="br0">&#93;</span>.<span class="me1">name</span></div></li><li class="li1"><div class="de1">                connections|=myaddition<span class="br0">&#40;</span>a,b,c<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">except</span>:</div></li><li class="li1"><div class="de1">            <span class="kw1">raise</span> OptionValueError<span class="br0">&#40;</span><span class="st0">'element error: %s does not exist'</span> <span class="sy0">%</span> <span class="br0">&#40;</span>element_,<span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">for</span> conn <span class="kw1">in</span>  connections:</div></li><li class="li1"><div class="de1">        ret+=conn+<span class="st0">';<span class="es0">\n</span>'</span></div></li><li class="li1"><div class="de1">    ret+=<span class="st0">'}'</span></div></li><li class="li1"><div class="de1">    <span class="kw1">print</span> ret</div></li><li class="li1"><div class="de1"><span class="kw3">parser</span> = OptionParser<span class="br0">&#40;</span><span class="st0">&quot;usage: %prog [options] [ELEMENTS|all]&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw3">parser</span>.<span class="me1">add_option</span><span class="br0">&#40;</span><span class="st0">&quot;-g&quot;</span>, <span class="st0">&quot;--how&quot;</span>, action=<span class="st0">&quot;callback&quot;</span>, callback=how, dest=<span class="st0">&quot;how&quot;</span>, <span class="kw2">help</span>=<span class="st0">&quot;how can I get ELEMENT&quot;</span>, default=<span class="kw2">False</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw3">parser</span>.<span class="me1">add_option</span><span class="br0">&#40;</span><span class="st0">&quot;-f&quot;</span>, <span class="st0">&quot;--forWhat&quot;</span>, action=<span class="st0">&quot;callback&quot;</span>, callback=forWhat, dest=<span class="st0">&quot;forWhat&quot;</span>, <span class="kw2">help</span>=<span class="st0">&quot;for what elements can ELEMENT be used&quot;</span>, default=<span class="kw2">False</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw3">parser</span>.<span class="me1">add_option</span><span class="br0">&#40;</span><span class="st0">&quot;-c&quot;</span>, <span class="st0">&quot;--graph&quot;</span>, action=<span class="st0">&quot;callback&quot;</span>, callback=graph, dest=<span class="st0">&quot;graph&quot;</span>,   <span class="kw2">help</span>=<span class="st0">&quot;graph the parents/childs from/to ELEMENT&quot;</span>, default=<span class="kw2">False</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="br0">&#40;</span>options, args<span class="br0">&#41;</span> = <span class="kw3">parser</span>.<span class="me1">parse_args</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li></ol></pre></div></div></p>
<p>Así, si quiero saber cómo obtener el elemento <em>egg</em>:<br />
<code><br />
$ ./alchemy.py -g egg<br />
egg = life + stone<br />
egg = bird + bird<br />
egg = turtle + turtle<br />
egg = lizard + lizard<br />
</code><br />
Si quiero saber para que me pueden servir los elemetos <em>dough</em> y <em>sea</em>:<br />
<code>$ ./alchemy.py -f dough sea<br />
bread = fire + dough<br />
cookie = fruit + dough<br />
ocean = water + sea<br />
seaweed = plant + sea<br />
beach = sand + sea<br />
wave = wind + sea<br />
tides = moon + sea<br />
seasickness = sickness + sea<br />
algae = plant + sea<br />
horizon = sky + sea<br />
</code><br />
Para obtener todas las combinaciones:<br />
<code>$ ./alchemy.py -g all</code><br />
que da <a href="http://www.lucianobello.com.ar/blog/alchemy_all.txt">este</a> listado. Me pareció interesante hacer algunos grafos con estos datos. Así se puede ver la sección local de <em>light bulb</em>:<br />
<code>./alchemy.py -c "light bulb" | dot -Tpng > light_bulb.png ; display light_bulb.png</code><br />
<img src="http://www.lucianobello.com.ar/blog/alchemy_graph.png" alt="" /><br />
Claro que también se puede hacer el grafo completo (si se tiene memoria y tiempo):<br />
<code>$ ./alchemy.py -c all | neato -Tpng > all.png ; display all.png</code><br />
Así se genera una imagen enorme de la que se puede ver un fragmento a continuación (<a href="http://www.lucianobello.com.ar/blog/alchemy_all.jpg">click acá</a> para verla completa, son 13MB 12027x 13593).<br />
<img src="http://www.lucianobello.com.ar/blog/alchemy_all_.png"/><br />
Fue divertido, incluso cuando evidentemente no fui el primero en notar esto y basta con<a href="https://encrypted.google.com/search?q=alchemy.l8r.pl+cheats"> googlear un poco para conocer las soluciones</a>. En lo personal, consideré parte del juego escribir el código que lo resuelve y lo usé de excusa para hacer algo con <a href="http://docs.python.org/library/optparse.html">optparse</a>, que lo tenía pendiente.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/jugando-a-ser-dios/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>parser para fórmulas de lógica proposicional (o una somera introducción a pyparsing)</title>
		<link>http://www.lucianobello.com.ar/post/parser-para-formulas-de-logica-proposicional-o-una-somera-introduccion-a-pyparsing/</link>
		<comments>http://www.lucianobello.com.ar/post/parser-para-formulas-de-logica-proposicional-o-una-somera-introduccion-a-pyparsing/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 17:13:29 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[academy]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[procrastination]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[university]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1515</guid>
		<description><![CDATA[La semana pasada empecé a cursar, de oyente, dos materias en Exactas: Lógica y Computabilidad y Teoría de Lenguajes. En la primera, empezamos a estudiar algunos conceptos de cálculo proposicional. Al final de la clase, el profesor sugirió escribir un pequeño parser que reconozca fórmulas de lógica proposicional. Dado que venía con ganas de entender [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://arte.atompedia.com/googleimages/arte.png/m/224753" align="right" />La semana pasada empecé a cursar, de oyente, dos materias en <a href="http://exactas.uba.ar/">Exactas</a>: <a href="http://cms.dm.uba.ar/academico/materias/1ercuat2011/logica_y_computabilidad/">Lógica y Computabilidad</a> y <a href="http://dc.uba.ar/materias/tl">Teoría de Lenguajes</a>. En la primera, empezamos a estudiar algunos conceptos de <a href="https://secure.wikimedia.org/wikipedia/es/wiki/L%C3%B3gica_proposicional">cálculo proposicional</a>. Al final de la clase, el profesor sugirió escribir un pequeño parser que reconozca fórmulas de lógica proposicional. Dado que venía con ganas de entender mejor <a href="http://pyparsing.wikispaces.com/">pyparsing</a>, me pareció que podía ser una buena forma de empezar.</p>
<p>Primero, <a href="http://pc-matias.dm.uba.ar/LyC/Cignoli-Martinez.pdf">la teoría</a>. Dado el alfabeto <img src='http://s.wordpress.com/latex.php?latex=A&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='A' title='A' class='latex' />, <img src='http://s.wordpress.com/latex.php?latex=A%5E%2A&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='A^*' title='A^*' class='latex' /> es el conjunto de palabras que pueden formarse combinando sus elementos.<br />
<img src='http://s.wordpress.com/latex.php?latex=A%3D%5C%7B%20%5Cto%20%2C%20%5Cwedge%20%2C%20%5Cvee%20%2C%20%5Cneg%20%2C%20%28%20%2C%20%29%20%2C%20p%20%2C%20%5Cprime%20%5C%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='A=\{ \to , \wedge , \vee , \neg , ( , ) , p , \prime \}' title='A=\{ \to , \wedge , \vee , \neg , ( , ) , p , \prime \}' class='latex' /><br />
Existe un tipo particular de palabras, a las que llamamos variables.<br />
<img src='http://s.wordpress.com/latex.php?latex=Var%3D%5C%7Bp%20%2C%20p%5Cprime%2C%20p%5Cprime%5Cprime%20%2C%20%20%5Cldots%20%5C%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='Var=\{p , p\prime, p\prime\prime ,  \ldots \}' title='Var=\{p , p\prime, p\prime\prime ,  \ldots \}' class='latex' /><br />
Es un conjunto infinito y, dado que puede ser tedioso contar la cantidad de <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Prime_%28symbol%29">primas</a>, las variables pueden ser referenciadas como <img src='http://s.wordpress.com/latex.php?latex=p_n&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p_n' title='p_n' class='latex' />, donde <em>n</em> es la cantidad de primas. Así, parece razonable pensar que no todas las palabras son <em>válidas</em> a la hora de escribir una fórmula (que es como llamaremos a las palabras válidas).</p>
<p>Ejemplos de fórmulas:
<ul>
<li> <img src='http://s.wordpress.com/latex.php?latex=%20p_2&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' p_2' title=' p_2' class='latex' />
<li> <img src='http://s.wordpress.com/latex.php?latex=%20%28%20%28%20p_3%20%5Cwedge%20p_5%20%29%20%5Cto%20%28%20%5Cneg%20p_2%20%5Cvee%20p_5%20%29%20%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' ( ( p_3 \wedge p_5 ) \to ( \neg p_2 \vee p_5 ) )' title=' ( ( p_3 \wedge p_5 ) \to ( \neg p_2 \vee p_5 ) )' class='latex' />
<li> <img src='http://s.wordpress.com/latex.php?latex=%20%5Cneg%20%5Cneg%20%28%20p%5Cprime%20%5Cvee%20p_%7B1232%7D%20%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' \neg \neg ( p\prime \vee p_{1232} )' title=' \neg \neg ( p\prime \vee p_{1232} )' class='latex' />
</ul>
<p>Ejemplos de no-fórmulas (palabras que no forman una fórmula):
<ul>
<li> <img src='http://s.wordpress.com/latex.php?latex=%20%5Cneg%5Cprime&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' \neg\prime' title=' \neg\prime' class='latex' />
<li> <img src='http://s.wordpress.com/latex.php?latex=%20%28%20p_2%20%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' ( p_2 )' title=' ( p_2 )' class='latex' />
<li> <img src='http://s.wordpress.com/latex.php?latex=%20p_3%20%5Cvee%20%5Cwedge%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' p_3 \vee \wedge ' title=' p_3 \vee \wedge ' class='latex' />
</ul>
<p>Si bien es más o menos intuitivo qué es una fórmula y qué no, es necesario definirlo en un sentido formal. Así  <img src='http://s.wordpress.com/latex.php?latex=%20Form%20%5Csubset%20A%5E%2A%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' Form \subset A^* ' title=' Form \subset A^* ' class='latex' /> y es el conjunto de las palabras que cumplen:
<ol TYPE="i">
<li> si <img src='http://s.wordpress.com/latex.php?latex=%5Calpha%20%5Cin%20A%5E%2A&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\alpha \in A^*' title='\alpha \in A^*' class='latex' /> y <img src='http://s.wordpress.com/latex.php?latex=%5Calpha%20%5Cin%20Var&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\alpha \in Var' title='\alpha \in Var' class='latex' />, entonces <img src='http://s.wordpress.com/latex.php?latex=%5Calpha%20%5Cin%20Form&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\alpha \in Form' title='\alpha \in Form' class='latex' />
<li> si <img src='http://s.wordpress.com/latex.php?latex=%5Calpha%20%5Cin%20Form&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\alpha \in Form' title='\alpha \in Form' class='latex' />, entonces <img src='http://s.wordpress.com/latex.php?latex=%5Cneg%20%5Calpha%20%5Cin%20Form&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\neg \alpha \in Form' title='\neg \alpha \in Form' class='latex' />
<li> si <img src='http://s.wordpress.com/latex.php?latex=%5Calpha%2C%5Cbeta%20%5Cin%20Form&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\alpha,\beta \in Form' title='\alpha,\beta \in Form' class='latex' />, entonces <img src='http://s.wordpress.com/latex.php?latex=%28%20%5Calpha%20%5Ccircledast%20%5Cbeta%29%5Cin%20Form&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='( \alpha \circledast \beta)\in Form' title='( \alpha \circledast \beta)\in Form' class='latex' />. Donde <img src='http://s.wordpress.com/latex.php?latex=%5Ccircledast%3D%5Cvee%2C%5Cwedge%2C%5Cto%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\circledast=\vee,\wedge,\to ' title='\circledast=\vee,\wedge,\to ' class='latex' />
</ol>
<p>Nada más es una fórmula.</p>
<p>Ahora, a la práctica. Queremos escribir un parser que, dada una palabra, reconozca si es una fórmula. Y para esto vamos a jugar con el módulo <a href="http://pyparsing.wikispaces.com/">pyparsing</a>, para python.</p>
<p>Lo primero es definir el conjunto de variables.<br />
<code><br />
>>> from pyparsing import Word<br />
>>> variable=Word('Pp',"0123456789'")<br />
>>> variable.parseString('p1')<br />
(['p1'], {})<br />
>>> variable.parseString("P'")<br />
(["P'"], {})<br />
</code><br />
Así, <tt>variable</tt> reconoce los posibles nombres de variables. Toda expresión que sea parseable por <tt>variable</tt>, es una formula. Para el punto <i>ii.</i> hay que definir una estructura recursiva. Utilizaremos el <i>bang</i> (<tt>!</tt>) para la negación.<br />
<code>from pyparsing import Forward<br />
formula=Forward()<br />
ii='!' + formula<br />
</code><br />
Caso similar en el punto <i>iii.</i>. Para esto hay que definir los operadores, que son <i>and</i> (<tt>&#038;</tt>), <i>or</i> (<tt>|</tt>) y  <i>then</i> (<tt>&lt;</tt>).<br />
<code><br />
operador=Word('&#038;|>',max=1)<br />
iii='('+formula+operador+formula+')'</code><br />
Por último, definimos una fórmula cómo una variable (<i>i.</i>) o una negación de una fórmula (<i>ii.</i>) o una operación entre fórmulas (<i>iii.</i>).<br />
<code><br />
formula << ( variable | ii | iii )<br />
</code><br />
Y esto es, básicamente, nuestro parser:<br />
<code><br />
>>> formula.parseString("(p1 | p4)")<br />
(['(', 'p1', '|', 'p4', ')'], {})<br />
</code><br />
Lo dicho, con un poco más de contexto y en un único archivo, a continuación:<br />
<div id="wpshdo_2" class="wp-synhighlighter-outer"><div id="wpshdt_2" class="wp-synhighlighter-collapsed"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_2"></a><a id="wpshat_2" class="wp-synhighlighter-title" href="#codesyntax_2"  onClick="javascript:wpsh_toggleBlock(2)" title="Click to show/hide code block">logicparser.py</a></td><td align="right"><a href="#codesyntax_2" onClick="javascript:wpsh_code(2)" title="Show code only"><img border="0" style="border: 0 none" src="http://www.lucianobello.com.ar/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_2" onClick="javascript:wpsh_print(2)" title="Print code"><img border="0" style="border: 0 none" src="http://www.lucianobello.com.ar/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_2" class="wp-synhighlighter-inner" style="display: none;"><pre class="python" style="font-family:monospace;"><ol><li class="li1"><div class="de1"><span class="kw1">from</span> pyparsing <span class="kw1">import</span> Forward, Word</div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">sys</span> </div></li><li class="li1"><div class="de1">expression=<span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">variable=Word<span class="br0">&#40;</span><span class="st0">'Pp'</span>,<span class="st0">&quot;0123456789'&quot;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">operador=Word<span class="br0">&#40;</span><span class="st0">'&amp;|&gt;'</span>,<span class="kw2">max</span>=<span class="nu0">1</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">formula=Forward<span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">ii=<span class="st0">'!'</span> + formula</div></li><li class="li1"><div class="de1">iii=<span class="st0">'('</span>+formula+operador+formula+<span class="st0">')'</span></div></li><li class="li1"><div class="de1">formula <span class="sy0">&lt;&lt;</span> <span class="br0">&#40;</span> variable | ii | iii <span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw1">print</span> expression,<span class="st0">&quot; - es formula? &quot;</span>,</div></li><li class="li1"><div class="de1"><span class="kw1">try</span>:</div></li><li class="li1"><div class="de1">    palabras = formula.<span class="me1">parseString</span><span class="br0">&#40;</span>expression.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span>,parseAll=<span class="kw2">True</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">print</span> <span class="st0">&quot;TRUE&quot;</span>,</div></li><li class="li1"><div class="de1">    <span class="kw1">print</span> palabras</div></li><li class="li1"><div class="de1"><span class="kw1">except</span>:</div></li><li class="li1"><div class="de1">    <span class="kw1">print</span> <span class="st0">&quot;FALSE&quot;</span></div></li></ol></pre></div></div></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/parser-para-formulas-de-logica-proposicional-o-una-somera-introduccion-a-pyparsing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>how to hack a h4ckc0nt3st</title>
		<link>http://www.lucianobello.com.ar/post/how-to-hack-a-h4ckc0nt3st/</link>
		<comments>http://www.lucianobello.com.ar/post/how-to-hack-a-h4ckc0nt3st/#comments</comments>
		<pubDate>Sun, 27 Feb 2011 22:34:31 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[ego]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[procrastination]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1502</guid>
		<description><![CDATA[Hace unas horas acabo de volver de A Coruña, donde pasé unos excelentes días entre charlas y talleres de excelente nivel técnico y amigos en las Jornadas de Seguridad Informáticas organizadas por GSIC. Pero este post tiene otro objetivo que contar lo lindo que fue. Así que si esperabas algo blando, puedes dejar de leer [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unas horas acabo de volver de A Coruña, donde pasé unos excelentes días entre charlas y talleres de excelente nivel técnico y amigos en las <a href="http://www.gsicoruna.com/jornadas">Jornadas de Seguridad Informáticas</a> organizadas por <a href="http://www.gsicoruna.com/index.html">GSIC</a>.</p>
<p>Pero este post tiene otro objetivo que contar lo lindo que fue. Así que si esperabas algo blando, puedes dejar de leer acá :P (las fotos estarán online en breve). Lo que sigue es la respuesta larga a la pregunta que me realizaron varias veces en los últimos días: <em>¿Estas jugando al h4ckc0nt3st?</em>. La respuesta corta era <em>sí, lo estoy haciendo en este exacto momento, aunque no de la forma tradicional</em>.</p>
<h3>El contexto</h3>
<p>Durante la conferencia,  <a href="https://twitter.com/mgesteiro">Miguel</a> organizó un muy divertido hack contest. El objetivo era llegar a una respuesta a través de la resolución de diferentes desafíos. Dicha respuesta se metía en un formulario web (que escuchaba en http://10.20.63.1:666) y de esta forma se acumulaban puntos.</p>
<h3>El hack</h3>
<p>Dado que la red sobre la que se hacía el concurso era una wifi abierta y que el servidor recibía las respuestas de los participantes en texto plano (no usaba <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Secure_Sockets_Layer">SSL</a>), pensé que sería divertido escuchar las respuestas de los demás concursantes. El paso siguiente de enviar dichas respuestas a mi nombre resultó inevitable. De esta forma, cada vez que alguien enviaba una posible respuesta a un desafío, yo también respondía lo mismo. Logré automatizar ello con las siguientes líneas:<br />
<code><br />
tshark -T fields -e data -i mon0 -R 'ip.dst == 10.20.63.1 and tcp.dstport == 666 and ip.src != mi.propia.ip ' | ./loro.py</code><br />
Donde <tt>loro.py</tt> este archivo:<br />
<div id="wpshdo_3" class="wp-synhighlighter-outer"><div id="wpshdt_3" class="wp-synhighlighter-collapsed"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_3"></a><a id="wpshat_3" class="wp-synhighlighter-title" href="#codesyntax_3"  onClick="javascript:wpsh_toggleBlock(3)" title="Click to show/hide code block">loro.py</a></td><td align="right"><a href="#codesyntax_3" onClick="javascript:wpsh_code(3)" title="Show code only"><img border="0" style="border: 0 none" src="http://www.lucianobello.com.ar/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_3" onClick="javascript:wpsh_print(3)" title="Print code"><img border="0" style="border: 0 none" src="http://www.lucianobello.com.ar/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_3" class="wp-synhighlighter-inner" style="display: none;"><pre class="python" style="font-family:monospace;"><ol><li class="li1"><div class="de1"><span class="co1">#!/usr/bin/python</span></div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">sys</span></div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">binascii</span></div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">socket</span></div></li><li class="li1"><div class="de1"><span class="kw1">for</span> line <span class="kw1">in</span> <span class="kw3">sys</span>.<span class="me1">stdin</span>:</div></li><li class="li1"><div class="de1">    todecode=line.<span class="me1">strip</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    decode=<span class="kw3">binascii</span>.<span class="me1">a2b_hex</span><span class="br0">&#40;</span>todecode<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">if</span> <span class="st0">'acceder'</span> <span class="kw1">in</span> decode <span class="kw1">or</span> <span class="st0">'enviar'</span> <span class="kw1">in</span> decode :</div></li><li class="li1"><div class="de1">        datas=decode.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">'<span class="es0">\n</span>'</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        <span class="kw1">if</span> <span class="st0">'desafio'</span> <span class="kw1">in</span> datas<span class="br0">&#91;</span>0<span class="br0">&#93;</span>:</div></li><li class="li1"><div class="de1">            <span class="kw1">for</span> i,j <span class="kw1">in</span> <span class="kw2">enumerate</span><span class="br0">&#40;</span>datas<span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">                <span class="kw1">if</span> <span class="st0">'Cookie'</span> <span class="kw1">in</span> j: datas<span class="br0">&#91;</span>i<span class="br0">&#93;</span>=<span class="st0">'Cookie: HCWSSESSID=&quot;your cookie goes here&quot;'</span></div></li><li class="li1"><div class="de1">            tosend=<span class="st0">'<span class="es0">\n</span>'</span>.<span class="me1">join</span><span class="br0">&#40;</span>datas<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">            <span class="kw3">sys</span>.<span class="me1">stderr</span>.<span class="me1">write</span><span class="br0">&#40;</span>tosend<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">            s = <span class="kw3">socket</span>.<span class="kw3">socket</span><span class="br0">&#40;</span><span class="kw3">socket</span>.<span class="me1">AF_INET</span>, <span class="kw3">socket</span>.<span class="me1">SOCK_STREAM</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">            s.<span class="me1">connect</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="st0">'10.20.63.1'</span>, 666<span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">            s.<span class="me1">send</span><span class="br0">&#40;</span>tosend<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">            s.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">            <span class="kw1">print</span> <span class="st0">'-'</span><span class="sy0">*</span><span class="nu0">30</span></div></li></ol></pre></div></div></p>
<h3>La explicación</h3>
<p><a href="http://www.wireshark.org/docs/man-pages/tshark.html">Tshark</a> es la versión de consola de <a href="http://www.wireshark.org/">wireshark</a>. Este toma los paquetes de una interfaz en modo monitor (lee <a href="http://aircrack-ng.org/doku.php?id=iwl3945">esto</a> para aprender cómo). El modificador <tt>-f</tt> es el encargado de darme solo aquellos paquetes que vayan al servidor. Excluir del filtro a mi propia IP evita que el sniffer vea mis replayes y entre en loop (tardé en darme cuenta de esto, perdona Miguel por floodear tus logs). El script <tt>loro.py</tt> recibe el campo <tt>data</tt> de los por <tt>stdin</tt> (línea (#) 5), lo decodifica en <a href="https://secure.wikimedia.org/wikipedia/en/wiki/ASCII">ascii</a> (#7), y chequea si es una respuesta (#8). Después lo divide y busca la cookie (# 9 a 11). Al encontrarla, la reemplaza por mi propia cookie (#12, fue una suerte práctica que no caducara). Luego vuelve a juntar todo (#13), lo imprime en stderr (#14, con fines de logging, nada más) y lo envía de nuevo al server (# 15 a 18).</p>
<p>Como dicen por acá, <em>¡a que mola!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/how-to-hack-a-h4ckc0nt3st/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>exportando cumpleaños de Facebook a Google Calendar</title>
		<link>http://www.lucianobello.com.ar/post/fb2gc/</link>
		<comments>http://www.lucianobello.com.ar/post/fb2gc/#comments</comments>
		<pubDate>Wed, 09 Feb 2011 18:55:20 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[geek]]></category>
		<category><![CDATA[life]]></category>
		<category><![CDATA[procrastination]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[social networking]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1480</guid>
		<description><![CDATA[Ocurre que soy realmente malo para recordar eventos. Muchas veces me comprometí a estar en dos lados simultáneamente y me olvido de hacer tal o cual cosa. Mi desorden se extiende a cosas repetitivas, como los cursos o cumpleaños. Para intentar apalear este mal, utilizo Google Calendar intensamente. Es por esto que intenté exportar las [...]]]></description>
			<content:encoded><![CDATA[<p>Ocurre que soy realmente malo para recordar eventos. Muchas veces me comprometí a estar en dos lados simultáneamente y me olvido de hacer tal o cual cosa. Mi desorden se extiende a cosas repetitivas, como los cursos o cumpleaños. Para intentar apalear este mal, utilizo <a href="http://www.google.com/calendar">Google Calendar</a> intensamente. Es por esto que intenté exportar las fechas de cumpleaños a mis calendarios. Pero cuando intenté hacerlo <em>out-of-the-box</em> me encontré con unos incordios:</p>
<ul>
<li>No hay forma de exportar solo un subconjunto de las fechas</li>
<li>Con los cambios de <a href="http://en.wikipedia.org/wiki/Daylight_saving_time">DST</a>, hay eventos que duran dos días</li>
<li>Los eventos no son de <em>días completos</em>, sino que van de 12am a 12am</li>
<li>No quedan como eventos editables <em>normales</em></li>
</ul>
<p>Los eventos se ven algo así:<br />
<img class="alignnone" src="http://www.lucianobello.com.ar/blog/fbbirthdays5.png" /><br />
Y la verdad que están horribles. Así que realicé estos 5 sencillos pasos:</p>
<h3>Paso 1</h3>
<p>Fui <a href="http://www.facebook.com/#!/?sk=bd">a los eventos de cumpleaños en mi perfil</a>, donde puse <em>exportar cumpleaños</em>.<br />
<img src="http://www.lucianobello.com.ar/blog/fbbirthdays0.png" alt="" /><br />
Así, facebook me proveyó una URL, que empieza con <em>webcal://</em><br />
<img src="http://www.lucianobello.com.ar/blog/fbbirthdays1.png" alt="" /></p>
<h3>Paso 2</h3>
<p>Esta URL, reemplazando <em>webcal</em> por <em>http</em>, la utilicé para obtener los eventos, en formato CSV:<br />
<code>wget "http://www.facebook.com/ical/b.php?uid=2XXXXXX4&amp;key=3XXXXXXX8" -O facebook.csv</code></p>
<h3>Paso 3 (opcional)</h3>
<p>Dada mi política de <em>aceptar-todo-contacto</em> en Facebook hay muchos eventos que no quisiera incluir en mi calendario. Por lo que generé una lista de los que sí quiero tener:<br />
<code>rgrep "^SUMMARY" facebook.csv &gt; lista.txt</code><br />
Y después borré de <tt>lista.txt</tt> aquellos que quería excluir.</p>
<h3>Paso 4</h3>
<p>Escribí el siguiente script:<br />
<div id="wpshdo_4" class="wp-synhighlighter-outer"><div id="wpshdt_4" class="wp-synhighlighter-collapsed"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_4"></a><a id="wpshat_4" class="wp-synhighlighter-title" href="#codesyntax_4"  onClick="javascript:wpsh_toggleBlock(4)" title="Click to show/hide code block">fb2gc.py</a></td><td align="right"><a href="#codesyntax_4" onClick="javascript:wpsh_code(4)" title="Show code only"><img border="0" style="border: 0 none" src="http://www.lucianobello.com.ar/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_4" onClick="javascript:wpsh_print(4)" title="Print code"><img border="0" style="border: 0 none" src="http://www.lucianobello.com.ar/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_4" class="wp-synhighlighter-inner" style="display: none;"><pre class="python" style="font-family:monospace;"><ol><li class="li1"><div class="de1"><span class="co1">#!/usr/bin/python</span></div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">datetime</span></div></li><li class="li1"><div class="de1"><span class="kw1">import</span> <span class="kw3">sys</span></div></li><li class="li1"><div class="de1"><span class="kw1">print</span> <span class="st0">''</span><span class="st0">'BEGIN:VCALENDAR</span></div></li><li class="li1"><div class="de1"><span class="st0">PRODID:localscript</span></div></li><li class="li1"><div class="de1"><span class="st0">VERSION:2.0</span></div></li><li class="li1"><div class="de1"><span class="st0">CALSCALE:GREGORIAN</span></div></li><li class="li1"><div class="de1"><span class="st0">METHOD:PUBLISH</span></div></li><li class="li1"><div class="de1"><span class="st0">X-WR-CALNAME:</span></div></li><li class="li1"><div class="de1"><span class="st0">X-WR-TIMEZONE:America/Argentina/Buenos_Aires</span></div></li><li class="li1"><div class="de1"><span class="st0">X-WR-CALDESC:</span></div></li><li class="li1"><div class="de1"><span class="st0">BEGIN:VTIMEZONE</span></div></li><li class="li1"><div class="de1"><span class="st0">TZID:America/Argentina/Buenos_Aires</span></div></li><li class="li1"><div class="de1"><span class="st0">X-LIC-LOCATION:America/Argentina/Buenos_Aires</span></div></li><li class="li1"><div class="de1"><span class="st0">BEGIN:STANDARD</span></div></li><li class="li1"><div class="de1"><span class="st0">TZOFFSETFROM:-0300</span></div></li><li class="li1"><div class="de1"><span class="st0">TZOFFSETTO:-0300</span></div></li><li class="li1"><div class="de1"><span class="st0">TZNAME:ART</span></div></li><li class="li1"><div class="de1"><span class="st0">DTSTART:19700101T000000</span></div></li><li class="li1"><div class="de1"><span class="st0">END:STANDARD</span></div></li><li class="li1"><div class="de1"><span class="st0">END:VTIMEZONE'</span><span class="st0">''</span></div></li><li class="li1"><div class="de1">day=<span class="kw3">datetime</span>.<span class="me1">timedelta</span><span class="br0">&#40;</span>1<span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">fd = <span class="kw2">open</span><span class="br0">&#40;</span> <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span>1<span class="br0">&#93;</span> <span class="br0">&#41;</span></div></li><li class="li1"><div class="de1"><span class="kw1">try</span>:</div></li><li class="li1"><div class="de1">    mylist=<span class="kw2">open</span><span class="br0">&#40;</span> <span class="kw3">sys</span>.<span class="me1">argv</span><span class="br0">&#91;</span>2<span class="br0">&#93;</span> <span class="br0">&#41;</span>.<span class="me1">readlines</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    nolist=<span class="kw2">False</span></div></li><li class="li1"><div class="de1"><span class="kw1">except</span>:</div></li><li class="li1"><div class="de1">    nolist=<span class="kw2">True</span></div></li><li class="li1"><div class="de1">va = <span class="kw2">False</span></div></li><li class="li1"><div class="de1">person=<span class="st0">&quot;&quot;</span></div></li><li class="li1"><div class="de1"><span class="kw1">for</span> line <span class="kw1">in</span> fd.<span class="me1">readlines</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:</div></li><li class="li1"><div class="de1">    <span class="kw1">if</span> <span class="st0">'BEGIN:VEVENT'</span> <span class="kw1">in</span> line:</div></li><li class="li1"><div class="de1">        person=<span class="st0">'BEGIN:VEVENT<span class="es0">\n</span>'</span></div></li><li class="li1"><div class="de1">    <span class="kw1">elif</span> <span class="st0">'DTSTART'</span> <span class="kw1">in</span> line:</div></li><li class="li1"><div class="de1">        dateS=line.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">':'</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">'T'</span><span class="br0">&#41;</span><span class="br0">&#91;</span>0<span class="br0">&#93;</span></div></li><li class="li1"><div class="de1">        date=<span class="kw3">datetime</span>.<span class="me1">date</span><span class="br0">&#40;</span><span class="kw2">int</span><span class="br0">&#40;</span>dateS<span class="br0">&#91;</span>0:4<span class="br0">&#93;</span><span class="br0">&#41;</span>,<span class="kw2">int</span><span class="br0">&#40;</span>dateS<span class="br0">&#91;</span>4:6<span class="br0">&#93;</span><span class="br0">&#41;</span>,<span class="kw2">int</span><span class="br0">&#40;</span>dateS<span class="br0">&#91;</span><span class="nu0">6</span>:<span class="nu0">8</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">        tomorrow=date+day</div></li><li class="li1"><div class="de1">        person+=<span class="st0">'DESCRIPTION:Imported from Facebook<span class="es0">\n</span>STATUS:CONFIRMED<span class="es0">\n</span>DTSTART;VALUE=DATE:%s<span class="es0">\n</span>DTEND;VALUE=DATE:%s<span class="es0">\n</span>TRANSP:TRANSPARENT<span class="es0">\n</span>'</span> <span class="sy0">%</span> <span class="br0">&#40;</span>date.<span class="me1">strftime</span><span class="br0">&#40;</span><span class="st0">&quot;%Y%m%d&quot;</span><span class="br0">&#41;</span>,tomorrow.<span class="me1">strftime</span><span class="br0">&#40;</span><span class="st0">&quot;%Y%m%d&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div></li><li class="li1"><div class="de1">    <span class="kw1">elif</span> <span class="st0">'END:VEVENT'</span> <span class="kw1">in</span> line:</div></li><li class="li1"><div class="de1">        person+=<span class="st0">'END:VEVENT<span class="es0">\n</span>'</span></div></li><li class="li1"><div class="de1">        <span class="kw1">if</span> va:</div></li><li class="li1"><div class="de1">            <span class="kw1">print</span> person,</div></li><li class="li1"><div class="de1">    <span class="kw1">elif</span> <span class="st0">'SUMMARY'</span> <span class="kw1">in</span> line:</div></li><li class="li1"><div class="de1">        person+=line</div></li><li class="li1"><div class="de1">        va=nolist <span class="kw1">or</span> line <span class="kw1">in</span> mylist</div></li><li class="li1"><div class="de1">    <span class="kw1">elif</span> <span class="st0">'DURATION'</span> <span class="kw1">in</span> line:</div></li><li class="li1"><div class="de1">        <span class="kw1">pass</span></div></li><li class="li1"><div class="de1">    <span class="kw1">else</span>:</div></li><li class="li1"><div class="de1">        person+=line</div></li><li class="li1"><div class="de1"><span class="kw1">print</span> <span class="st0">'END:VCALENDAR'</span></div></li></ol></pre></div></div><br />
El cual convierte los eventos de <em>facebook</em> en eventos <em>lindos</em>. Se ejecuta así:<br />
<code>./fb2gc.py facebook.csv lista.txt > miscumples.csv<br />
</code> El parámetro <tt>lista.txt</tt> es optativo, si pasaste por el Paso 3.</p>
<h3>Paso 5</h3>
<p>El archivo generado se pueden importar en Google Calendar, en un calendario existente.<br />
<img src="http://www.lucianobello.com.ar/blog/fbbirthdays3.png" alt="" /><br />
<img src="http://www.lucianobello.com.ar/blog/fbbirthdays4.png" alt="" /><br />
Y ahora, tengo agendados los cumpleaños de forma mucho más agradable.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/fb2gc/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>secure information flow analysis: my first steps</title>
		<link>http://www.lucianobello.com.ar/post/secure-information-flow-analysis-my-first-steps/</link>
		<comments>http://www.lucianobello.com.ar/post/secure-information-flow-analysis-my-first-steps/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 23:40:06 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[academy]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[information flow]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[sorry for my english]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1451</guid>
		<description><![CDATA[During the last months and have been reading a lot about information flow analysis, with the remarkable Eduardo Bonelli&#8216;s guidance. Some months ago, as an exercise, I wrote two analyzers for a really short command set of Python (while, if and assign). Before remove that directory, it occurred to me that may exists a remote [...]]]></description>
			<content:encoded><![CDATA[<p>During the last months and have been reading a lot about information flow analysis, with the remarkable <a href="http://www.informatik.uni-trier.de/~ley/db/indices/a-tree/b/Bonelli:Eduardo.html">Eduardo Bonelli</a>&#8216;s guidance.</p>
<p>Some months ago, as an exercise, I wrote two analyzers for a really short command set of Python (<tt>while</tt>, <tt>if</tt> and <tt>assign</tt>). Before remove that directory, it occurred to me that may exists a remote possibility that someone might find it interesting. So here it is, with a quick and dirty introduction to secure information flow.</p>
<p>The goal, in short words, is to avoid that variables tagged as secret (high confidential level) doesn&#8217;t leak to public variables (low confidential level). This may happen in two ways:
<ul>
<li>Explicit: A high variable is assigned to a low variable</li>
<p><code>public:=secret</code></p>
<li>Implicit: A low variable content depends on the content of a high variable</li>
<p><code>if secret == true<br />
     then public:=true<br />
     else public:=false</code></ul>
<p>If there is no leak, we said that the code satisfies <strong>non-interference</strong> (<a href="https://secure.wikimedia.org/wikipedia/en/wiki/Non-interference_%28security%29">wikipedia link</a>). You can learn more about secure information flow analysis <a href="https://encrypted.google.com/search?q=secure+information+flow+analysi">in the web</a>. In my humble opinion, <a href="https://users.cs.fiu.edu/~smithg/papers/sif06.pdf">this</a> is a good introduction.</p>
<p>A typical way (certainly not the only one) to detect these leaks is with type systems. This was the approach in both analyzers. The first one is a sort of  an implementation of a <a href="http://www.lucianobello.com.ar/pif/volpano.ps">fundation paper, by Volpano et.al.</a>. I made an algorithm version (probably wrong) of the typing rules exposed in the paper. The code is <a href="http://www.lucianobello.com.ar/pif/denning-style.py">here</a>. This type of analyzers are called Denning-style, because Denning and Denning introduced those concepts in a <a href="http://www.lucianobello.com.ar/pif/denning-denning.pdf">1977 paper</a>.</p>
<p>The second analyzer (the code is <a href="http://www.lucianobello.com.ar/pif/huntsands.py">here</a>) is based on the formalism presented by Hunt and Sands in <a href="http://www.lucianobello.com.ar/pif/huntsands.pdf">this paper</a>. It&#8217;s a dynamic analyzer (Denning-style analyzers are static), which means that the non-interference can be broken in subprograms and still be good as a whole. This may be a little tricky. For example, this code is secure (the leak was overwritten with a 0) even when a subprogram (without the last line) is insecure:<br />
<code>public:=secret<br />
public:=0<br />
</code><br />
Anyway, that&#8217;s all for now. The analyzers are written in Python, using the <a href="http://www.python.org/doc//current/library/ast.html">Abstract Syntax Trees module</a> and <a href="https://code.google.com/p/python-lattice/">python-lattice</a> (yes, this is what that stupid library is for). If you want to play more, here is a <a href="http://www.lucianobello.com.ar/pif/pif.tar.gz">tarball with the code, the papers and few examples to analyze</a>.
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/secure-information-flow-analysis-my-first-steps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>operating elements of a finite lattice is now easy(?)</title>
		<link>http://www.lucianobello.com.ar/post/lattice/</link>
		<comments>http://www.lucianobello.com.ar/post/lattice/#comments</comments>
		<pubDate>Tue, 07 Dec 2010 01:13:28 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[free software]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[procrastination]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sorry for my english]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1444</guid>
		<description><![CDATA[In the context of my recent readings about Information Flow analysis, I wrote a little (tiny) Python module to operate elements of a finite lattice. Here is the code and usage tutorial. Comments are welcome. Patches to my broken English in the main page are very welcome.]]></description>
			<content:encoded><![CDATA[<p><img src="http://image.absoluteastronomy.com/images/encyclopediaimages/l/la/lattice_of_the_divisibility_of_60.svg.png" align="right" />In the context of my recent readings about Information Flow analysis, I wrote a little (tiny) Python module to operate elements of a finite lattice. Here is <a href="https://code.google.com/p/python-lattice/">the code and usage tutorial</a>. Comments are welcome. Patches to my broken English in the main page are <strong>very</strong> welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/lattice/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>eventé, eventando y eventaré</title>
		<link>http://www.lucianobello.com.ar/post/evente-eventando-y-eventare/</link>
		<comments>http://www.lucianobello.com.ar/post/evente-eventando-y-eventare/#comments</comments>
		<pubDate>Wed, 27 Oct 2010 14:47:58 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[free software]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[journeys & traveling]]></category>
		<category><![CDATA[lectures & talks]]></category>
		<category><![CDATA[life]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1431</guid>
		<description><![CDATA[He estado (y lo estaré) de evento en evento. Así que acá va un pequeño resumen. Tal vez a alguien le sea útil o pueda lamentarse de no haber ido a aquellos que ya ocurrieron. Si tenés pensado ir a alguno en donde nos encontremos, no dudes en inscribirme para tomar una cerveza. En el [...]]]></description>
			<content:encoded><![CDATA[<p>He estado (y lo estaré) de evento en evento. Así que acá va un pequeño resumen. Tal vez a alguien le sea útil o pueda lamentarse de no haber ido a aquellos que ya ocurrieron. Si tenés pensado ir a alguno en donde nos encontremos, no dudes en inscribirme para tomar una cerveza.</p>
<p>En el pasado:</p>
<ul>
<li><a href="http://ar.pycon.org/2010/">PyCon Argentina 2010</a>: En Córdoba, 15 y 16 de Octubre. Es un evento cada vez más disfrutable. En particular, aprendí mucho de <a href="http://ar.pycon.org/2010/conference/schedule/event/59/">AMQP</a>, <a href="http://ar.pycon.org/2010/conference/schedule/event/78/">DBus</a>, <a href="http://ar.pycon.org/2010/conference/schedule/event/49/">sistemas de tipos</a>, <a href="http://ar.pycon.org/2010/conference/schedule/event/79/">defragmentación de memoria</a> y <a href="http://ar.pycon.org/2010/conference/schedule/event/73/">otras yerbas</a>.</li>
<li><a href="http://www.cacic2010.edu.ar">XVI Congreso Argentino de Ciencias de la Computación (CACIC 2010)</a>:  En Buenos Aires y Morón, del 18 al 22 de Octubre. Presenté <a href="http://www.citefa.gov.ar/si6/descargas/keystroke-dataset.pdf">mi primer paper</a> en el workshop arquitectura, redes y sistemas operativos (WARSO).</li>
</ul>
<p>En el futuro:</p>
<ul>
<li><a href="http://www.jornadasregionales.org/">10º Jornadas Regionales de Software Libre</a>: En San Luis, el 28, 29 y 30 de Octubre. Este año no podré asistir, pero se corre la bola de que va a estar muy muy buena.</li>
<li><a href="https://sites.google.com/site/devfest2010arg/">Google DevFest 2010 Argentina</a>: En Buenos Aires, 1 y 2 de Noviembre. Si bien la inscripción ya debería haber terminado, yo lo hice fuera de termino y parece que tengo la confirmación. El procedimiento requiere dar respuesta <a href="https://developerquiz.appspot.com/">un breve quiz</a>.</li>
<li><a href="http://www.bsdday.org.ar/">BSDday Argentina 2010</a> (una web muy geek): En Buenos Aires, 5 y 6 de Noviembre. Me inscribí hace meses y no voy a poder ir (por la razón que se comenta en el siguiente item). El año paso la pasé muy bien y este año las charlas realmente prometen.</li>
<p><a href="http://jornadassl.agora.unnoba.edu.ar/"><img style="margin: 2px;" src="http://jornadassl.agora.unnoba.edu.ar/banners/banner3.jpg" alt="" width="109" height="79" align="right" /></a></p>
<li><a href="http://jornadassl.agora.unnoba.edu.ar/">6º Jornadas de Software Libre</a>: En Junín, 5 y 6 de Noviembre. Hablaré <a href="http://jornadassl.agora.unnoba.edu.ar/disertantes.php#lbello">Linux Capabilities y Hardening</a>. Muchísimas gracias a los organizadores por invitarme. El programa se ve muy interesante y será una excelente oportunidad para reencontrarme con amigos y visitar la ciudad.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/evente-eventando-y-eventare/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>removing your facebook photo tags automagically</title>
		<link>http://www.lucianobello.com.ar/post/rmfb-en/</link>
		<comments>http://www.lucianobello.com.ar/post/rmfb-en/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 16:22:35 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[planet]]></category>
		<category><![CDATA[procrastination]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[social networking]]></category>
		<category><![CDATA[sorry for my english]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1242</guid>
		<description><![CDATA[Este post también está escrito en español aquí. Privacy at Facebook is heavy-duty. As a big fan of the Worlds Collide Theory I hate be tagged compulsively. I would like to select in which photos appear in my profile and feed. Since I couldn&#8217;t find that option in the setting menu, I looked for the [...]]]></description>
			<content:encoded><![CDATA[<p><small>Este post también está escrito en español <a href="http://www.lucianobello.com.ar/post/rmfb-es/">aquí</a></small>.</p>
<p>Privacy at <a href="http://www.facebook.com/privacy/">Facebook</a> is heavy-duty. As a big fan of the <a href="http://www.urbandictionary.com/define.php?term=Worlds Collide Theory">Worlds Collide Theory</a> I hate be tagged compulsively. I would like to select in which photos appear in my profile and feed. Since I couldn&#8217;t find that option in the setting menu, I looked for the answer in my favorite scripting language: <a href="http://www.python.org/">Python</a>.</p>
<p><a href="http://python.pastebin.com/f55c5896f">This 60-lines-long script</a> removes your tag from the latests photos where you has been labelled. You can download it from <a href="http://www.lucianobello.com.ar/rmfb/">here</a>. You may run it hourly (or every 15 minutes, or every 5 minutes, depends how paranoid you are) via <a href="http://en.wikipedia.org/wiki/Cron">cron</a> or whatever.</p>
<p>Any improvement is welcome. It probably runs on Windows too. If you managed to do it, leave a comment for the others.</p>
<p><strong>NEW VERSION!</strong> (available <a href="http://www.lucianobello.com.ar/rmfb/">here</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/rmfb-en/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>remover tu etiqueta de las fotos de facebook automágicamente</title>
		<link>http://www.lucianobello.com.ar/post/rmfb-es/</link>
		<comments>http://www.lucianobello.com.ar/post/rmfb-es/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 16:21:24 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[geek]]></category>
		<category><![CDATA[planeta]]></category>
		<category><![CDATA[procrastination]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[social networking]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1245</guid>
		<description><![CDATA[This post has been written in English too. La privacidad en Facebook es un asunto complejo. Como gran suscriptor a la Teoría de Colisión de Mundos es que odio ser etiquetado en fotos de forma compulsiva. Me gustaría tener alguna forma de elegir en que fotos aparezco en mi perfil y actualizaciones. Dado que no [...]]]></description>
			<content:encoded><![CDATA[<p><small>This post has been written <a href="http://www.lucianobello.com.ar/post/rmfb-en/">in English too</a></small>.</p>
<p>La privacidad en <a href="http://www.facebook.com/privacy/">Facebook</a> es un asunto complejo. Como gran suscriptor a la <a href="http://www.urbandictionary.com/define.php?term=Worlds Collide Theory">Teoría de Colisión de Mundos</a> es que odio ser etiquetado en fotos de forma compulsiva. Me gustaría tener alguna forma de elegir en que fotos aparezco en mi perfil y actualizaciones. Dado que no pude encontrar tal opción entre la configuración, busqué la respuesta en mi lenguaje de scripting favorito: <a href="http://www.python.org/">Python</a>.</p>
<p><a href="http://python.pastebin.com/f55c5896f">Este script de 60 lineas</a> remueve tu etiqueta de las últimas fotos donde te hayan tagueado. Puede ser descargado desde <a href="http://www.lucianobello.com.ar/rmfb/">aquí</a>. Hay que correrlo cada hora (o cada 15 minutos, o cada 5, dependiendo de que tan paranoico seas) a través de <a href="http://en.wikipedia.org/wiki/Cron">cron</a> o como sea.</p>
<p>Cualquier mejora es bienvenida. Posiblemente también corra en Windows. Si lograste hacer esto, deja un comentario que pueda serle útil a otros.</p>
<p><strong>¡NUEVA VERSIÓN!</strong> (disponible <a href="http://www.lucianobello.com.ar/rmfb/">aquí</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/rmfb-es/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>φbonacci</title>
		<link>http://www.lucianobello.com.ar/post/%cf%86bonacci/</link>
		<comments>http://www.lucianobello.com.ar/post/%cf%86bonacci/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 22:23:58 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[books & reading]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[φ]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=1026</guid>
		<description><![CDATA[Mi conjunto de números favoritos son los enteros en general y los naturales en particular. Son los primeros números que aprendemos en la vida, sencillos, de apariencia intuitiva pero con poderosas propiedades. Dado que mi amateur aproximación a la matemática se dio por el camino de la teoría de números, fueron mi primer gran amor [...]]]></description>
			<content:encoded><![CDATA[<p>Mi conjunto de números favoritos son <a href="http://es.wikipedia.org/wiki/N%C3%BAmero_entero">los enteros</a> en general y <a href="http://es.wikipedia.org/wiki/N%C3%BAmeros_naturales">los naturales</a> en particular. Son los primeros números que aprendemos en la vida, sencillos, de apariencia intuitiva pero con poderosas propiedades. Dado que mi amateur aproximación a la matemática se dio por el camino de la <a href="http://usuarios.lycos.es/teoriadenumeros/historia.html">teoría de números</a>, fueron mi primer gran amor matemático.<br />
<center><img src="http://upload.wikimedia.org/math/9/7/0/970e61b0fbe1dacbdcf11c86210ef97d.png" alt="" /></center><br />
Sin embargo, no es difícil encontrar fascinante a otros conjuntos de números. Muchas de estos patean el tablero de formas agradables, como <a href="http://es.wikipedia.org/wiki/N%C3%BAmero_complejo">los complejos</a>, que se escaparon de la recta real para irse de vacaciones al <a href="http://es.wikipedia.org/wiki/Diagrama_de_Argand">plano</a>. Entre los más impetuosos contra la intuición están, obviamente, <a href="http://es.wikipedia.org/wiki/N%C3%BAmero_irracional">los irracionales</a>. Y a uno de ellos va dedicado este post.</p>
<p><a href='http://www.lucianobello.com.ar/post/asimov-leibniz-pi-python-floats-y-evadirse-de-la-realidad/'> Hace un par de meses divagué con π</a>. Este semana terminé de leer el libro  <a href='http://www.elbuscon.es/L9788434455313-proporcion-aurea.html'><i>La Proporción Áurea</i> de Mario Livio</a>. Este libro, que evidentemente trata sobre la constante φ (phi), lo compré en Madrid, atraído por la promesa de desasnarme con respecto a la historia de este número.</p>
<p>Primero me gustaría hablarles sobre el libro como tal, el cual resultó sumamente entretenido, aunque tal vez le sobren unas 50 o 100 páginas. Es un paseo por la historia del arte plástico, arquitectónico, escultural y matemático con φ como eje central hilador. Además de dar ejemplos de como se expresan los números en la naturaleza, explica con profundo detalle ciertas propiedades matemáticas en sus numerosos apéndices e invita al lector a pensar sobre porque la matemática encaja también como explicación del universo. Por momentos se va por las ramas pero casi siempre de forma afable y atrapante. Son altamente rescatables los pasajes donde el autor trata con ácida ironía los esfuerzos de los numerólogos de meter a φ lugares arbitrarios cualquiera, como en las dimensiones de Panteón. En mi opinión es un libro altamente recomendable para el aficionado a la matemática y mi calificación (hace mucho que no califico libros con estrellas) es <img src="http://g-ec2.images-amazon.com/images/G/01/x-locale/common/customer-reviews/stars-3-5.gif">.</p>
<p>En segundo lugar quisiera comentar algunas <i>nerdeadas</i> matemáticas inspiradas en el la lectura de este libro. Empezando por lo principio, presentar a quienes no conozcan el número φ, en las palabras de Euclides:<br />
<center><i>Se dice que una línea recta está dividida en el extremo y su proporcional cuando la línea entera es al segmento mayor como el mayor es al menor</i></center><br />
La frase <i>dividida en el extremo y su proporcional</i> hace referencia a la proporción de la que estamos hablando. La definición para mortales es:<br />
<center><img src='http://upload.wikimedia.org/wikipedia/commons/6/65/Image-Golden_ratio_line.png'><br />
La longitud total <em>a+b</em> es al segmento más largo <em>a</em> como <em>a</em> es al segmento más corto <em>b</em><br />
<img src='http://upload.wikimedia.org/math/2/6/a/26aac0b3f0b9b167de1bc16d619472c0.png'></center></p>
<p>El valor en cuestión se puede calcular <a href='http://es.wikipedia.org/wiki/N%C3%BAmero_%C3%A1ureo#Definici.C3.B3n'>despejando algebraicamente tomando b=1</a>, y es:<br />
<img src="http://upload.wikimedia.org/math/1/9/7/19772583149fbdf5a4a4cc751ecf727e.png"><br />
Puede verse que, al igual que π(pi), es un número irracional. Pero, a diferencia de π, es un <a href="http://es.wikipedia.org/wiki/N%C3%BAmero_algebraico">número algebraico</a>, lo que lo emparenta bastante con teoría de números. Sin embargo, su expresión como fracción continua compuesta de solo 1s (unos), hace que converja muy lentamente, convirtiéndolo en <i><a href='http://es.wikipedia.org/wiki/Fracci%C3%B3n_continua#Mejores_aproximaciones_racionales'>el más irracional entre todos los irracionales</a></i>. En términos llanos, φ puede expresarse como la siguiente fracción continua:<br />
<img src="http://upload.wikimedia.org/math/b/3/2/b32ae9361ac6befe1184595499875c6c.png"><br />
Nótese que, cada iteración de esta fracción continua puede expresarse como (los primeros 15 valores, esta secuencia fue resultado de <a href="http://www.lucianobello.com.ar/blog/phi.py">este script</a>):<br />
<tt><br />
2 / 1 = 2<br />
3 / 2 = 1.5<br />
5 / 3 = 1.666666666666666666666666667<br />
8 / 5 = 1.600000000000000000000000000<br />
13 / 8 = 1.625<br />
21 / 13 = 1.615384615384615384615384615<br />
34 / 21 = 1.619047619047619047619047619<br />
55 / 34 = 1.617647058823529411764705882<br />
89 / 55 = 1.618181818181818181818181818<br />
144 / 89 = 1.617977528089887640449438202<br />
233 / 144 = 1.618055555555555555555555556<br />
377 / 233 = 1.618025751072961373390557940<br />
610 / 377 = 1.618037135278514588859416446<br />
987 / 610 = 1.618032786885245901639344262<br />
</tt><br />
Aquel lector atento notará que las fracciones tiene cierto patrón. Por un lado, el numerador de cada reglón pasa a ser el denominador en el siguiente. Los números son:<br />
1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,&#8230;.<br />
¡Exacto! ¡Es la <a href='http://es.wikipedia.org/wiki/Sucesi%C3%B3n_de_Fibonacci'>sucesión de Fibonacci</a>! Cada número es la suma de los dos anteriores. En efecto, siendo F(n) el termino n-ésimo de la serie de Fibonacci:<br />
<img src="http://upload.wikimedia.org/math/2/2/5/225733cd8bc6fd64ffbd6f8c434760bd.png" alt="" /><br />
Así es como puede verse una fuerte relación entre φ y Fibonacci. Y si con Fibonacci se puede calcular la proporción áurea&#8230; ¿cómo es la relación a la inversa?</p>
<p>Con esta formula se puede calcular el valor del término n-ésimo de la serie de Fibonacci:<br />
<img src='http://upload.wikimedia.org/math/9/2/1/921b240159ff0704c70e678ae1ed1eb1.png'><br />
Es fácil reconocer que dentro de esa fórmula está φ.</p>
<p>La propoción áurea φ tiene un montón de raras y divertidas propiedades. Entre las más atractivas se encuentran:<br />
<img src='http://upload.wikimedia.org/math/2/b/8/2b8437ac407db17df893d1aa10cc00e2.png'><br />
<img src='http://upload.wikimedia.org/math/4/a/c/4ac61581f0b9580c002651b191ae7c73.png'><br />
<img src='http://upload.wikimedia.org/math/e/e/c/eecaf197f1e87e5d32c0c4596785b2d8.png'></p>
<p>En lo personal aprendí muchas cosas nuevas sobre la proporción áurea. Pero en el apéndice 9 (como dije, es un libro con muchos apéndices) se comenta un concepto que me voló la cabeza: <a href='http://es.wikipedia.org/wiki/Ley_de_Benford'>la ley de Benford</a>. El tema se toca tangencialmente, promediando el último capítulo, como un ejemplo de como las matemáticas sorprenden. Y sí que lo hacen.</p>
<p>Pero ese será tema del siguiente post.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/%cf%86bonacci/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Asimov, Leibniz, pi, python, floats y evadirse de la realidad</title>
		<link>http://www.lucianobello.com.ar/post/asimov-leibniz-pi-python-floats-y-evadirse-de-la-realidad/</link>
		<comments>http://www.lucianobello.com.ar/post/asimov-leibniz-pi-python-floats-y-evadirse-de-la-realidad/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 00:10:00 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[books & reading]]></category>
		<category><![CDATA[favorites]]></category>
		<category><![CDATA[procrastination]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[π]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=896</guid>
		<description><![CDATA[La matemática tiene cosas sorprendentemente lindas. Y una de las que siempre me gustó de forma especial es la formula de Leibniz para el cálculo de π. También conocida como la serie de Gregory-Leibniz es una simpática manera de expresar el más famoso de los números irracionales: O para aquellos no gustan de las notación [...]]]></description>
			<content:encoded><![CDATA[<p>La matemática tiene cosas sorprendentemente lindas. Y una de las que siempre me gustó de forma especial es <a href="http://en.wikipedia.org/wiki/Leibniz_formula_for_pi">la formula de Leibniz para el cálculo de π</a>. También conocida como la serie de Gregory-Leibniz es una simpática manera de expresar el más famoso de los números irracionales:<br />
<img src="http://www.lucianobello.com.ar/blog/pi2.png" alt="" align="middle" /><br />
O para aquellos no gustan de las notación <a href="http://en.wikipedia.org/wiki/Summation#Capital-sigma_notation">sigma-grande</a>:<br />
<img src="http://www.lucianobello.com.ar/blog/pi1.png" alt="" align="middle" /><br />
Como verán, se trata de una serie sumamente simple y elegante. Y como suele ocurrir con estas cosas, aparecen en la vida de uno en momentos extraños, casi que al rescate.</p>
<p><img title="pi" src="http://imgs.xkcd.com/comics/pi.jpg" alt="" width="469" height="247" align="left" />Anoche me hallé frente a la biblioteca buscando nada en espacial. Necesitaba despejar la cabeza, olvidarme de los asuntos terrenales asociados con las complejas interacciones y relaciones humanas.</p>
<p>Fue en esa circunstancia que me encuentro con <em><a href="http://www.tematica.com.ar/libros/ciencias_de_la_salud__naturales_y_divulgacion_cientifica--7/divulgacion_cientifica--1/en_general--1/de_los_numeros_y_su_historia--119120.htm">De los números y su historia</a></em> de <a href="http://es.wikipedia.org/wiki/Isaac_Asimov">Isaac Asimov</a> (que puede ser descargado desde <a href="http://www.librosmaravillosos.com/delosnumerosysuhistoria/index.html">aquí</a>). Mientras lo hojeaba vi la formula de Leibniz, promediando el <a href="http://www.librosmaravillosos.com/delosnumerosysuhistoria/capitulo06.html">capítulo 6</a> e inmediatamente atrajo mi atención.</p>
<p>Después de expresar la serie, Asimov explica:</p>
<p><em>&lt;&lt;Ustedes podrán condenar mi falta de perseverancia, pero los invito a calcular la serie de Leibniz simplemente hasta donde la hemos escrito más arriba, es decir hasta 4/15. Incluso pueden enviarme una postal para darme el resultado. Si al terminar se sienten desilusionados al descubrir que su respuesta no está tan cerca de π como lo está el valor 355/113, no se den por vencidos. Sigan sumando términos. Sumen 4/17 al resultado anterior, luego resten 4/19, después sumen 4/21 y resten 4/23, etcétera. Pueden seguir hasta donde lo deseen, y si alguno de ustedes descubre cuántos términos se requieren para mejorar el valor 355/113, escríbanme unas líneas y no dejen de decírmelo. &gt;&gt;</em><br />
En efecto, la fracción <a href="http://www.google.com/search?q=355%2F113">355/113</a> parece ser la forma que mejor balancea precisión y simpleza a la hora de arrimarse a π desde lo números racionales, quedando a solo <a href="“http://www.google.com/search?q=355%2F113-pi”">2.66764189 × 10<sup>-7</sup> de distancia</a>. Mucha gente también utiliza la relación 22/7, aunque con menor precisión.</p>
<p>El desafío propuesto parecía interesante. Resultaba una entretenida oportunidad de jugar con <a href="http://docs.python.org/tut/node16.html">floats en python</a>, que siempre a resultado ser bastante <a href="http://www.wordreference.com/es/translation.asp?tranword=tricky">tricky</a> (además de ser un excusa para despejar la cabeza).</p>
<p>Empecé por escribir una <a href="http://www.lucianobello.com.ar/blog/asimov_simple.py">versión relativamente obvia</a> de la solución, que me dijo que al llegar al cociente 7497257 (n=3748629 en la sumatoria de Leibniz) el valor de la sumatoria estaría en 3.14159292035, quedando a 2.66764081935 x 10<sup>-7</sup> de π. Dado que los decimales (floats, representaciones de punto flotante) en Python <a href="http://www.google.com/search?q=python+&quot;0.10000000000000001&quot;+&quot;0.1&quot;">no se comportan de forma intuitiva</a>, decidí hacer <a href="http://www.lucianobello.com.ar/blog/asimov.py">una segunda versión</a>.</p>
<p>En <a href="http://www.lucianobello.com.ar/blog/asimov.py">esta versión</a> traté de mudarme al predecible mundo de los enteros. Y obtuve valores levemente distintos. En el cociente 7497247 (n=3748624) se obtiene la primera aproximación mejor que 355/113, que es 3.141592386825&#8230;  (a 2.66764162 x 10<sup>-7</sup> de π)</p>
<p>Tampoco estoy seguro de que la segunda solución sea la correcta. Me pregunto cual será el promedio de valores en las postales que la <a href="http://en.wikipedia.org/wiki/Janet_Asimov">viuda Asimov</a> seguramente guarda en una caja de zapatos.</p>
<p>El hecho es que fue entretenido intentarlo y tal vez continúe con la experiencia la próxima vez que quiera desconectarme del mundo. Después de todo, como dijo el mismo <a href="http://es.wikiquote.org/wiki/Isaac_Asimov">Asimov</a>: <em>“Los hombres que se acostumbran a preocuparse por las necesidades de unas máquinas, se vuelven insensibles respecto a las necesidades de los hombres”</em>, y hay veces que volverse insensible se ve, erróneamente, como una propuesta seductora. Hay gente que ahoga penas en alcohol, mucho más sano es ahogarlas matemáticas&#8230;</p>
<p>BTW, ya que tenía los datos armé un<a href="http://www.lucianobello.com.ar/blog/leibniz_principio.png"> plot de los primeros 1000 valores</a> de la serie para mostrar de forma gráfica la convergencia.</p>
<p>Ahora es momento de volver a la realidad, que buena o mala, irracional o racional (seguro que real al menos), inexacta o precisa, después de este recreo metal ya no se ve tan mal :-)</p>
<p><strong>UPDATE: Sat, 20 Sep 2008 22:18:18 -0300:</strong> La solución estaba realmente cerca (en mi misma ciudad) y se llama <a href="http://www.taniquetil.com.ar/plog/">Facundo</a>, quien dejó un <a href="http://www.lucianobello.com.ar/post/asimov-leibniz-pi-python-floats-y-evadirse-de-la-realidad/#comment-801">comentario</a>. Bah.. se llama <a href="http://docs.python.org/lib/module-decimal.html">decimal</a>, pero existe gracias a Facundo :). La <a href="http://docs.python.org/lib/module-decimal.html">biblioteca  decimal</a> permite manejar de forma exacta una cantidad arbitraria de decimales. La respuesta correcta es&#8230;&#8230;.. (redoblantes de suspenso) con <strong>n=(7497259+1)/2! aproxima a Π en 3.141592386825668744985771256 a solo 2.66764125 × 10<sup>-7</sup> del número irracional</strong>. El nuevo script.. <a href="http://www.lucianobello.com.ar/blog/asimov_decimal.py">aquí</a>.</p>
<p>Gracias Facundo, gracias decimal, gracias Asimov, gracias Leibniz&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/asimov-leibniz-pi-python-floats-y-evadirse-de-la-realidad/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>sudoku, algorítmos genéticos, la estrategia backtracking, programación lineal y R</title>
		<link>http://www.lucianobello.com.ar/post/sudoku-algoritmos-geneticos-la-estrategia-backtracking-programacion-lineal-y-r/</link>
		<comments>http://www.lucianobello.com.ar/post/sudoku-algoritmos-geneticos-la-estrategia-backtracking-programacion-lineal-y-r/#comments</comments>
		<pubDate>Wed, 16 May 2007 20:16:00 +0000</pubDate>
		<dc:creator>luciano</dc:creator>
				<category><![CDATA[academy]]></category>
		<category><![CDATA[favorites]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[procrastination]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[university]]></category>

		<guid isPermaLink="false">http://www.lucianobello.com.ar/?p=845</guid>
		<description><![CDATA[/* Habiendo leído El curioso incidente del perro a medianoche le tomé cierto buen gusto a los títulos largos :-) */ Hace unas semanas, Mahoo me regaló un pequeño libro con un montón de sudokus para resolver. Si bien conocía el juego, nunca me atrajo particularmente. En esos días, yo estaba buscando algún tema original [...]]]></description>
			<content:encoded><![CDATA[<p>/* Habiendo leído <a href="http://www.ociojoven.com/article/articleview/948974/"><em>El curioso incidente del perro a medianoche</em></a> le tomé cierto buen gusto a los títulos largos :-) */</p>
<p><img src="http://farm1.static.flickr.com/228/498135954_f8dd8b4b08_m.jpg" alt="" align="right" />Hace unas semanas, <a href="http://www.asciigirl.com">Mahoo</a> me regaló un pequeño libro con un montón de <a href="http://www.sudoku.com/">sudokus</a> para resolver. Si bien conocía el juego, nunca me atrajo particularmente. En esos días, yo estaba buscando algún tema original para uno de los trabajos prácticos de <em>Inteligencia Artificial</em>. La consigna se refería al uso de <a href="http://es.wikipedia.org/wiki/Algoritmo_gen%C3%A9tico">algoritmos genéticos</a> para la resolución de algún problema. Lo importante no era el programa, sino el análisis de su comportamiento: estudiando, por ejemplo, qué <a href="http://en.wikipedia.org/wiki/Crossover_%28genetic_algorithm%29">método de cruzamiento</a> se aplica mejor o qué <a href="http://en.wikipedia.org/wiki/Fitness_function">función de aptitud</a> es más representativa.</p>
<p>Viendo como Mahoo se entretenía con alguno de ellos (práctica en la que también se iniciaba) se me ocurrió que un <em>resolver de sudokus</em> podría ser una linda propuesta para mi TP.</p>
<p><a href="http://www.genetic-programming.com/">Los algoritmos genéticos</a> intentan emular a la naturaleza, a base de prueba y error, favoreciendo a las soluciones más aptas y castigando a las que no lo son tanto. Suponiendo que el <em>cruzamiento</em> de las <em>buenas-soluciones</em> generan <em>aún-mejores-soluciones</em>. Se trata de la búsqueda probabilística, muy parecida a meter muchas soluciones en un <a href="http://images.google.com/images?q=cubilete">cubilete</a> gigante y agitarlas hasta encontrar algo útil.</p>
<p>Al tratarse de un problema determinístico, la solución dista muchísimo de ser óptima. De hecho, ni siquiera se asegura que vaya a haber una solución. Pero me pareció algo simpático de intentar.</p>
<p>El resultado, escrito en mi rústico <a href="http://www.python.org/">Python</a>, puede ser bajado de <a href="http://www.lucianobello.com.ar/miSudoku.tar.gz">aquí</a> (incluye instrucciones para correrlo en Windows). No, no esperen que funcione bien, advertidos están. Es uno de los peores métodos posibles para este tipo de problemas. Sólo llega a una solución cuando la cantidad de incógnitas es (muy) limitada. Se plantean soluciones a base de llenar de random cada uno de los casilleros vacíos y chequeando cuantos valores se repiten en cada fila, columna y región. Cuando este chequeo da 0, se llega a una solución. Bastante cavernícola como notarán.</p>
<p>Es natural pensar en cuál sería la forma correcta de llegar a una solución. Recordé las clases de <em>Investigación Operativa</em> y la utilización del <a href="http://www.phpsimplex.com/pages/teoria.htm">método simplex</a> para la solución a problemas con restricciones. De hecho, es una solución que <a href="http://www.google.com/search?q=simplex+sudoku+%22Linear+Programming%22">muchos proponen</a>. No se si alguno de ustedes lo ha intentado. Yo sí, durante las clases aburridas me senté a pensar como sería el conjunto de ecuaciones y me encontré con una demencial y frustrante cantidad de ecuaciones. <a href="ftp://ftp.math.tu-berlin.de/pub/Lehre/LinOpt/WS06/Uebung18.10.06/SudokuH.pdf">Acá</a> hay una linda explicación, la que resumo, haciendo énfasis en las complicaciones:<br />
Se necesitan variables binarias de la forma x<sub>ijk</sub> donde 1 significa que el símbolo <em>k</em> (de 1 a 9) va en la celda <em>(i,j)</em> de la solución. 0 significa que no está. Esto genera un total de <em>729 variables</em> (9<sup>3</sup>) lo que, como mínimo, asusta. Veamos las ecuaciones:<br />
<img src="http://www.lucianobello.com.ar/blog/sudokuSimplex.jpg" alt="" align="center" /><br />
<strong>(1)</strong> Para que cada celda <em>(i,j)</em> tenga un símbolo y éste sea único. Se necesitan 81 ecuaciones como éstas (una por cada celda).<br />
<strong>(2)</strong> Para que en la fila <em>i</em> cada símbolo esté una vez y que en todas las columnas sea distinto. Se necesitan 81 ecuaciones como éstas(una por cada columna y cada símbolo posible).<br />
<strong>(3)</strong> Para que en la columna <em>j</em> cada símbolo esté una vez y que en todas las filas sea distinto. Se necesitan 81 ecuaciones como éstas(una por cada fila y cada símbolo posible).<br />
<strong>(4)</strong> Para que en cada región cada símbolo esté una y solo una vez. Se necesitan 81 ecuaciones como éstas (una por cada región y cada símbolo posible).<br />
<strong>(5)</strong> Representa el enunciado, es decir, el problema a resolver. Por ejemplo, x<sub>115</sub>=1 significa que en la celda (1,1) hay un 5. Dependiendo cuantos casilleros vengan asignados es la cantidad de igualdades como estas que se necesitan; típicamente, ~30.<br />
<strong>(6)</strong> Restringe las variables al conjunto binario.</p>
<p>¡En total son <strong>más de 350 ecuaciones</strong>! Hay <a href="http://www.sudoku.com/forums/viewtopic.php?p=720&amp;sid=401c15a1aac8ef33e6056a968f0c1f7a">propuestas</a> con menos ecuaciones, pero siempre serán muchísimas. Evidentemente, ésta tampoco es la solución óptima (aunque es mucho mejor que los algoritmos genéticos). Y su problema radica en que, desde algún punto de vista, el método simplex no se ajusta al problema. Gráficamente, las ecuaciones representan semiplanos en un hiperespacio multidimencional (de 9 dimensiones?) cuya intersección es, en caso que haya una única solución, un único punto. /* Puede que le esté pifiando en esta conclusión final y cualquier ratificación o rectificación es bienvenida */</p>
<p>Simplex está pensado para restricciones de máximos y mínimos donde el objetivo es maximizar o minimizar y las variables binarias intentan ampliar el método para restricciones de este tipo. Da soluciones múltiples en forma de un polígono, donde a una o más se las llama <em>óptima</em>, porque maximiza o minimiza la función objetivo. Es claro que el problema del sudoku no usa sus ventajas y abusa de sus debilidades.</p>
<p>Curiosamente, cuando comenté este problema a un <a href="http://www.opensolaris.org//viewProfile.jspa?id=11967">reciente conocido</a>, surgió que también él tuvo que hacer un trabajo práctico que resolvía sudokus. En este caso, el TP giraba entorno a la gestión de la pila para recorrer árboles. Particularmente, árboles empleados en <a href="http://es.wikipedia.org/wiki/Vuelta_Atr%C3%A1s">la estrategia de backtracking</a>. Así pues, <a href="http://www.lucianobello.com.ar/sudokuBT.tar.gz">éste</a> es su programita, sencillo, simpático y rápido. Gracias Nacho :).</p>
<p>Los métodos basados en búsqueda combinatoria sobre árboles parecen ser particularmente buenas para el problema del sudoku. En la wikipedia figuran dos interesantes formas: <a href="http://es.wikipedia.org/wiki/Sudoku_backtracking">backtracking</a> y  <a href="http://es.wikipedia.org/wiki/Sudoku_ramificaci%C3%B3n_y_poda">ramificación y poda</a>.</p>
<p>Para terminar, una última casualidad: Por razones que no vienen al caso ahora y que seguramente provocarán un nuevo post en el futuro estoy aprendiendo un lenguaje para el procesamiento de señales llamado <a href="http://www.r-project.org/">R</a>. Estoy trabajando mucho con una biblioteca llamada <em><a href="http://cran.r-project.org/src/contrib/Descriptions/sound.html">sound</a></em>. Buscándola en el repositorio de bibliotecas, me encuentro con una llamada <em><a href="http://cran.r-project.org/src/contrib/Descriptions/sudoku.html">sudoku</a></em>. No resistí la tentación de probarla :). Un ejemplo de su uso:</p>
<pre>&gt; <strong>install.packages("sudoku")</strong>
&gt; <strong># es necesario instalar tcltk si se quiere la parte gráfica</strong>
&gt; <strong>install.packages("tcltk")</strong>
&gt; <strong>library(sudoku)</strong>
&gt; <strong>library(tcltk)</strong>
&gt; <strong>library(tkrplot)</strong>
&gt; <strong>miSudoku &lt;- generateSudoku(Nblank=50, print.it=TRUE)</strong>
  +-------+-------+-------+
  |   6   |   7   |   8 2 |
  | 4 8   |     1 | 7     |
  |       | 8 2   | 5     |
  +-------+-------+-------+
  |       | 1     | 9 7   |
  |       |     2 |   5 1 |
  | 5 1 6 |   9 7 |       |
  +-------+-------+-------+
  |       |   4 8 |       |
  | 6 5   | 7   9 | 8     |
  |       |       |   9 7 |
  +-------+-------+-------+
&gt; <strong># la variable miSudoku es una matriz</strong>
&gt; <strong>miSudoku</strong>
       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
 [1,]    0    6    0    0    7    0    0    8    2
 [2,]    4    8    0    0    0    1    7    0    0
 [3,]    0    0    0    8    2    0    5    0    0
 [4,]    0    0    0    1    0    0    9    7    0
 [5,]    0    0    0    0    0    2    0    5    1
 [6,]    5    1    6    0    9    7    0    0    0
 [7,]    0    0    0    0    4    8    0    0    0
 [8,]    6    5    0    7    0    9    8    0    0
 [9,]    0    0    0    0    0    0    0    9    7
&gt; <strong>#La biblioteca incluye una función para para solucionarlo</strong>
&gt; <strong>solveSudoku(miSudoku)</strong>
       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
 [1,]    1    6    5    9    7    3    4    8    2
 [2,]    4    8    2    5    6    1    7    3    9
 [3,]    3    7    9    8    2    4    5    1    6
 [4,]    2    4    8    1    5    6    9    7    3
 [5,]    7    9    3    4    8    2    6    5    1
 [6,]    5    1    6    3    9    7    2    4    8
 [7,]    9    3    7    2    4    8    1    6    5
 [8,]    6    5    1    7    3    9    8    2    4
 [9,]    8    2    4    6    1    5    3    9    7
&gt; <strong># Incluso trae soporte gráfico para resolverlo en una ventanita :)</strong>
&gt; <strong>playSudoku()</strong></pre>
<p>Así fue como, un simple regalo, un TP universitario y un montón de simpáticas casualidades tuvieron su punto de conexión. Y que divertido que resultó ser :). Ahora tengo que escribir el informe sobre los algoritmos genéticos en el sudoku. La semana que viene espero publicarlo <a href="http://www.lucianobello.com.ar/sudoku/">aquí</a>.</p>
<p><strong>UPDATE August 6th</strong>: El informe y los archivos relacionados <a href="http://www.lucianobello.com.ar/sudoku/">ya está publicados</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lucianobello.com.ar/post/sudoku-algoritmos-geneticos-la-estrategia-backtracking-programacion-lineal-y-r/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

