<?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>El vol de l&#039;home ocell &#187; Programació</title>
	<atom:link href="http://www.elvoldelhomeocell.net/archives/category/geek/informatica/programacio/feed" rel="self" type="application/rss+xml" />
	<link>http://www.elvoldelhomeocell.net</link>
	<description>Vull tenir dret a volar.</description>
	<lastBuildDate>Fri, 13 Jan 2012 10:15:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Correcció automàtica en l&#8217;Oracle: Trie</title>
		<link>http://www.elvoldelhomeocell.net/archives/1553</link>
		<comments>http://www.elvoldelhomeocell.net/archives/1553#comments</comments>
		<pubDate>Sat, 05 Nov 2011 16:20:41 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Jo]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[Projectes]]></category>
		<category><![CDATA[algorismes]]></category>
		<category><![CDATA[cerca aproximada]]></category>
		<category><![CDATA[complexitat computacional]]></category>
		<category><![CDATA[correcció automàtica]]></category>
		<category><![CDATA[estructures de dades]]></category>
		<category><![CDATA[friki]]></category>
		<category><![CDATA[oracle de woody allen]]></category>
		<category><![CDATA[trie]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/?p=1553</guid>
		<description><![CDATA[Continuem amb la segona alternativa que vaig fer servir per a permetre la correcció automàtica, o si voleu cerca aproximada. Ja us vaig comentar en l&#8217;anterior entrada els problemes que presenta la cerca dicotòmica amb cadenes ordenades per ordre lexicogràfic &#8230; <a href="http://www.elvoldelhomeocell.net/archives/1553">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Continuem amb la <a href="http://www.elvoldelhomeocell.net/archives/1515" target="_blank">segona</a> alternativa que vaig fer servir per a permetre la <a href="http://en.wikipedia.org/wiki/Spell_checker" target="_blank">correcció automàtica</a>, o si voleu <a href="http://en.wikipedia.org/wiki/Approximate_string_matching" target="_blank">cerca aproximada</a>.</p>
<p>Ja us vaig comentar en l&#8217;anterior entrada els problemes que presenta la cerca dicotòmica amb cadenes ordenades per ordre lexicogràfic per a buscar alternatives a una cerca que conté algun error. Semblava doncs que l&#8217;ordre lexicogràfic no era suficient per a establir la relació que jo necessitava entre els noms de les persones, així que la segona idea que vaig tenir és la d&#8217;utilitzar la famosa <a href="http://en.wikipedia.org/wiki/Levenshtein_distance" target="_blank">distància de Levenshtein</a>.</p>
<p>Sols comentar que quan estava escrivint aquest post em vaig adonar que tenia un greu error en el meu algorisme, de fet vaig haver de canviar-lo. Això em va servir per a entendre bé aquest nou algorisme que explique ací i millorar alguns aspectes en la implementació del meu programa. Eixe és el motiu pel qual m&#8217;ha dut quasi una setmana publicar aquesta entrada.</p>
<p>Avisar-vos també que aquest post és molt més llarg i pesat que l&#8217;anterior, això sí, molt més interessant també. Els algorismes que ací descric no són cosa meua i poden haver errors en la descripció de l&#8217;algorisme o la seva complexitat. Evidentment, aquest blog no tracta de ser una font de referència i no deuríeu de confiar excessivament en els detalls que s&#8217;expliquen ja que poden ser imprecisos o inclús erronis. Si us interessa el tema i voleu informació en la que pugueu confiar més, sols heu de cercar els termes en articles de la <a href="http://en.wikipedia.org" target="_blank">Wikipedia</a> o els algorismes en publicacions de <a href="http://scholar.google.com/" target="_blank">Google Scholar</a>.</p>
<p>Fet aquest avís, comencem.</p>
<p><strong id="damerau-levenshtein">Distància de Damerau-Levenshtein</strong></p>
<p>La <a href="http://en.wikipedia.org/wiki/Levenshtein_distance" target="_blank">distància de Levenshtein</a> mesura la distància d&#8217;edició entre dues cadenes de text en termes d&#8217;insercions, esborrats i substitucions. Això és, el nombre mínim d&#8217;aquestes operacions que són necessàries per transformar una cadena <em>A</em> en una altra cadena <em>B</em>. Si volem comptar també les transposicions com a operacions, la mètrica s&#8217;anomena distància de <a href="http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance" target="_blank">Damerau-Levenshtein</a>. L&#8217;algorisme utilitzat per a computar aquesta mètrica és un clàssic de qualsevol curs de <a href="http://en.wikipedia.org/wiki/Dynamic_programming" target="_blank">programació dinàmica</a>. </p>
<p>Intentaré explicar l&#8217;algorisme de manera breu. Imaginem que volem calcular la distància d&#8217;una cadena <em>X</em> a una cadena <em>Y</em>. Llavors és construeix una matriu <em>D</em> de <em>|X|+1</em> files i <em>|Y|+1</em> columnes. L&#8217;element <img src='http://s.wordpress.com/latex.php?latex=D_%7Bij%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='D_{ij}' title='D_{ij}' class='latex' /> indica quina és la distància de la subcadena <img src='http://s.wordpress.com/latex.php?latex=x_1%20%5Cldots%20x_i&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x_1 \ldots x_i' title='x_1 \ldots x_i' class='latex' /> a la subcadena <img src='http://s.wordpress.com/latex.php?latex=y_1%20%5Cldots%20y_j&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='y_1 \ldots y_j' title='y_1 \ldots y_j' class='latex' />. La fila 0 i la columna 0 representen les distàncies de la cadena <img src='http://s.wordpress.com/latex.php?latex=%5Cepsilon&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\epsilon' title='\epsilon' class='latex' /> a <img src='http://s.wordpress.com/latex.php?latex=y_1%20%5Cldots%20y_j&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='y_1 \ldots y_j' title='y_1 \ldots y_j' class='latex' /> i de la cadena <img src='http://s.wordpress.com/latex.php?latex=x_1%20%5Cldots%20x_i&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x_1 \ldots x_i' title='x_1 \ldots x_i' class='latex' /> a <img src='http://s.wordpress.com/latex.php?latex=%5Cepsilon&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\epsilon' title='\epsilon' class='latex' /> respectivament (<img src='http://s.wordpress.com/latex.php?latex=%5Cepsilon&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\epsilon' title='\epsilon' class='latex' /> és la cadena buida, aquella que no conté cap símbol).</p>
<p>Doncs bé, la fórmula per a calcular cada element de la taula és la següent.<img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2011/11/formula_d.png" alt="" title="formula_d" width="300" height="120" class="aligncenter size-full wp-image-1605" /></p>
<p><img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2011/11/formula_s.png" alt="" title="formula_s" width="138" height="43" class="aligncenter size-full wp-image-1606" /></p>
<p><img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2011/11/formula_t.png" alt="" title="formula_t" width="213" height="43" class="aligncenter size-full wp-image-1607" /></p>
<p>Ací teniu un exemple de com quedaria matriu per a les cadenes <em>hola</em> i <em>poal</em>.</p>
<p style="text-align: center;"><img src='http://s.wordpress.com/latex.php?latex=%20%20%5Cbegin%7Barray%7D%7B%7Cc%7Cc%7Cc%7Cc%7Cc%7Cc%7C%7D%20%20%5Chline%20D%20%26%20%5Cepsilon%20%26%20p%20%26%20o%20%26%20a%20%26%20l%20%5C%5C%20%20%5Chline%20%5Cepsilon%20%26%200%20%26%201%20%26%202%20%26%203%20%26%204%20%5C%5C%20%20%5Chline%20h%20%26%201%20%26%201%20%26%202%20%26%203%20%26%204%5C%5C%20%20%5Chline%20o%20%26%202%20%26%202%20%26%201%20%26%202%20%26%203%5C%5C%20%20%5Chline%20l%20%26%203%20%26%203%20%26%202%20%26%202%20%26%202%5C%5C%20%20%5Chline%20a%20%26%204%20%26%204%20%26%203%20%26%202%20%26%202%5C%5C%20%20%5Chline%20%20%5Cend%7Barray%7D%20%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='  \begin{array}{|c|c|c|c|c|c|}  \hline D &amp; \epsilon &amp; p &amp; o &amp; a &amp; l \\  \hline \epsilon &amp; 0 &amp; 1 &amp; 2 &amp; 3 &amp; 4 \\  \hline h &amp; 1 &amp; 1 &amp; 2 &amp; 3 &amp; 4\\  \hline o &amp; 2 &amp; 2 &amp; 1 &amp; 2 &amp; 3\\  \hline l &amp; 3 &amp; 3 &amp; 2 &amp; 2 &amp; 2\\  \hline a &amp; 4 &amp; 4 &amp; 3 &amp; 2 &amp; 2\\  \hline  \end{array}  ' title='  \begin{array}{|c|c|c|c|c|c|}  \hline D &amp; \epsilon &amp; p &amp; o &amp; a &amp; l \\  \hline \epsilon &amp; 0 &amp; 1 &amp; 2 &amp; 3 &amp; 4 \\  \hline h &amp; 1 &amp; 1 &amp; 2 &amp; 3 &amp; 4\\  \hline o &amp; 2 &amp; 2 &amp; 1 &amp; 2 &amp; 3\\  \hline l &amp; 3 &amp; 3 &amp; 2 &amp; 2 &amp; 2\\  \hline a &amp; 4 &amp; 4 &amp; 3 &amp; 2 &amp; 2\\  \hline  \end{array}  ' class='latex' /></p>
<p>Si mirem l&#8217;element <img src='http://s.wordpress.com/latex.php?latex=D_%7B4%2C4%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='D_{4,4}' title='D_{4,4}' class='latex' /> de la taula, veiem que la distància de Damerau-Levenshtein entre les dues cadenes és 2 (transformacion: <em>hola</em>-><em>pola</em>-><em>poal</em>). Fixeu-vos que és menor que la distància de Levenshtein (que no admet transposicions) i que seria 3.</p>
<p>La gràcia d&#8217;aquest algorisme és que pot anar construint-se fila a fila i columna a columna, de manera que el cost temporal de l&#8217;algorisme per a dues cadenes de longituds <em>m</em> i <em>n</em> és <img src='http://s.wordpress.com/latex.php?latex=O%28m%20%5Ccdot%20n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(m \cdot n)' title='O(m \cdot n)' class='latex' />, a l&#8217;igual que el cost espacial.</p>
<p>El problema d&#8217;aquesta mètrica és el cost: no és lineal. No era una alternativa adequada simplement computar per a cada cerca la seva distància de Damerau-Levenshtein amb els noms de les persones i quedar-me amb aquelles amb un mínim error. Suposant que tenim <em>n</em> persones i la longitud dels seus noms és aproximadament <em>l</em>, el cost temporal d&#8217;aquesta cerca seria <img src='http://s.wordpress.com/latex.php?latex=O%28n%20%5Ccdot%20l%5E2%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(n \cdot l^2)' title='O(n \cdot l^2)' class='latex' />, un cost massa alt si el comparem amb el de la cerca dicotòmica (<img src='http://s.wordpress.com/latex.php?latex=O%28l%20%5Ccdot%20%5Clog_2%20n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(l \cdot \log_2 n)' title='O(l \cdot \log_2 n)' class='latex' />).</p>
<p><strong id="damerau-levenshtein-ukkonen">Millora d&#8217;Ukkonen</strong></p>
<p>El primer que hem de tenir clar és que no necessitem saber la distància exacta entre dues paraules. Imaginem que un usuari s&#8217;equivoca escrivint la paraula que busca i escriu <em>ocel</em>. Què serà més probable, que l&#8217;usuari estigués buscant una paraula que està a una distància 1 (p.ex: <em>ocell</em>) o que estigués buscant una paraula a una distància 5 (p.ex: <em>tomaca</em>)? Realment, sols estem interessats en saber si la distància entre dues cadenes <em>X</em> i <em>Y</em> és menor o igual que un cert llindar <em>k</em>.</p>
<p>Si estem calculant la distància entre dues cadenes i tenim una fila per a la qual, cap element és menor o igual que <em>k</em>, llavors cap element de les següents files serà menor o igual que <em>k</em>.</p>
<p>A més, siga <img src='http://s.wordpress.com/latex.php?latex=C_i%20%3D%20j&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='C_i = j' title='C_i = j' class='latex' />, l&#8217;última columna <em>j</em> per a la fila <em>i</em> tal que <img src='http://s.wordpress.com/latex.php?latex=D_%7Bi%2Cj%7D%20%5Cleq%20k&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='D_{i,j} \leq k' title='D_{i,j} \leq k' class='latex' />, llavors quan construïm la fila <em>i</em> sols haurem de fer-ho fins la columna <img src='http://s.wordpress.com/latex.php?latex=C_%7Bi-1%7D%2B1&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='C_{i-1}+1' title='C_{i-1}+1' class='latex' />, ja que els elements de les columnes posteriors tindran un valor <img src='http://s.wordpress.com/latex.php?latex=D_%7Bi%2Cj%7D%20%3E%20k&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='D_{i,j} &gt; k' title='D_{i,j} &gt; k' class='latex' />.</p>
<p>Ací teniu un exemple de com quedaria la matriu per a les cadenes <em>hola</em> i <em>poal</em>, amb un valor de <em>k</em> igual a 1.</p>
<p style="text-align: center;"><img src='http://s.wordpress.com/latex.php?latex=%20%20%5Cbegin%7Barray%7D%7B%7Cc%7C%7Cc%7Cc%7Cc%7Cc%7Cc%7Cc%7C%7D%20%20%5Chline%20C%20%26%20D%20%26%20%5Cepsilon%20%26%20p%20%26%20o%20%26%20a%20%26%20l%20%5C%5C%20%20%5Chline%201%20%26%20%5Cepsilon%20%26%200%20%26%201%20%26%20%20%26%20%20%26%20%20%5C%5C%20%20%5Chline%201%20%26%20h%20%26%201%20%26%201%20%26%202%20%26%20%20%26%20%5C%5C%20%20%5Chline%202%20%26%20o%20%26%202%20%26%202%20%26%201%20%26%20%20%26%20%5C%5C%20%20%5Chline%200%20%26%20l%20%26%203%20%26%203%20%26%202%20%26%202%20%26%20%5C%5C%20%20%5Chline%200%20%26%20a%20%26%20%20%26%20%20%26%20%20%26%20%20%26%20%5C%5C%20%20%5Chline%20%20%5Cend%7Barray%7D%20%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='  \begin{array}{|c||c|c|c|c|c|c|}  \hline C &amp; D &amp; \epsilon &amp; p &amp; o &amp; a &amp; l \\  \hline 1 &amp; \epsilon &amp; 0 &amp; 1 &amp;  &amp;  &amp;  \\  \hline 1 &amp; h &amp; 1 &amp; 1 &amp; 2 &amp;  &amp; \\  \hline 2 &amp; o &amp; 2 &amp; 2 &amp; 1 &amp;  &amp; \\  \hline 0 &amp; l &amp; 3 &amp; 3 &amp; 2 &amp; 2 &amp; \\  \hline 0 &amp; a &amp;  &amp;  &amp;  &amp;  &amp; \\  \hline  \end{array}  ' title='  \begin{array}{|c||c|c|c|c|c|c|}  \hline C &amp; D &amp; \epsilon &amp; p &amp; o &amp; a &amp; l \\  \hline 1 &amp; \epsilon &amp; 0 &amp; 1 &amp;  &amp;  &amp;  \\  \hline 1 &amp; h &amp; 1 &amp; 1 &amp; 2 &amp;  &amp; \\  \hline 2 &amp; o &amp; 2 &amp; 2 &amp; 1 &amp;  &amp; \\  \hline 0 &amp; l &amp; 3 &amp; 3 &amp; 2 &amp; 2 &amp; \\  \hline 0 &amp; a &amp;  &amp;  &amp;  &amp;  &amp; \\  \hline  \end{array}  ' class='latex' /></p>
<p>Si consultem el valor de l&#8217;element <img src='http://s.wordpress.com/latex.php?latex=D_%7Bi%2Cj%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='D_{i,j}' title='D_{i,j}' class='latex' /> aquest sols és vàlid si <img src='http://s.wordpress.com/latex.php?latex=C_i%20%3E%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='C_i &gt; 0' title='C_i &gt; 0' class='latex' />. Si no és així, sabem que <img src='http://s.wordpress.com/latex.php?latex=D_%7Bi%2Cj%7D%20%3E%20k&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='D_{i,j} &gt; k' title='D_{i,j} &gt; k' class='latex' />.</p>
<p>Doncs bé, tenint en compte aquesta millora, el cost temporal de l&#8217;algorisme es redueix a <img src='http://s.wordpress.com/latex.php?latex=O%28k%5E2%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(k^2)' title='O(k^2)' class='latex' />, segons diu la <a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.37.2019&#038;rep=rep1&#038;type=pdf" target="_blank">publicació</a> d&#8217;on vaig treure l&#8217;algorisme.</p>
<p>Així i tot, no resulta interessant aplicar aquest algorisme sobre tots els noms ja que el cost estaria en <img src='http://s.wordpress.com/latex.php?latex=O%28n%20%5Ctimes%20k%5E2%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(n \times k^2)' title='O(n \times k^2)' class='latex' />. Per a <em>k</em> xicotetes és molt menor que <img src='http://s.wordpress.com/latex.php?latex=O%28n%20%5Ctimes%20l%5E2%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(n \times l^2)' title='O(n \times l^2)' class='latex' /> de la idea original, però que encara es pot millorar.</p>
<p>Necessitava tenir els noms de les persones representats d&#8217;alguna manera per a estalviar-me treball reduir aquest cost. I ací és on entren en joc els <em><a href="http://en.wikipedia.org/wiki/Trie" target="_blank">tries</a></em>.</p>
<p><strong id="trie">Trie</strong></p>
<p>Un <em>trie</em> no és més que un arbre de prefixes. El node arrel representa el prefixe de la cadena buida (o <img src='http://s.wordpress.com/latex.php?latex=%5Cepsilon&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\epsilon' title='\epsilon' class='latex' />). Cada aresta de l&#8217;arbre s&#8217;etiqueta amb un símbol de l&#8217;alfabet <img src='http://s.wordpress.com/latex.php?latex=%5CSigma&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\Sigma' title='\Sigma' class='latex' />, de manera que el node representa el prefix format per la concatenació de tots els símbols en les arestes des de l&#8217;arrel fins a l&#8217;esmentat node.</p>
<p>Vegem-ho més clar en un exemple. Suposem que tenim els noms de <a href="http://en.wikipedia.org/wiki/Alan_Turing" target="_blank">Alan</a>, <a href="http://en.wikipedia.org/wiki/Andrew_S._Tanenbaum" target="_blank">Andrew</a>, <a href="http://en.wikipedia.org/wiki/Leslie_Lamport" target="_blank">Leslie</a>, <a href="http://en.wikipedia.org/wiki/Johan_H%C3%A5stad" target="_blank">Johan</a> i <a href="http://en.wikipedia.org/wiki/John_Hopcroft" target="_blank">John</a>. El trie que representaria tots aquests noms és el següent.<br />
<img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2011/11/trie1.png" alt="" title="trie1" width="350" height="633" class="aligncenter size-full wp-image-1564" /></p>
<p>Com vegeu, les fulles de l&#8217;arbre corresponen al nom complet d&#8217;alguna de les persones: <em>allan</em>, <em>john</em>, <em>johan</em>, <em>andrew</em> i <em>leslie</em> (recorreguent l&#8217;arbre en amplada).</p>
<p>Un dels avantatges d&#8217;utilitzar un arbre de prefixes és que el cost de buscar una persona no depèn del nombre de persones. Amb una cadena de longitud <em>l</em>, el cost de la cerca és <img src='http://s.wordpress.com/latex.php?latex=O%28l%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(l)' title='O(l)' class='latex' />. Simplement hem de descendir de nivell en nivell en l&#8217;arbre per a cada lletra del nom. </p>
<p><strong id="radixtree">Compressió de camins</strong></p>
<p>El problema dels tries, com ja podreu deduir de la imatge anterior és l&#8217;espai que ocupen en memòria. Suposant de nou que totes les cadenes tenen la mateixa longitud <em>l</em>, en el pitjor dels casos, cap de les <em>n</em> cadenes codificades en l&#8217;arbre tindrà un prefixe comú i en aquest cas el nombre de nodes és <img src='http://s.wordpress.com/latex.php?latex=O%28n%20%5Ccdot%20l%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(n \cdot l)' title='O(n \cdot l)' class='latex' /> (encara que això sols passar quan <img src='http://s.wordpress.com/latex.php?latex=n%20%5Cleq%20%5Cvert%20%5CSigma%20%5Cvert&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='n \leq \vert \Sigma \vert' title='n \leq \vert \Sigma \vert' class='latex' />). </p>
<p>A primera vista sembla que no és gran cosa, ja que té el mateix cost temporal que mantenir els noms en un vector. El problema és que necessitem emmagatzemar per a cada node quins són els seus descendents.</p>
<p>Si volem mantenir el cost de cerca <img src='http://s.wordpress.com/latex.php?latex=O%28l%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(l)' title='O(l)' class='latex' />, necessitem determinar en cost <img src='http://s.wordpress.com/latex.php?latex=O%281%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(1)' title='O(1)' class='latex' /> per quina branca em de descendir quan busquem una cadena. La resposta en aquest cas és evident: Mantenir un vector de punters amb tants elements com símbols té l&#8217;alfabet amb el que treballem. Si hi ha algun descendent en el node per al símbol <em>i</em>, el punter <img src='http://s.wordpress.com/latex.php?latex=p_i&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p_i' title='p_i' class='latex' /> apuntarà a aquest descendent. Mentre que si <img src='http://s.wordpress.com/latex.php?latex=p_i&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p_i' title='p_i' class='latex' /> és nul, sabem que no hi ha cap descendent del node actual per al símbol <em>i</em>. D&#8217;aquesta manera, el cost espacial de mantenir l&#8217;arbre de prefixos és <img src='http://s.wordpress.com/latex.php?latex=O%28%20l%20%5Ccdot%20n%20%5Ccdot%20%5Cvert%20%5CSigma%20%5Cvert%20%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O( l \cdot n \cdot \vert \Sigma \vert )' title='O( l \cdot n \cdot \vert \Sigma \vert )' class='latex' />.</p>
<p>El cost ja no és tan atractiu com semblava. Suposem que el nostre alfabet té 26 caràcters (de la <em>a</em> a la <em>z</em>), que tenim 3 milions de persones i la longitud mitjana dels noms és de 30 caràcters. Suposant que els punters són de 4 bytes, com serien en un processador de 32 bits, mantenir aquesta estructura podria necessitar al voltant de 9GB! </p>
<p>Evidentment, en la realitat el nombre de nodes és molt menor ja que els noms sí que tenen prefixos en comú així i tot en la realitat no només tenim 26 caràcters en l&#8217;alfabet: els noms de les persones de <a href="http://www.imdb.com" target="_blank">IMDB</a> inclouen també números, espais, símbols d&#8217;exclamació, caràcters accentuats i caràcters d&#8217;altres alfabets que no són el llatí (ciríl·lic o grec, per exemple).</p>
<p>Com solucionem aquest problema? En primer lloc, tractant de reduir el nombre de nodes i això pot fer-se fàcilment utilitzant compressió de camins en l&#8217;arbre. Què és la compressió de camins? Fixeu-se en el primer arbre que us he presentat. Veureu que molts dels nodes sols tenen un descendent. No seria possible unir en un únic node tots els nodes que tenen un únic descendent? Això és la compressió de camins i aquest <em>trie</em> s&#8217;anomena <em><a href="http://en.wikipedia.org/wiki/Radix_tree" target="_blank">Radix Tree</a></em>. Veieu com quedaria l&#8217;arbre anterior amb els camins comprimits.<br />
<img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2011/10/trie2.png" alt="" title="trie2" width="350" height="304" class="aligncenter size-full wp-image-1567" /></p>
<p><strong id="reduint-espai-nodes">Reduint l&#8217;espai dels nodes</strong></p>
<p>Una altra millora que pot fer-se per a reduir l&#8217;espai és intentar reduir el nombre de punters que s&#8217;emmagatzemen en cada node. Havíem dit que si volem mantenir el cost de cerca en <img src='http://s.wordpress.com/latex.php?latex=O%28l%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(l)' title='O(l)' class='latex' /> necessitem un vector de <img src='http://s.wordpress.com/latex.php?latex=%5Cvert%20%5CSigma%20%5Cvert&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\vert \Sigma \vert' title='\vert \Sigma \vert' class='latex' /> punters. Però no podem reduir aquest nombre? La resposta és sí, però a costa d&#8217;incrementar el cost de cerca.</p>
<p>Una possible millora és emmagatzemar els punters en un arbre de cerca (en el meu cas he utilitzat el map de la STL de C++). Així, en cada node sols s&#8217;emmagatzema un punter per a cada descendent i no per a cada símbol de l&#8217;alfabet (per tant, no tenim punters nuls que ocupen memòria). Si en un node no hi ha cap punter per al símbol que busquem, llavors no hi ha descendent per a aquest símbol. D&#8217;aquesta manera el nombre de punters en cada node es redueix considerablement, especialment a mesura que es descendeix en l&#8217;arbre, que és també quan més nodes hi ha. Penseu que és probable que tinguem noms començant en totes les lletres (el node arrel tindrà tants descendents com símbols té l&#8217;alfabet), en canvi és poc probable que tinguem molts noms amb el mateix prefix i amb l&#8217;última lletra diferent (els nodes de nivells inferiors tindran pocs descendents).</p>
<p>El problema és que ara el cost de cercar una cadena en el trie és <img src='http://s.wordpress.com/latex.php?latex=O%28l%20%5Ccdot%20%5Clog_2%20p%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(l \cdot \log_2 p)' title='O(l \cdot \log_2 p)' class='latex' />, on <em>p</em> és el nombre de punters en els nodes (<img src='http://s.wordpress.com/latex.php?latex=p%20%5Cleq%20%5Cvert%20%5CSigma%20%5Cvert&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p \leq \vert \Sigma \vert' title='p \leq \vert \Sigma \vert' class='latex' />, normalment prou menor). </p>
<p>Amb totes aquestes millores, el meu programa ocupa ara mateixa 3686MB en memòria, que és bastant menys dels 9GB que comentàvem al començament. Hi ha que tenir en compte a més, que aquests 3686MB no són només del <em>trie</em> sinó també de mantenir els títols de les pel·lícules, el graf que relaciona pel·lícules i actors i tota la informació corresponent a cada persona i pel·lícula. </p>
<p>Comentaré també que em vaig endur una desagradable sorpresa al passar el programa d&#8217;una màquina de 32 bits a una de 64 bits: els punters van passar d&#8217;ocupar 4 bytes a ocupar-ne 8 i clar, emmagatzemar el mateix arbre necessitava el doble de memòria!</p>
<p><strong id="approximate-matching">Cerca aproximada</strong></p>
<p>Hem parlat molt de com emmagatzemar eficientment el <em>trie</em>, però encara no hem solucionat el problema que havíem plantejat: fer una cerca aproximada donada una cadena <em>X</em>. Ací és on unim l&#8217;algorisme de Damerau-Levenshtein explicat <a href="http://www.elvoldelhomeocell.net/?p=1553#damerau-levenshtein-ukkonen">abans</a> i els <em><a href="http://www.elvoldelhomeocell.net/?p=1553#trie">tries</a></em>.</p>
<p>Hi ha dos coses importants a tenir en compte a l&#8217;hora de calcular la distància de Damerau-Levenshtein sobre distintes cadenes:</p>
<ol>
<li>Al calcular la distància entre la cadena <em>X</em> i la cadena <em>YZ</em>, les <em>|Y|+1</em> primeres files de la matriu de Damerau-Levenshtein seran iguals a les del càlcul de la distància entre la cadena <em>X</em> i la cadena <em>Y</em>.</li>
<li>Si per al càlcul de la distància entre una cadena <em>X</em> i una cadena <em>Y</em>, totes les columnes de la fila <em>|Y|</em> tenen un valor major que <em>k</em>, cap cadena amb el prefix <em>Y</em> estarà a una distància menor que <em>k</em> de <em>X</em>.</li>
</ol>
<p>El <em>trie</em> permet estalviar temps ja què la matriu de Damerau-Levenshtein va calculant-se iterativament quan descendim en l&#8217;arbre, pel que havíem comentat en la propietat (1). A més, tenint en compte la propietat (2), si per a un node la distància a la cadena buscada és major que un cert llindar <em>k</em> llavors sabem que cap dels descendents d&#8217;aquest node tindrà un llindar menor, de manera que no hem d&#8217;explorar els descendents. </p>
<p><img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2011/11/approximate_lookup_algorithm.png" alt="" title="approximate_lookup_algorithm" width="454" height="274" class="aligncenter size-full wp-image-1655" /></p>
<p>Algunes consideracions sobre les operacions que apareixen en el pseudocodi. L&#8217;operació <img src='http://s.wordpress.com/latex.php?latex=update%28D%2C%20C%2C%20x%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='update(D, C, x)' title='update(D, C, x)' class='latex' /> el que fa és actualitzar la matriu <em>D</em> afegint <em>|x|</em> files i computant el valor dels nous elements i el vector <em>C</em> com he explicat en la millora de Ukkonen.</p>
<p>L&#8217;operació <img src='http://s.wordpress.com/latex.php?latex=dist%28D%27%2C%20C%27%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='dist(D&#039;, C&#039;)' title='dist(D&#039;, C&#039;)' class='latex' /> el que fa es tornar el valor de l&#8217;element <img src='http://s.wordpress.com/latex.php?latex=D%27_%7B%7Cv%7C%20%2C%20%7Cw%7C%20%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='D&#039;_{|v| , |w| }' title='D&#039;_{|v| , |w| }' class='latex' /> tenint en compte que potser aquest element no ha arribat a calcular-se en l&#8217;operació <em>update</em>. Aquest valor és la distància que hi ha entre les cadenes <em>v</em> i <em>w</em> si aquesta distància és menor o igual que <em>k</em>, o <em>k+1</em> en cas contrari.</p>
<p>La gràcia d&#8217;aquest algorisme és que té una complexitat temporal de <img src='http://s.wordpress.com/latex.php?latex=O%28k%20%5Ctimes%20%7B%5Cvert%20%5CSigma%20%5Cvert%7D%5Ek%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(k \times {\vert \Sigma \vert}^k)' title='O(k \times {\vert \Sigma \vert}^k)' class='latex' />, segons l&#8217;article que us citava <a href="http://www.elvoldelhomeocell.net/?p=1553#damerau-levenshtein-ukkonen">abans</a>. Això suposant que l&#8217;arbre de prefixos és complet i que cada node emmagatzema un vector de punters als possibles descendents (és a dir, sense tenir en compte les millores per a <a href="http://www.elvoldelhomeocell.net/?p=1553#radixtree">reduir</a> <a href="http://www.elvoldelhomeocell.net/?p=1553#reduint-espai-nodes">espai</a>). </p>
<p>Fixeu-vos que l&#8217;algorisme no depèn del nombre de cadenes en el <em>trie</em>! Això significa que podem trobar els noms que més s&#8217;aproximen a una cerca feta per l&#8217;usuari sense importar quants noms tenim emmagatzemats. Una considerable millora front al cost <img src='http://s.wordpress.com/latex.php?latex=O%28n%20%5Ctimes%20k%5E2%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(n \times k^2)' title='O(n \times k^2)' class='latex' />, això sí, sempre que <em>k</em> siga menuda, perquè el cost creix de manera exponencial amb <em>k</em>!</p>
<p>El gràfic que es mostra ací baix és el temps mitjà de resposta per part de l&#8217;oracle quan es busca el nom d&#8217;un actor que no existeix en la base de dades. El valor de <em>k</em> que utilitze és <img src='http://s.wordpress.com/latex.php?latex=%5Cmin%283%2C%20%5Cleft%5Clfloor%20%5Cfrac%7B%7Cw%7C%7D%7B4%7D%20%5Cright%5Crfloor%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\min(3, \left\lfloor \frac{|w|}{4} \right\rfloor)' title='\min(3, \left\lfloor \frac{|w|}{4} \right\rfloor)' class='latex' />. Si usés un valor fixe per a <em>k</em> hi hauria molts suggeriments per a noms curts que realment no tenen massa sentit. Anem al cas extrem: imaginem que un usuari busca el nom <em>a</em>, té sentit suggerir-li els noms <em>b</em>, <em>c</em>, <em>d</em>, etc? La distància a tots ells és 1, però és que la longitud de la cadena era 1! Això significaria que l&#8217;usuari ha errat en el 100% de la cadena! Jo permet a l&#8217;usuari que s&#8217;equivoqui fins a un 25% de la longitud de la cadena. Però si la cadena cercada fos molt llarga el valor <em>k</em> seria molt gran, per això pose un límit al número d&#8217;errors a 3.</p>
<p><a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2011/11/lookup_times.png" rel="lightbox[1553]"><img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2011/11/lookup_times.png" alt="" title="lookup_times" width="400" height="250" class="aligncenter size-full wp-image-1660" /></a></p>
<p>Dir que l&#8217;<a href="http://en.wikipedia.org/wiki/Confidence_interval" target="_blank">interval de confiança</a> que es mostra és per a un valor crític del 95%. Crec que el gràfic no mereix més explicacions. El temps de resposta mitjà és de 0.208 segons amb totes les millores comentades. També apareix el temps de resposta utilitzant el càlcul de la distància de Damerau-Levenshtein sense la millora de Ukkonen (0.301 segons).</p>
<p><strong>Encara millor?</strong></p>
<p>Des del primer moment vaig tenir com a referència a Google i el seu &#8220;<em><a href="http://www.google.com/support/websearch/bin/answer.py?answer=1723" target="_blank">Did you mean&#8230;?</a></em>&#8220;. I tenia ben clar que els de Google no podien utilitzar un <em>trie</em> gegantí perquè el vocabulari amb el que treballen és enorme: imagineu totes les paraules diferents que poden haver en la WWW i el que suposaria construir un <em>trie</em> com el descrit! </p>
<p>Google utilitza un <a href="http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en/us/pubs/archive/36180.pdf" target="_blank">enfocament</a> basat en <a href="http://en.wikipedia.org/wiki/Machine_learning" target="_blank">aprenentatge automàtic</a> i <a href="http://en.wikipedia.org/wiki/Natural_language_processing" target="_blank">processament del llenguatge natural</a>. I aquesta va ser la ruta que em vaig proposar seguir i que us explicaré en el pròxim post.</p>
<p>Mentrestant els <em>tries</em> han funcionat prou bé: són ràpids i sobretot obtenen els resultats que l&#8217;usuari espera. I poden ser una alternativa senzilla en situacions amb un vocabulari i un alfabet més reduït. Per exemple, per a construir un corrector automàtic en un editor de textos.</p>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/1553" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/1553/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Correcció automàtica en l&#8217;Oracle: cerca dicotòmica</title>
		<link>http://www.elvoldelhomeocell.net/archives/1515</link>
		<comments>http://www.elvoldelhomeocell.net/archives/1515#comments</comments>
		<pubDate>Mon, 31 Oct 2011 00:59:53 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Jo]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[Projectes]]></category>
		<category><![CDATA[algorismes]]></category>
		<category><![CDATA[cerca aproximada]]></category>
		<category><![CDATA[cerca binària]]></category>
		<category><![CDATA[cerca dicotòmica]]></category>
		<category><![CDATA[complexitat computacional]]></category>
		<category><![CDATA[correcció automàtica]]></category>
		<category><![CDATA[friki]]></category>
		<category><![CDATA[oracle de woody allen]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/?p=1515</guid>
		<description><![CDATA[La màxima &#8220;qui no te feina, Déu li&#8217;n busca&#8221; és ben certa, però a sovint alguns anem més enllà i ens en busquem de nova quan encara no hem acabat la que tenim entre mans. I si no tenia prou &#8230; <a href="http://www.elvoldelhomeocell.net/archives/1515">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>La màxima &#8220;qui no te feina, Déu li&#8217;n busca&#8221; és ben certa, però a sovint alguns anem més enllà i ens en busquem de nova quan encara no hem acabat la que tenim entre mans. I si no tenia prou amb estar d&#8217;Erasmus, els <a href="http://ai-class.com" target="_blank">cursets</a> a <a href="http://ml-class.org" target="_blank">distància</a> de Stanford i la competició de <a href="http://aichallenge.org/" target="_blank">ai-challange.com</a>, farà un parell de setmanes que em ronda pel cap una nova millora per al meu Oracle de Woody Allen. Però bo, no vaig a queixar-me perquè no es pot dir que la feina vinga forçada.</p>
<p>Recordeu l&#8217;<a href="http://joapuipe.dyndns.org/allen/" target="_blank">Oracle de Woody Allen</a>? Ja us he parlat d&#8217;aquest xicotet projecte en <a href="http://www.elvoldelhomeocell.net/archives/990" target="_blank">altres</a> <a href="http://www.elvoldelhomeocell.net/archives/997" target="_blank">posts</a>, però us refrescaré la memòria. Es tracta d&#8217;una senzilla pàgina web que et permet trobar quina connexió uneix a dos persones del món del cinema (actors, directors, guionistes i productors). La idea és que si dos persones han treballat juntes en una pel·lícula, hi ha una distància de separació de 1. De la mateixa manera, Si la persona <em>A</em> ha treballat amb la persona <em>B</em>, i aquesta amb la pesona <em>C</em>, les persones <em>A</em> i <em>C</em> estan a una distància de 2. I així successivament.</p>
<p>No em centraré amb els detalls de com es calcula aquesta distància i la connexió (camí, en terminologia de grafs) perquè no és del que va aquest article, simplement dir que s&#8217;utilitza l&#8217;algorisme de <a href="http://en.wikipedia.org/wiki/Breadth-first_search" target="_blank">cerca per amplada</a>.</p>
<p>Des de les primeres versions, volia que el meu programa fora capaç de &#8220;tolerar&#8221; errades humanes. Per exemple, si un usuari escriu &#8220;Wody Allen&#8221; en lloc de &#8220;Woody Allen&#8221;, el meu programa fora capaç de suggerir-li una <a href="http://en.wikipedia.org/wiki/Spell_checker" target="_blank">correcció automàtica</a>. En els següents tres articles comentaré dues alternatives que ha utilitzat el programa per a solucionar el problema i finalment una tercera que encara no he implementat, però que us plantejaré ja que encara queden alguns detalls per polir i amb un poc de sort algú es decideix a aportar alguna idea.</p>
<p>Avise que el contingut de les pròximes entrades és molt tècnic. Per als dos primers articles necessitareu coneixements bàsics d&#8217;algorísmica i complexitat computacional, res que un alumne de primer o segon d&#8217;Enginyeria Informàtica no puga entendre. Per al tercer, a més, necessitareu coneixements bàsics d&#8217;aprenentatge automàtic, que inclou estadística bàsica (bàsicament, teorema de Bayes). </p>
<p><strong>Cerca dicotòmica</strong></p>
<p>La primera tècnica que vaig utilitzar per a proveir de correccions a l&#8217;usuari era l&#8217;algorisme de <a href="http://en.wikipedia.org/wiki/Binary_search" target="_blank">cerca dicotòmica</a> o binària.</p>
<p>La idea és mantenir els noms de les persones en <a href="http://en.wikipedia.org/wiki/Lexicographical_order" target="_blank">ordre lexicogràfic</a>. No vaig a explicar l&#8217;algorisme de la cerca dicotòmica, perquè entenc que si heu arribat fins ací el coneixeu.</p>
<p>El que fa l&#8217;algorisme és suggerir com a correccions els noms més pròxims (en ordre lexicogràfic) al nom introduït per l&#8217;usuari. Per a veure com funciona l&#8217;algorisme, suposarem que els noms de les persones són nombres enters. Imaginem que tenim el següent conjunt de nombres en un vector ordenat (<img src='http://s.wordpress.com/latex.php?latex=i&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='i' title='i' class='latex' /> indica l&#8217;índex de l&#8217;element i <img src='http://s.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' /> el <em>nom</em> de la persona):</p>
<p style="text-align: center;"><img src='http://s.wordpress.com/latex.php?latex=%20%20%5Cbegin%7Barray%7D%7B%7Cc%7Cc%7Cc%7Cc%7Cc%7Cc%7Cc%7C%7D%20%20%5Chline%20%20i%20%26%200%20%26%201%20%26%202%20%26%203%20%26%204%20%26%205%20%5C%5C%20%20%5Chline%20%20p%20%26%201%20%26%202%20%26%203%20%26%205%20%26%207%20%26%209%20%5C%5C%20%20%5Chline%20%20%5Cend%7Barray%7D%20%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='  \begin{array}{|c|c|c|c|c|c|c|}  \hline  i &amp; 0 &amp; 1 &amp; 2 &amp; 3 &amp; 4 &amp; 5 \\  \hline  p &amp; 1 &amp; 2 &amp; 3 &amp; 5 &amp; 7 &amp; 9 \\  \hline  \end{array}  ' title='  \begin{array}{|c|c|c|c|c|c|c|}  \hline  i &amp; 0 &amp; 1 &amp; 2 &amp; 3 &amp; 4 &amp; 5 \\  \hline  p &amp; 1 &amp; 2 &amp; 3 &amp; 5 &amp; 7 &amp; 9 \\  \hline  \end{array}  ' class='latex' /></p>
<p>Suposem que busquem la persona amb <em>nom</em> 6, llavors l&#8217;algorisme s&#8217;executaria de la següent forma:</p>
<p style="text-align: center;"><img src='http://s.wordpress.com/latex.php?latex=%20%20%5Cbegin%7Barray%7D%7B%7Cc%7Cc%7Cc%7Cc%7Cc%7C%7D%20%20%5Chline%20%5Ctext%7BIter.%7D%20%26%20l%20%26%20r%20%26%20c%20%26%20p_c%20%5C%5C%20%20%5Chline%201%20%26%200%20%26%205%20%26%202%20%26%203%20%5C%5C%20%20%5Chline%202%20%26%203%20%26%205%20%26%204%20%26%207%20%5C%5C%20%20%5Chline%203%20%26%203%20%26%203%20%26%203%20%26%205%20%5C%5C%20%20%5Chline%20%20%5Cend%7Barray%7D%20%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='  \begin{array}{|c|c|c|c|c|}  \hline \text{Iter.} &amp; l &amp; r &amp; c &amp; p_c \\  \hline 1 &amp; 0 &amp; 5 &amp; 2 &amp; 3 \\  \hline 2 &amp; 3 &amp; 5 &amp; 4 &amp; 7 \\  \hline 3 &amp; 3 &amp; 3 &amp; 3 &amp; 5 \\  \hline  \end{array}  ' title='  \begin{array}{|c|c|c|c|c|}  \hline \text{Iter.} &amp; l &amp; r &amp; c &amp; p_c \\  \hline 1 &amp; 0 &amp; 5 &amp; 2 &amp; 3 \\  \hline 2 &amp; 3 &amp; 5 &amp; 4 &amp; 7 \\  \hline 3 &amp; 3 &amp; 3 &amp; 3 &amp; 5 \\  \hline  \end{array}  ' class='latex' /></p>
<p>Com que l&#8217;últim element considerat (<img src='http://s.wordpress.com/latex.php?latex=p_c%5E%7B%283%29%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p_c^{(3)}' title='p_c^{(3)}' class='latex' />) és menor que el cercat, es proposarien com a correccions els elements 5 (posició <img src='http://s.wordpress.com/latex.php?latex=c%5E%7B%283%29%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c^{(3)}' title='c^{(3)}' class='latex' />) i 7 (posició <img src='http://s.wordpress.com/latex.php?latex=c%5E%7B%283%29%7D%20%2B%201&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c^{(3)} + 1' title='c^{(3)} + 1' class='latex' />). En el cas de que l&#8217;últim element considerat fora major que el cercat, es proposarien com a correccions els elements en les posicions <img src='http://s.wordpress.com/latex.php?latex=c%5E%7B%283%29%7D%20-%201&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c^{(3)} - 1' title='c^{(3)} - 1' class='latex' /> i <img src='http://s.wordpress.com/latex.php?latex=c%5E%7B%283%29%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c^{(3)}' title='c^{(3)}' class='latex' />.</p>
<p>Fixeu-se que en cas de no trobar un element, sempre proposarem un element menor i un major. I a més, sempre seran els dos que més s&#8217;aproximen a l&#8217;element cercat.</p>
<p>El problema és que els noms no són enters i l&#8217;ordre lexicogràfic té un xicotet problema: Dos noms als que sols els hem canviat una lletra poden estar molt separats en ordre lexicogràfic. Ací un exemple que il·lustra el problema:</p>
<p style="text-align: center;"><img src='http://s.wordpress.com/latex.php?latex=%20%20%5Cbegin%7Barray%7D%7B%7Cc%7Cc%7Cc%7Cc%7Cc%7C%7D%20%20%5Chline%20i%20%26%200%20%26%201%20%26%202%20%26%203%20%5C%5C%20%20%5Chline%20p%20%26%20%5Ctext%7Bblai%7D%20%26%20%5Ctext%7Bjaume%7D%20%26%20%5Ctext%7Bjavi%7D%20%26%20%5Ctext%7Btoni%7D%20%5C%5C%20%20%5Chline%20%20%5Cend%7Barray%7D%20%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='  \begin{array}{|c|c|c|c|c|}  \hline i &amp; 0 &amp; 1 &amp; 2 &amp; 3 \\  \hline p &amp; \text{blai} &amp; \text{jaume} &amp; \text{javi} &amp; \text{toni} \\  \hline  \end{array}  ' title='  \begin{array}{|c|c|c|c|c|}  \hline i &amp; 0 &amp; 1 &amp; 2 &amp; 3 \\  \hline p &amp; \text{blai} &amp; \text{jaume} &amp; \text{javi} &amp; \text{toni} \\  \hline  \end{array}  ' class='latex' /></p>
<p>Suposem que en l&#8217;anterior situació, un usuari s&#8217;equivoca escrivint el nom de <em>J<strong>a</strong>ume</em> i escriu <em>J<strong>e</strong>ume</em>:</p>
<p style="text-align: center;"><img src='http://s.wordpress.com/latex.php?latex=%20%20%5Cbegin%7Barray%7D%7B%7Cc%7Cc%7Cc%7Cc%7Cc%7C%7D%20%20%5Chline%20%5Ctext%7BIter.%7D%20%26%20l%20%26%20r%20%26%20c%20%26%20p_c%20%5C%5C%20%20%5Chline%201%20%26%200%20%26%203%20%26%201%20%26%20%5Ctext%7Bjaume%7D%20%5C%5C%20%20%5Chline%202%20%26%202%20%26%203%20%26%202%20%26%20%5Ctext%7Bjavi%7D%20%5C%5C%20%20%5Chline%203%20%26%203%20%26%203%20%26%203%20%26%20%5Ctext%7Btoni%7D%20%5C%5C%20%20%5Chline%20%20%5Cend%7Barray%7D%20%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='  \begin{array}{|c|c|c|c|c|}  \hline \text{Iter.} &amp; l &amp; r &amp; c &amp; p_c \\  \hline 1 &amp; 0 &amp; 3 &amp; 1 &amp; \text{jaume} \\  \hline 2 &amp; 2 &amp; 3 &amp; 2 &amp; \text{javi} \\  \hline 3 &amp; 3 &amp; 3 &amp; 3 &amp; \text{toni} \\  \hline  \end{array}  ' title='  \begin{array}{|c|c|c|c|c|}  \hline \text{Iter.} &amp; l &amp; r &amp; c &amp; p_c \\  \hline 1 &amp; 0 &amp; 3 &amp; 1 &amp; \text{jaume} \\  \hline 2 &amp; 2 &amp; 3 &amp; 2 &amp; \text{javi} \\  \hline 3 &amp; 3 &amp; 3 &amp; 3 &amp; \text{toni} \\  \hline  \end{array}  ' class='latex' /></p>
<p>Llavors, les correccions proposades serien <em>Javi</em> i <em>Toni</em> i cap dels dos és el que l&#8217;usuari buscava.</p>
<p>Una possible millora és no sols considerar els dos noms al voltant del cercat, sinó considerar <em>k</em> noms més pròxims en ordre lexicogràfic (per exemple, amb <em>k</em> igual a 3, l&#8217;algorisme consideraria <em>Jaume</em>, <em>Javi</em> i <em>Toni</em>). Però aquesta solució no funciona massa bé quan el nombre d&#8217;elements en el vector és de més de dos milions i l&#8217;usuari s&#8217;equivoca en una de les primeres lletres del nom.</p>
<p>No obstant això, l&#8217;algorisme és molt eficient en quant a temps i memòria i sobre tot, és molt senzill. Suposant que tots els noms tenen aproximadament la mateixa longitud <em>l</em>, podem expressar la complexitat espacial i temporal (de cerca) en funció del nombre de persones <em>n</em> i aquesta longitud <em>l</em> (la suposició de la longitud <em>l</em> és sols per a simplificar les expressions de la complexitat).</p>
<p style="text-align: center;"><img src='http://s.wordpress.com/latex.php?latex=%20%20S%28n%2C%20l%29%20%5Cin%20O%20%5Cleft%28%20l%20%5Ccdot%20n%20%5Cright%29%20%5C%5C%20%20T%28n%2C%20l%29%20%5Cin%20O%20%5Cleft%28%20l%20%5Ccdot%20%5Clog_2%20n%20%5Cright%29%20%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='  S(n, l) \in O \left( l \cdot n \right) \\  T(n, l) \in O \left( l \cdot \log_2 n \right)  ' title='  S(n, l) \in O \left( l \cdot n \right) \\  T(n, l) \in O \left( l \cdot \log_2 n \right)  ' class='latex' /></p>
<p>La primera expressió es deriva del fet que tenim <em>n</em> noms i cada nom té una longitud de <em>l</em> caràcters. La segona expressió es deriva del fet que la cerca dicotòmica fa <img src='http://s.wordpress.com/latex.php?latex=O%28%5Clog_2%20n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\log_2 n)' title='O(\log_2 n)' class='latex' /> comparacions de cadenes, i per comparar dues cadenes de longitud <em>l</em> necessitem fins a <em>l</em> comparacions de caràcters.</p>
<p>Aquesta senzilla idea fou reemplaçada per una que donava millors resultats cara a l&#8217;usuari, però que té un fort inconvenient: l&#8217;ús de memòria. L&#8217;alternativa que presentaré en la pròxima entrada, és la que està implementada ara mateixa en l&#8217;Oracle.</p>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/1515" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/1515/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>L&#8217;Oracle de Woody Allen: últims canvis</title>
		<link>http://www.elvoldelhomeocell.net/archives/997</link>
		<comments>http://www.elvoldelhomeocell.net/archives/997#comments</comments>
		<pubDate>Sat, 18 Sep 2010 18:58:53 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[Estudis]]></category>
		<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Jo]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[Projectes]]></category>
		<category><![CDATA[bacon]]></category>
		<category><![CDATA[bacon number]]></category>
		<category><![CDATA[enginyeria informàtica]]></category>
		<category><![CDATA[estiu]]></category>
		<category><![CDATA[fiv]]></category>
		<category><![CDATA[friki]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[google code]]></category>
		<category><![CDATA[llen number]]></category>
		<category><![CDATA[número de bacon]]></category>
		<category><![CDATA[oracle de bacon]]></category>
		<category><![CDATA[oracle de woody allen]]></category>
		<category><![CDATA[oracle of woody allen]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[upv]]></category>
		<category><![CDATA[woody allen]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/?p=997</guid>
		<description><![CDATA[Imagine que tots els que visiteu aquest blog us haureu passat per la web de l&#8217;Oracle de Woody Allen i espere que quan entràreu estiguera funcionant. Després explicaré perquè no està en funcionament el 100% del temps. Aquests darrers dies &#8230; <a href="http://www.elvoldelhomeocell.net/archives/997">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Imagine que tots els que visiteu aquest blog us haureu passat per la web de l&#8217;<a href="http://www.jpuigcerver.net/allen" target="_blank">Oracle de Woody Allen</a> i espere que quan entràreu estiguera funcionant. Després explicaré perquè no està en funcionament el 100% del temps.</p>
<p>Aquests darrers dies he estat documentant el codi font, corregint algunes coses, preparant els fitxers de l&#8217;<a href="http://en.wikipedia.org/wiki/Automake" target="_blank">Automake</a>, etc. És a dir, feina que no mola però que s&#8217;ha de fer si vols que algú més a part de tu siga capaç de llegir i entendre el que fas.</p>
<p>Doncs bé, fruit d&#8217;aquest treball he obert un <a href="http://code.google.com/p/oracleofwoodyallen/" target="_blank">projecte al Google Code</a> que a partir d&#8217;ara serà la pàgina oficial del projecte, d&#8217;aquesta manera acabe de trencar completament amb l&#8217;antic &#8220;<a href="http://svn.assembla.com/svn/oraclebacon" target="_blank">Número de Bacon</a>&#8220;. En aquesta pàgina web podreu trobar les últimes novetats pel que fa al desenvolupament del projecte.</p>
<p>També he penjat a Internet la <a href="http://joapuipe.dyndns.org/allen/doc/html" target="_blank">documentació HTML</a> de l&#8217;Oracle i també <a href="http://joapuipe.dyndns.org/allen/doc/latex/refman.pdf">una versió en PDF</a>.</p>
<p>He intentat escriure-ho tot en anglès el menys <em>macarroni</em> possible, però si en valencià ja se me&#8217;n passen de burrades, en anglès de segur que també. Els suggeriments i correccions són benvinguts/des.</p>
<p>I ara el que us havia d&#8217;explicar al principi. Per què no està en funcionament l&#8217;Oracle tot el dia? Resposta ràpida: No tinc un ordinador amb prou memòria RAM disponible per a tenir-lo connectat 24h.</p>
<p>En casa tinc un ordinador (<em>clarke</em>) que està connectat les 24h realitzant càlcul científic en la xarxa <a href="http://boinc.berkeley.edu/" target="_blank">BOINC</a>, l&#8217;utilitze de servidor web i servidor ftp, etc. Però aquest ordinador té 2GB de memòria RAM i el client BOINC i els càlculs científics ocupen entre 500 i 600MB.</p>
<p>Com que la base de dades de l&#8217;Oracle es carrega en memòria i es prou gran (el programa ocupa 1,4GB) no en cap tot en la memòria de <em>clarke</em> (peu de nota, els meus ordinadors tenen noms de científics i escriptors de ciència ficció). Quan us connectàreu a l&#8217;Oracle, aquest s&#8217;estava executant en un altre ordinador que tinc amb 4GB de RAM.</p>
<p>Què pense fer? En primer lloc, he començat a mirar-me la documentació d&#8217;un gestor de bases de dades anomenat <a href="http://www.eyedb.org/" target="_blank">EyeDB</a>. Aquest gestor no utilitza el típic <a href="http://en.wikipedia.org/wiki/Relational_model" target="_blank">paradigma relacional</a>, sinó que utilitza el paradigma <a href="http://en.wikipedia.org/wiki/Object_database" target="_blank">Orientat a Objectes</a>. En poques paraules i per al cas, això significa que és molt més ràpid que <a href="http://www.mysql.com/" target="_blank">MySQL</a>, per exemple. Possiblement adapte l&#8217;Oracle per a treballar amb aquesta base de dades. El funcionament serà un poc més lent, però consumirà menys memòria RAM.</p>
<p>En segon lloc, si algú té una placa base amb <a href="http://en.wikipedia.org/wiki/LGA_775" target="_blank">Socket 775</a> per a un Pentium 4 de 64 bits i que suporte almenys 4GB de memòria RAM, estic interessat en adquirir-la. Si no, una placa base nova d&#8217;aquestes característiques costa uns 50 euros. S&#8217;accepten donacions.</p>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/997" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/997/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>L&#8217;Oracle de Woody Allen</title>
		<link>http://www.elvoldelhomeocell.net/archives/990</link>
		<comments>http://www.elvoldelhomeocell.net/archives/990#comments</comments>
		<pubDate>Fri, 27 Aug 2010 23:24:14 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[Cinema i televisió]]></category>
		<category><![CDATA[Estudis]]></category>
		<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Jo]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[Projectes]]></category>
		<category><![CDATA[allen number]]></category>
		<category><![CDATA[bacon]]></category>
		<category><![CDATA[bacon number]]></category>
		<category><![CDATA[enginyeria informàtica]]></category>
		<category><![CDATA[estiu]]></category>
		<category><![CDATA[fiv]]></category>
		<category><![CDATA[friki]]></category>
		<category><![CDATA[número de bacon]]></category>
		<category><![CDATA[oracle de bacon]]></category>
		<category><![CDATA[oracle de woody allen]]></category>
		<category><![CDATA[oracle of woody allen]]></category>
		<category><![CDATA[upv]]></category>
		<category><![CDATA[woody allen]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/?p=990</guid>
		<description><![CDATA[Normalment els estius aprofite per començar tots els projectes que em passen pel cap durant el curs, però malauradament, no acostume a acabar-ne mai cap i l&#8217;any següent tornem a ser igual. Aquest any ha estat un poc diferent: He &#8230; <a href="http://www.elvoldelhomeocell.net/archives/990">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Normalment els estius aprofite per començar tots els projectes que em passen pel cap durant el curs, però malauradament, no acostume a acabar-ne mai cap i l&#8217;any següent tornem a ser igual. Aquest any ha estat un poc diferent: He començat alguna coseta, sí, però sobretot m&#8217;he centrat en <em>finiquitar </em>projectes que tenia començats.</p>
<p>I així ha passat amb l&#8217;<em>Oracle</em>. Ja us vaig parlar sobre el <a href="http://www.elvoldelhomeocell.net/archives/310" target="_blank">Número de Bacon i l&#8217;Oracle</a> que havia fet quan feia Programació en primer. Us vaig comentar que havia reescrit el codi que havia fet en Programació per fer-lo més ràpid, que consumís menys memòria i amb més funcionalitats. Volia construir un servidor que rebés peticions i les atenguera, a l&#8217;estil de la web <a href="http://www.oracleofbacon.org" target="_blank">The Oracle of Bacon</a>.</p>
<p>Doncs bé, aquest estiu (les dues últimes setmanes) m&#8217;he posat de nou a la feina i li he afegit algunes millores i he rematat la part del servidor, que no estava acabada. Ahir, aprofitant l&#8217;estrena a Espanya de l&#8217;última pel·lícula de <a href="http://ca.wikipedia.org/wiki/Woody_Allen" target="_blank">Woody Allen</a> (<em><a href="http://www.imdb.com/title/tt1182350/" target="_blank">Coneixeràs a l&#8217;home dels teus somnis</a></em>) vaig llançar la pàgina web titulada, en un moment de màxima inspiració, <a href="http://www.elvoldelhomeocell.net/works/allen" target="_blank">The Oracle of Woody Allen</a>.</p>
<p>El llançament ha estat un poc precipitat per fer-lo coincidir amb l&#8217;estrena de la pel·lícula (que encara no he vist), però ha estat una estratègia de &#8220;màrqueting&#8221;. Durant els propers dies estaré fent proves al servidor i a la pàgina web, així que és molt probable que quan la proveu el servidor no estiga funcionant (jo diria que es troba en fase pre-pre-Alpha).</p>
<p>Haig de solucionar encara un parell de <em>Segmentation Fault</em>s que apareixen en certes peticions i dels quals no he pogut descobrir el perquè i implementar en la web dues funcionalitats més a banda de la que apareix ara mateixa. Una vegada acabada la web, les funcionalitats seran:</p>
<ul>
<li>Calcular la distància entre dues persones en la base de dades.</li>
<li>Obtenir totes les persones a una distància <em>N</em> d&#8217;una determinada persona.</li>
<li>Calcular la distància mitjana d&#8217;una persona</li>
</ul>
<p>Les dues primeres funcionalitats també es troben disponibles en <a href="http://www.oracleofbacon.org" target="_blank">www.oracleofbacon.org</a> però no la tercera (degut al seu cost computacional, imagine) i en aquesta web tampoc hi ha la possibilitat d&#8217;explorar directors, productors i guionistes, sols actors. Jo, per diferenciar-me un poc de la pàgina web original, he decidit que les cerques es facen entre directors, productors i guionistes per defecte (ja que a Woody Allen se&#8217;l coneix principalment com a director i guionista).</p>
<p>En una altra ocasió (quan estiga 100% funcional) ja us contaré més detalls sobre el funcionament. Els més <em>geeks </em>podeu trobar el codi font en <a href="http://svn.assembla.com/svn/oraclebacon/trunk/" target="_blank">el servidor Subversion</a> (llicència GPL v3).</p>
<p>En fi, <em>stay tunned</em> i com diu en la pàgina web: <em>molt prompte estarà completament funcional (o no tan prompte)</em>.</p>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/990" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/990/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sudoku</title>
		<link>http://www.elvoldelhomeocell.net/archives/666</link>
		<comments>http://www.elvoldelhomeocell.net/archives/666#comments</comments>
		<pubDate>Sat, 02 May 2009 19:33:15 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[Curiositats]]></category>
		<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Matemàtiques]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[algorismes]]></category>
		<category><![CDATA[backtraking]]></category>
		<category><![CDATA[combinatoria]]></category>
		<category><![CDATA[complexitat computacional]]></category>
		<category><![CDATA[eda]]></category>
		<category><![CDATA[fiv]]></category>
		<category><![CDATA[friki]]></category>
		<category><![CDATA[japó]]></category>
		<category><![CDATA[miyagi]]></category>
		<category><![CDATA[np-complet]]></category>
		<category><![CDATA[sudoku]]></category>
		<category><![CDATA[upv]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/?p=666</guid>
		<description><![CDATA[Jo pensava que el sudoku era un d&#8217;aquests jocs mil·lenaris japonesos que havia exercitat la ment de monjos i Shoguns per a poder arribar a tota classe de revelacions pròpies del senyor Miyagi i que el deixen a un bocabadat &#8230; <a href="http://www.elvoldelhomeocell.net/archives/666">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Jo pensava que el <em><a href="http://en.wikipedia.org/wiki/Sudoku" target="_blank">sudoku</a></em> era un d&#8217;aquests jocs mil·lenaris japonesos que havia exercitat la ment de monjos i <a href="http://es.wikipedia.org/wiki/Sh%C5%8Dgun" target="_blank">Shoguns</a> per a poder arribar a tota classe de revelacions pròpies del <a href="http://en.wikipedia.org/wiki/Mr._Miyagi" target="_blank">senyor Miyagi</a> i que el deixen a un bocabadat durant una bona estona.</p>
<p>Però resulta que de joc mil·lenari i japonès en té ben poc, ja que va ser l&#8217;arquitecte nord-americà <a href="http://en.wikipedia.org/wiki/Howard_Garns" target="_blank">Howard Garns</a>, qui l&#8217;inventà&#8230; en 1979! Quina decepció.</p>
<p>Els <em>sudokus</em> es feren populars a Japó en la dècada dels vuitanta quan una companyia de <em>puzzles</em> comença a comercialitzar-los en el país de l&#8217;orient, però s&#8217;estengueren mundialment l&#8217;any 2004 quan el periòdic britànic <a href="http://www.timesonline.co.uk/tol/news/" target="_blank"><em>The Times</em></a> començà a incloure&#8217;ls entre les seves pàgines junt a sopes de lletres, encreuats i demés passatemps.</p>
<p><em><strong>El joc</strong></em></p>
<p>El joc consisteix <em>senzillament</em> en omplir un tauler de costats 9&#215;9 amb nombres de l&#8217;1 al 9 de manera que no hi haja dos nombre iguals en cap fila, ni cap columna, ni cap <em>bloc</em> de 3&#215;3. Els taulers de <em>sudoku</em> tenen la següent forma.</p>
<div id="attachment_681" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2009/05/sudoku_sol.png" rel="lightbox[666]"><img class="size-medium wp-image-681" title="Sudoku" src="http://www.elvoldelhomeocell.net/wp-content/uploads/2009/05/sudoku-300x300.png" alt="Sudoku" width="300" height="300" /></a><p class="wp-caption-text">Un exemple de Sudoku (punxa per veure la solució)</p></div>
<p>Depenent del nombre de quadres plens que ens donen i la posició dels nombres amb els que comencem el joc resulta més difícil o menys.</p>
<p><em><strong>El principi</strong></em></p>
<p>Jo fins fa dos anys no havia jugat en ma vida al joc aquest. N&#8217;havia vist, sí, però no havia jugat mai. Fou a juny de 2007, de camí a València per comprar els bitllets del (fallit) <a href="http://www.interrailnet.com/" target="_blank">Interrail</a> quan vaig jugar per primera vegada amb <a href="http://llumdelluerna.blogspot.com/" target="_blank">Marina</a> i <a href="http://www.blaiserver.net/" target="_blank">Blai</a>. Marina i jo ens vàrem <em>picar</em> a veure qui podia completar-ne més ràpidament així que em vaig comprar un llibre d&#8217;aquests que estan tot plens de <em>sudokus</em> per anar fent-lo durant el viatge, però circumstàncies de la vida que ja coneixeu feren que el llibre l&#8217;emplenés en l&#8217;hospital.</p>
<p>I a què ve tot açò? Doncs l&#8217;altre dia estàvem en classe d&#8217;<a href="http://users.dsic.upv.es/asignaturas/facultad/eda/" target="_blank">Estructures de Dades i Algorismes</a> (<em>a.k.a</em> EDA) aprenent sobre <a href="http://en.wikipedia.org/wiki/Backtracking" target="_blank"><em>Backtracking</em></a> i sorgí l&#8217;exemple del <em>sudoku</em>, així que el professor va fer un programa que resolia <em>sudokus</em> fent servir aquest esquema algorísmic. Quan va acabar el programa va dir: &#8220;Podríem fer que ens imprimira tots els <em>sudokus</em> possibles&#8230;&#8221; i va llançar el programa per a que fera això, però com que ja era hora d&#8217;acabar la classe ací va quedar la cosa.</p>
<p>Jo, ahir que no sabia que fer (ara que ja s&#8217;ha acabat el concurs de l&#8217;assignatura) i com que no havia practicat encara res de <em>Backtraking</em> per compte propi em vaig dir: &#8220;Xe, anem a fer el <em>programeta</em> per resoldre <em>sudokus</em>&#8220;. I em vaig posar en això. Quan vaig acabar-lo em vaig preguntar per què no acabar la tasca que el professor havia començat però havia abandonat per falta de temps i vaig llançar <a href="http://trac.assembla.com/fivworks/browser/eda/codi/backtracking/sudoku.cpp" target="_blank">el meu programa</a> per a que em mostrara tots els <em>sudokus</em> que es podien formar en un tauler de 9&#215;9.</p>
<p>Ignorant de mi. Com veia que tardava me&#8217;n vaig anar a berenar esperant que quan tornes tindria ja tots els <em>sudokus</em> possibles. Però com ja imaginareu, quan vaig tornar el portàtil estava a 74ºC  (i això que havia limitat la freqüència a 996MHz) i el fitxer de solucions ja ocupava centenars de MB. Va ser ací quan em vaig adonar que segurament serien MOLTS <em>sudokus</em>&#8230;</p>
<p>Concretament, hi han <strong>6,670,903,752,021,072,936,960 taulers de <em>sudoku</em> possibles</strong> (o deixe expressat així i no en notació científica per a que s&#8217;aprecie millor la magnitud d&#8217;aquest nombre). I ací és on comença el <em>friquisme</em>.</p>
<p><em><strong>Parlant matemàticament&#8230;</strong></em></p>
<p>Hi ha un extens <a href="http://en.wikipedia.org/wiki/Mathematics_of_Sudoku" target="_blank">article en la Wikipedia anglesa</a> dedicat a les matemàtiques relacionades amb aquest joc, la seva <a href="http://en.wikipedia.org/wiki/Mathematics_of_Sudoku#References" target="_blank">llista de referències</a> no es queda curta i són moltes les investigacions sobre <a href="http://en.wikipedia.org/wiki/Combinatorics" target="_blank">Combinatòria</a> i també <a href="http://en.wikipedia.org/wiki/Computational_complexity_theory" target="_blank">Complexitat Computacional</a> que es centren en aquest joc.</p>
<p>El problema general del <em>sudoku</em> entès com un tauler de <img src='http://s.wordpress.com/latex.php?latex=N%5E2%20%5Ctimes%20N%5E2&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='N^2 \times N^2' title='N^2 \times N^2' class='latex' /> caselles agrupades en blocs de <img src='http://s.wordpress.com/latex.php?latex=N%20%5Ctimes%20N&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='N \times N' title='N \times N' class='latex' /> (9&#215;9 caselles agrupades en blocs de 3&#215;3, en el nostre cas), es pot expressar com un problema de colorejat d&#8217;un graf, on cada casella seria un vèrtex del graf enumerat de la forma <img src='http://s.wordpress.com/latex.php?latex=%28x%2Cy%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='(x,y)' title='(x,y)' class='latex' /> (on <img src='http://s.wordpress.com/latex.php?latex=x%2C%20y%20%5Cin%20%5Cmathbb%7BN%7D%20%5Cmid%20x%20%5Cle%20N%5E2%20%5Cwedge%20y%20%5Cle%20N%5E2&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x, y \in \mathbb{N} \mid x \le N^2 \wedge y \le N^2' title='x, y \in \mathbb{N} \mid x \le N^2 \wedge y \le N^2' class='latex' />)¹ i on dos vèrtex <img src='http://s.wordpress.com/latex.php?latex=i%2C%20j&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='i, j' title='i, j' class='latex' /> estarien units per una aresta si:</p>
<ul>
<li><img src='http://s.wordpress.com/latex.php?latex=x_i%20%3D%20x_j&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x_i = x_j' title='x_i = x_j' class='latex' /> (dues caselles d&#8217;una mateixa columna).</li>
<li><img src='http://s.wordpress.com/latex.php?latex=y_i%20%3D%20y_j&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='y_i = y_j' title='y_i = y_j' class='latex' /> (dues caselles d&#8217;una mateixa fila).</li>
<li><img src='http://s.wordpress.com/latex.php?latex=%5Clceil%20%5Cfrac%7Bx_i%7D%7BN%7D%20%5Crceil%20%3D%20%5Clceil%20%5Cfrac%7Bx_j%7D%7BN%7D%20%5Crceil%20%5Cwedge%20%5Clceil%20%5Cfrac%7By_i%7D%7BN%7D%20%5Crceil%20%3D%20%5Clceil%20%5Cfrac%7By_j%7D%7BN%7D%5Crceil&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\lceil \frac{x_i}{N} \rceil = \lceil \frac{x_j}{N} \rceil \wedge \lceil \frac{y_i}{N} \rceil = \lceil \frac{y_j}{N}\rceil' title='\lceil \frac{x_i}{N} \rceil = \lceil \frac{x_j}{N} \rceil \wedge \lceil \frac{y_i}{N} \rceil = \lceil \frac{y_j}{N}\rceil' class='latex' /> (dues caselles en un mateix bloc).</li>
</ul>
<p>Llavors, la solució seria assignar un color entre els <img src='http://s.wordpress.com/latex.php?latex=N%5E2&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='N^2' title='N^2' class='latex' /> possibles a cada vèrtex (un nombre de l&#8217;1 al 9 vaja) de manera que qualsevol aresta no tinga el mateix color en el seus dos extrems.</p>
<p>Doncs veges tu per on, aquest problema <strong>és un problema del tipus <a href="http://en.wikipedia.org/wiki/NP-complete" target="_blank">NP-Complet</a></strong>. Jo havia sentit parlar d&#8217;aquesta <a href="http://en.wikipedia.org/wiki/Complexity_class" target="_blank">classe de problemes</a> (per tot allò de <em><a href="http://en.wikipedia.org/wiki/P_%3D_NP_problem" target="_blank">P = NP</a>?</em>, un dels set problemes del mil·leni, la solució dels quals és premiada amb un milió de dòlars), però fins aquesta vesprada no sabia concretament que era un problema NP-Complet i tampoc estic segur de saber-ho ara, així que abans de contar-vos alguna bajanada us referencie a l&#8217;<a href="http://en.wikipedia.org/wiki/NP-complete" target="_blank">article de la Wikipedia</a>.</p>
<p>El que sí us sé dir és que, en poques a paraules, no es coneix un algorisme &#8220;eficient&#8221;, on eficient significa polinòmic (<img src='http://s.wordpress.com/latex.php?latex=O%28n%5Ek%29%20%5Cmid%20k%20%5Cin%20%5Cmathbb%7BN%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(n^k) \mid k \in \mathbb{N}' title='O(n^k) \mid k \in \mathbb{N}' class='latex' />) per solucionar el problema. El que fa l&#8217;algorisme basat en <em>Backtracking</em> és explorar tot l&#8217;arbre de possibles solucions descartant aquelles que no complisquen les condicions del joc (descrites anteriorment).</p>
<p>Haurem de renunciar doncs, de moment, a trobar tots els possibles <em>sudokus</em>&#8230; Podríem seguir parlant de com, almenys, comptar quantes són aquestes solucions, però per això necessitaríem un apunt encara més llar i ja s&#8217;està fent tard i tampoc era eixe l&#8217;objectiu del post. Si us he despertat un poc l&#8217;interès i us ha picat el <em>cuquet friqui</em>, podeu visitar <a href="http://www.afjarvis.staff.shef.ac.uk/sudoku/" target="_blank">aquesta pàgina web</a> de Bertram Felgenhauer i Frazer Jarvis que dugueren endavant els càlculs.</p>
<p>&#8212;</p>
<p>¹ Pregue que disculpeu el formalisme d&#8217;algunes expressions, però aprofite l&#8217;apunt per provar que dóna de sí el plugin WP-Latex.</p>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/666" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/666/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Wodax (pre-alpha)</title>
		<link>http://www.elvoldelhomeocell.net/archives/267</link>
		<comments>http://www.elvoldelhomeocell.net/archives/267#comments</comments>
		<pubDate>Wed, 06 Aug 2008 23:39:32 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[Criptografia]]></category>
		<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[Projectes]]></category>
		<category><![CDATA[esteganografia]]></category>
		<category><![CDATA[friki]]></category>
		<category><![CDATA[wodax]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/blog/archives/267</guid>
		<description><![CDATA[Ja us vaig comentar que arrel del llibre de Cryptonomicon se me va ocórrer fer un xicotet programa d&#8217;esteganografia. Doncs ja hi ha una versió pre-alpha disponible. De moment podeu únicament ocultar un arxiu de text en una imatge i &#8230; <a href="http://www.elvoldelhomeocell.net/archives/267">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ja us vaig comentar que <a href="http://www.elvoldelhomeocell.net/archives/264" target="_blank">arrel del llibre de <em>Cryptonomicon</em></a> se me va ocórrer fer un xicotet programa d&#8217;esteganografia. Doncs ja hi ha una versió <em>pre-alpha</em> disponible.</p>
<p>De moment podeu únicament ocultar un arxiu de text en una imatge i obtenir un text ocult. No vaig a explicar com funciona per ara, simplement us deixaré una prova. Aquest text (<a href="http://ca.wikipedia.org/wiki/Esteganografia" target="_blank">extret de la Viquipèdia</a>) es troba ocult en la imatge de la dreta de la <a href="http://en.wikipedia.org/wiki/Mona_Lisa" target="_blank">Mona Lisa</a> (una obra d&#8217;art <a href="http://en.wikipedia.org/wiki/Speculation_about_Mona_Lisa" target="_blank">plena de misteris</a>), la de l&#8217;esquerre és l&#8217;original. Noteu alguna diferència (feu clic per ampliar les imatges al 100%)?</p>
<blockquote>
<p align="left">L&#8217;esteganografia és l&#8217;art i la ciència d&#8217;escriure missatges ocults de tal manera que només en conegui l&#8217;existència el destinatari previst; a diferència de la criptografia, en que l&#8217;existència del missatge per ell mateix no s&#8217;oculta, però el contingut és amagat.</p>
<p align="left">La paraula &#8220;steganografia&#8221; té origen grec i vol dir &#8220;escrit ocult o tapat&#8221;. Els seus orígens es remunten a l&#8217;any 440 aC. L&#8217;historiador Heròdot va mencionar dos exemples d&#8217;esteganografia a les seves Històries. Demeratus va escriure un missatge per alertar d&#8217;un possible atac a Grècia, escrivint-lo en una tauleta de fusta i la va cobrir de cera. Les tauletes de cera s&#8217;utilitzaven com a superfície d&#8217;escriptura reusable. Un altre exemple de l&#8217;ús de l&#8217;esteganografia el trobem en Histiaeus, que rapava el cap dels seus esclaus més fidels i els tatuava un missatge. Quan el cabell els creixia, el missatge quedava ocult. El propòsit d&#8217;aquests missatges fou instigar una revolta contra els perses. Més tard, Johannes Trithemius va escriure Steganographia, un tractat de criptografia i esteganografia disfressat de llibre de màgia negra.</p>
</blockquote>
<p align="center"><a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/08/mona.png" target="_blank" rel="lightbox[267]"><img title="Mona Lisa original" src="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/08/mona_thumb.png" alt="Mona Lisa original" width="210" height="300" /></a> <a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/08/mona_out.png" target="_blank" rel="lightbox[267]"><img title="Mona Lisa modificada" src="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/08/mona_out_thumb.png" alt="Mona Lisa original" width="210" height="300" /></a></p>
<p>Està bé, fem les coses més fàcils&#8230; El mateix text està ocult en la imatge de la dreta. Feu clic i veureu les imatges al 500% i notareu xicotetes diferències en el color d&#8217;alguns píxels.</p>
<p align="center"><a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/08/rgb_big.png" target="_blank" rel="lightbox[267]"><img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/08/rgb.png" alt="" width="128" height="128" /></a> <a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/08/rgb_out_big.png" target="_blank" rel="lightbox[267]"><img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/08/rgb_out.png" alt="" width="128" height="128" /></a></p>
<p align="left">Ara falta fer que a banda d&#8217;ocultar text en les imatges, aquest text estiga xifrat per evitar així possibles atacs per força bruta (que són fins i tot prou complicats com ja us explicaré). Us deixe un <a href="http://svn.assembla.com/svn/wodax/trunk/" target="_blank">enllaç al servidor Subversion</a> on tinc penjat l&#8217;última versió del codi per si algú vol pegar-li una <em>miradeta</em> al codi (necessitareu la llibreria <a href="http://www.nongnu.org/pngpp/" target="_blank">png++</a>).</p>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/267" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/267/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Google CodeJam 2008 i els nombres extraterrestres</title>
		<link>http://www.elvoldelhomeocell.net/archives/262</link>
		<comments>http://www.elvoldelhomeocell.net/archives/262#comments</comments>
		<pubDate>Fri, 04 Jul 2008 18:21:38 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[algorismes]]></category>
		<category><![CDATA[concursos]]></category>
		<category><![CDATA[friki]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[google jam]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/blog/archives/262</guid>
		<description><![CDATA[Fa un parell de setmanes (el cap de setmana abans de l&#8217;examen de Fonaments Físics de la Informàtica) em vaig assabentar que els de Google organitzaven un campionat d&#8217;algorísmica i dic: &#8220;Coi, vaig a apuntar-me a veure quin tipus de &#8230; <a href="http://www.elvoldelhomeocell.net/archives/262">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Fa un parell de setmanes (el cap de setmana abans de l&#8217;examen de Fonaments Físics de la Informàtica) em vaig assabentar que els de <a href="http://www.google.com" target="_blank">Google</a> <a href="http://code.google.com/codejam/" target="_blank">organitzaven un campionat d&#8217;algorísmica</a> i dic: &#8220;Coi, vaig a apuntar-me a veure quin tipus de problemes plantegen&#8221;. Aprofitant els moments en que la idea del suïcidi em passava pel cap (vaig estar el cap de setmana sol al pis sense sortir, no proveu mai d&#8217;estar dos dies sense parlar amb cap humà&#8230;) em vaig posar a llegir els problemes que estaven plantejats per al període de proves i vaig resoldre el primer de quatre (el fàcil, clar).</p>
<p>El problema que es plantejava era un simple canvi de base entre dos sistemes de numeració, tradueixo la descripció del problema:</p>
<blockquote><p>El sistema numèric decimal està composat per deu dígits, els quals representem com &#8220;0123456789&#8243; (els dígits en un sistema estan escrits del menor al major). Imagina que has descobert un sistema numèric extraterrestres compost per uns quants dígits numèrics, els quals poden ser o no els mateixos del sistema decimal. Per exemple, si el sistema numèric extraterrestres es representa com &#8220;oF8&#8243;, els nombres de l&#8217;1 al 10 serien (F, 8, Fo, FF, F8, 8o, 8F, 88, Foo, FoF). Voldríem poder treballar amb nombres d&#8217;un sistema extraterrestres arbitrari. Més generalment, volem ser capaços de convertir un nombre qualsevol que està escrit en un sistema extraterrestres, a un altre sistema extraterrestres.</p></blockquote>
<p>El que se me va ocòrrer a mi va ser generalitzar els canvis de base binari-decimal i decimal-binari i xim-pum. Tant senzill com això. En la meva solució faig un canvi de base del sistema extraterrestre d&#8217;entrada a decimal i després de decimal al sistema extraterrestre de sortida. Per què? Doncs no sé, perquè se me va ocórrer de fer així i és el que estic acostumat a fer per passar d&#8217;hexadecimal a decimal o a binari. Però en principi no hi ha cap problema per fer una conversió directa entre els dos sistemes, sols has de saber fer-ho i jo no m&#8217;he aturat a pensar-ho.</p>
<p>Per programar la solució vaig utilitzar el llenguatge C++, que tenia ganes de provar-lo i el qual segurament utilitzaré aquest estiu per a un xicotet projecte pendent que tinc (ja us parlaré d&#8217;ell, però està relacionat amb el Número de Bacon) i que és el llenguatge utilitzat en <em><a href="http://www.upv.es/pls/oalu/sic_asi.Busca_Asi?p_codi=5824&amp;p_caca=act&amp;P_IDIOMA=v&amp;p_vista=" target="_blank">Estructures de Dades i Algorismes</a></em> (EDA), una assignatura que tindré l&#8217;any que ve i que, no vaig a enganyar-vos, tinc ganes de cursar (disculpeu la meva  els que us heu tingut que enfrontar a ella&#8230;). Una de les estructures implementades en la <a href="http://www.sgi.com/tech/stl/" target="_blank">llibreria STL</a> de C++ que he utilitzat és el <em><a href="http://www.sgi.com/tech/stl/Map.html">map</a> </em>(mapa, per als qui necessiteu traducció ¬¬), que no sé quina diferència presenta respecte d&#8217;una taula <em>Hash</em>. L&#8217;he utilitzada per relacionar un símbol del sistema extraterrestre d&#8217;entrada amb un valor i poder així operar amb ells.</p>
<p>En fi, <a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/07/alien_numbers.cpp" target="_blank">ací teniu la solució</a> (que és correcta) i uns exemples de canvi de base:</p>
<ul>
<li>Nombre: <strong>9</strong>; Sistema d&#8217;entrada: <strong>0123456789</strong>; Sistema de sortida: <strong>oF8</strong>; Solució: <strong>Foo</strong></li>
<li>Nombre: <strong>Foo</strong>; Sistema d&#8217;entrada: <strong>oF8</strong>; Sistema de sortida: <strong>0123456789</strong>; Solució: <strong>9</strong></li>
<li>Nombre: <strong>13</strong>; Sistema d&#8217;entrada: <strong>0123456789abcdef</strong>; Sistema de sortida:<strong> 01</strong>; Solució: <strong>10011</strong></li>
<li>Nombre: <strong>CODE</strong>; Sistema d&#8217;entrada: <strong>O!CDE?</strong>; Sistema de sortida: <strong>A?JM!.</strong>; Solució: <strong>JAM!</strong></li>
<li>Nombre: <strong>eEEeeeEEeeeEeE&#8230;E</strong>; Sistema d&#8217;entrada: <strong>E.e</strong>; Sistema de sortida: <strong>!0TtKXJ]hZi_|Q8sg[&gt;~DNAnWx$Gf%,k"2L&amp;ydYB</strong>; Solució: <strong>T$|gB~</strong></li>
<li>Nombre: <strong>&lt;-"i4g</strong>; Sistema d'entrada: <strong>m&lt;zqSI#F2]$`&#8221;9+~4&gt;kQxoGV{?T;7yvR_l3B-ti/ag6.%ews[8</strong>; Sistema de sortida: <strong>u%v</strong>; Solució: <strong>%%u%%vu%u%vvu%%u%vv</strong></li>
</ul>
<p>La primera fase de la competició, la de qualificació, és el pròxim 16 de Juliol de les 23:00 UTC fins el 17 de Juliol a la mateixa hora (la fase dura 24h). Tinc curiositat per veure els problemes que plantegen, però no crec que sàpiga resoldre&#8217;n cap. No sé prou d&#8217;algorísmica. Per a que us feu una idea, el quart problema de la fase d&#8217;entrenament d&#8217;on he tret el problema anterior, és el següent:</p>
<blockquote><p>Teniu una llista d&#8217;objectes a comprar avui, i sabeu els llocs (representats per punts en uns eixos cartesians) d&#8217;unes poques tendes en l&#8217;àrea. Sabeu també quines coses de la vostra llista ven cada tenda i a quin preu ho venen. Donat el preu de la gasolina, quina és la mínima quantitat de diners que necessiteu per comprar tots els objectes i tornar a casa? Comences i acabes a la teva casa, que està en la posició (0,0) dels eixos cartesià.</p>
<p>Per fer les coses més interessants, alguns dels objectes en la llista es poden fer malbé. Quan compreu un o més d&#8217;aquests productes, no podeu conduir fins una altra tenda sense abans passar per casa. Tots els objectes de la vostra llista es troben en alguna tenda, per tant el viatge sempre és possible.</p></blockquote>
<p>Aquest problema ja és <em>xunguet</em>, almenys per als coneixements que tinc jo. Em recorda al <a href="http://mathworld.wolfram.com/ChinesePostmanProblem.html" target="_blank">problema del carter xinès</a> o algun paregut, un famós problema del qual he sentit parlar per la xarxa mare i no tinc ni idea de com es resol. S&#8217;agrairia als visitants que han fet Algorísmica (que sé que hi han) que ens contaren alguna cosa a través dels comentaris&#8230;</p>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/262" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/262/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Write in C</title>
		<link>http://www.elvoldelhomeocell.net/archives/261</link>
		<comments>http://www.elvoldelhomeocell.net/archives/261#comments</comments>
		<pubDate>Thu, 03 Jul 2008 10:21:44 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[Humor]]></category>
		<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Música]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[caxondeo]]></category>
		<category><![CDATA[friki]]></category>
		<category><![CDATA[write in C]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/blog/archives/261</guid>
		<description><![CDATA[Avui estava organitzant tot el material docent virtual que tenia de les assignatures que he cursat i per casualitat m&#8217;he trobat en el Poliforma&#8217;t (una espècie d&#8217;aula virtual on els professors col·loquen les transparències, apunts, exercicis, notes, etc.) amb un &#8230; <a href="http://www.elvoldelhomeocell.net/archives/261">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Avui estava organitzant tot el material docent virtual que tenia de les assignatures que he cursat i per casualitat m&#8217;he trobat en el Poliforma&#8217;t (una espècie d&#8217;aula virtual on els professors col·loquen les transparències, apunts, exercicis, notes, etc.) amb un enllaç a una cançó una mica <em>geek </em>(o friqui, directament).</p>
<p>La lletra de la cançó la podeu trobar en <a href="http://www.cs.bgu.ac.il/~omri/Humor/write_in_c.html" target="_blank">aquest enllaç</a>, però ja us avise que està en anglès i necessites saber alguna coseta del llenguatge de programació C (i ser un poc friqui) per entendre-la. L&#8217;heu de cantar amb la melodia de <em>&#8220;Let it be&#8221;</em> dels (<em>The</em>) <em>Beatles </em>[Kit-Kat: Per què mai ningú posa el <em>The </em>al nom d'aquest grup?]. Buscant pel Youtube algun altre paio que s&#8217;atrevís a cantar-la m&#8217;he trobat amb <a href="http://www.youtube.com/watch?v=J5LNTTGDKYo" target="_blank">aquest vídeo</a> on la podeu escoltar amb algun que altre refilet.</p>
<p>El que m&#8217;ha fet gràcia del vídeo ha sigut el fons: una imatge fixa amb la fotografia de Denis Ritchie (un dels creadors del C) i el següent text a l&#8217;aire Bruce Lee i el seu <em>Be water my friend</em>.</p>
<p align="center">Empty your memory, // Buida la teva memòria,<br />
with a free()&#8230; // amb un free()&#8230;<br />
like a pointer! //com un punter!</p>
<p align="center">If you cast a pointer to an integer, // Si moldeges un punter a un enter,<br />
it becomes the integer. // es convertirà en l&#8217;enter.<br />
If you cast a pointer to a struct,  // Si moldeges un punter a una estructura,<br />
it becomes the struct&#8230; // es convertirà en l&#8217;estructura&#8230;</p>
<p align="center">The pointer can crash&#8230; // El punter pot fallar&#8230;<br />
and can overflow&#8230; //i pot desbordar-se&#8230;
</p>
<p align="center">Be a pointer my friend&#8230; // Sigues un punter amic meu&#8230;</p>
<p align="left">M&#8217;ha fet gràcia, què voleu que us diga? Vaig a escoltar-la de nou&#8230;</p>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/261" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/261/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Frikisme 100%</title>
		<link>http://www.elvoldelhomeocell.net/archives/242</link>
		<comments>http://www.elvoldelhomeocell.net/archives/242#comments</comments>
		<pubDate>Wed, 12 Mar 2008 13:22:28 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[El Blog]]></category>
		<category><![CDATA[Estudis]]></category>
		<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Lectura]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[assemblador]]></category>
		<category><![CDATA[fco]]></category>
		<category><![CDATA[fibonacci]]></category>
		<category><![CDATA[fiv]]></category>
		<category><![CDATA[friki]]></category>
		<category><![CDATA[pcspim]]></category>
		<category><![CDATA[upv]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/blog/archives/242</guid>
		<description><![CDATA[Doncs aquest matí he anat al centre metge (de Benimaclet) i a l&#8217;Hospital Clínic a fer unes gestions i quan he acabat m&#8217;ha entrat una gossera enorme d&#8217;anar-me&#8217;n a classe i m&#8217;he dit: &#8220;em quede a casa a estudiar&#8221;. Qualsevol &#8230; <a href="http://www.elvoldelhomeocell.net/archives/242">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Doncs aquest matí he anat al centre metge (de Benimaclet) i a l&#8217;Hospital Clínic a fer unes gestions i quan he acabat m&#8217;ha entrat una gossera enorme d&#8217;anar-me&#8217;n a classe i m&#8217;he dit: &#8220;em quede a casa a estudiar&#8221;.</p>
<p>Qualsevol altra persona amb bona salut mental s&#8217;hauria encès la televisió i hauria mirat algun programa de debats d&#8217;aquests que fan pels matins, que segur que deuen d&#8217;estar d&#8217;allò més &#8220;interessants&#8221; després de les eleccions. Però jo no he fet això!</p>
<p>Com que m&#8217;estava pelant la classe de FCO m&#8217;han entrat remordiments i m&#8217;he dit: &#8220;anem a fer exercicis&#8221; i m&#8217;he posat a fer exercicis d&#8217;assemblador. Doncs bé, farà una estoneta, quan ja estava cansat de fer exercicis (després de quasi dues hores) m&#8217;ha vingut al cap de provar de fer algun programeta en assemblador i açò és el que he fet (imagine que dels que llegiu el bloc ningú entendreu que collons fa, però és igual, és una cosa MOLT <em>friki</em>).</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="asm" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">.data</span>
itera<span style="color: #339933;">:</span>    <span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">byte</span> <span style="color: #0000ff;">0x0A</span>       #numero de iteracions <span style="color: #009900; font-weight: bold;">&#40;</span>sense comptar a<span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #0000ff;">1</span><span style="color: #009900; font-weight: bold;">&#93;</span> i a<span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #0000ff;">2</span><span style="color: #009900; font-weight: bold;">&#93;</span><span style="color: #009900; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">.data</span> <span style="color: #0000ff;">0x10010010</span>
vector<span style="color: #339933;">:</span>    <span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">byte</span> <span style="color: #0000ff;">0x00</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">0x01</span> #vector que representa la successio<span style="color: #339933;">.</span>
#els primers valors corresponen a<span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #0000ff;">1</span><span style="color: #009900; font-weight: bold;">&#93;</span> = <span style="color: #0000ff;">0</span> i a<span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #0000ff;">2</span><span style="color: #009900; font-weight: bold;">&#93;</span> = <span style="color: #0000ff;">1</span><span style="color: #339933;">.</span>
&nbsp;
<span style="color: #339933;">.</span>text
<span style="color: #339933;">.</span>globl __start
&nbsp;
__start<span style="color: #339933;">:</span>
la $<span style="color: #0000ff;">4</span><span style="color: #339933;">,</span> itera
la $<span style="color: #0000ff;">7</span><span style="color: #339933;">,</span> vector
lb $<span style="color: #0000ff;">3</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">1</span><span style="color: #009900; font-weight: bold;">&#40;</span>$<span style="color: #0000ff;">7</span><span style="color: #009900; font-weight: bold;">&#41;</span>    # a<span style="color: #009900; font-weight: bold;">&#91;</span>n<span style="color: #339933;">-</span><span style="color: #0000ff;">1</span><span style="color: #009900; font-weight: bold;">&#93;</span><span style="color: #339933;">.</span> a<span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #0000ff;">2</span><span style="color: #009900; font-weight: bold;">&#93;</span> = <span style="color: #0000ff;">1</span>
lb $<span style="color: #0000ff;">2</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">0</span><span style="color: #009900; font-weight: bold;">&#40;</span>$<span style="color: #0000ff;">7</span><span style="color: #009900; font-weight: bold;">&#41;</span>    # a<span style="color: #009900; font-weight: bold;">&#91;</span>n<span style="color: #339933;">-</span><span style="color: #0000ff;">2</span><span style="color: #009900; font-weight: bold;">&#93;</span><span style="color: #339933;">.</span> a<span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #0000ff;">1</span><span style="color: #009900; font-weight: bold;">&#93;</span> = <span style="color: #0000ff;">0</span>
addi $<span style="color: #0000ff;">7</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">7</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">2</span>  # comencem a afegir a partir de la tercena pos<span style="color: #339933;">.</span>
lb $<span style="color: #0000ff;">4</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">0</span><span style="color: #009900; font-weight: bold;">&#40;</span>$<span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#41;</span>    # iteracions
addi $<span style="color: #0000ff;">6</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">0</span>  # contador
&nbsp;
bucle<span style="color: #339933;">:</span>
<span style="color: #00007f; font-weight: bold;">add</span> $<span style="color: #0000ff;">5</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">2</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">3</span>  # a<span style="color: #009900; font-weight: bold;">&#91;</span>n<span style="color: #009900; font-weight: bold;">&#93;</span> = a<span style="color: #009900; font-weight: bold;">&#91;</span>n<span style="color: #339933;">-</span><span style="color: #0000ff;">1</span><span style="color: #009900; font-weight: bold;">&#93;</span> <span style="color: #339933;">+</span> a<span style="color: #009900; font-weight: bold;">&#91;</span>n<span style="color: #339933;">-</span><span style="color: #0000ff;">2</span><span style="color: #009900; font-weight: bold;">&#93;</span>
<span style="color: #00007f; font-weight: bold;">add</span> $<span style="color: #0000ff;">2</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">3</span>
<span style="color: #00007f; font-weight: bold;">add</span> $<span style="color: #0000ff;">3</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">5</span>
addi $<span style="color: #0000ff;">6</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">6</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">1</span>  #incrementa comptador
sb $<span style="color: #0000ff;">5</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">0</span><span style="color: #009900; font-weight: bold;">&#40;</span>$<span style="color: #0000ff;">7</span><span style="color: #009900; font-weight: bold;">&#41;</span>
addi $<span style="color: #0000ff;">7</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">7</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">1</span>
bne $<span style="color: #0000ff;">6</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">4</span><span style="color: #339933;">,</span> bucle  #si encara no hem fet totes <span style="color: #00007f; font-weight: bold;">les</span> iter<span style="color: #339933;">.</span> repetim<span style="color: #339933;">...</span>
&nbsp;
<span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">end</span></pre></td></tr></table></div>

<p>I què és el què fa la cosa aquesta? Doncs va omplint un vector en memòria on cada element és un terme de la successió de Fibonacci (0,1,1,2,3,5,8,13, &#8230;). Ni més ni menys.</p>
<p>La idea era fer una cosa semblant a aquesta feta en C:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio .h&gt;</span>
<span style="color: #339933;">#define MAX_ITER 10</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #993333;">int</span> vector<span style="color: #009900;">&#91;</span>MAX_ITER<span style="color: #339933;">+</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> i<span style="color: #339933;">;</span>
vector<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
vector<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d %d &quot;</span><span style="color: #339933;">,</span> vector<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> vector<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
i <span style="color: #339933;">=</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">!=</span> MAX_ITER<span style="color: #339933;">+</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
vector<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> vector<span style="color: #009900;">&#91;</span>i<span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+</span> vector<span style="color: #009900;">&#91;</span>i<span style="color: #339933;">-</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d &quot;</span><span style="color: #339933;">,</span> vector<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
i<span style="color: #339933;">++;</span>
<span style="color: #009900;">&#125;</span>
putchar<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'n'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #339933;">&lt;/</span>stdio<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Ací tenim el resultat de l&#8217;execució del programa en assemblador:</p>
<p style="text-align: center;"><a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/03/fibonacci.png" target="_blank" rel="lightbox[242]"><img class="aligncenter" src="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/03/fibonacci_sm.png" alt="" width="400" height="42" /></a></p>
<p align="left">Descarrega&#8217;t el codi font i juga una poc amb ell (fixa&#8217;t en que el vector és de bytes!). El llenguatge assemblador és per al processador MIPS R2000 així que necessitaràs un simulador. Jo utilitze el <a href="http://pages.cs.wisc.edu/~larus/spim.html" target="_blank">Spim</a>, està disponible tant per a Windows com per a Linux (encara que jo utilitze la versió de Windows sobre el Wine).</p>
<ul>
<li><a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/03/fibonacci.c">fibonacci.c</a></li>
<li><a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2008/03/fibonacci.asm" target="_blank">fibonacci.asm</a></li>
</ul>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/242" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/242/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Canvpan (que original&#8230;)</title>
		<link>http://www.elvoldelhomeocell.net/archives/217</link>
		<comments>http://www.elvoldelhomeocell.net/archives/217#comments</comments>
		<pubDate>Tue, 27 Nov 2007 22:01:57 +0000</pubDate>
		<dc:creator>Joan</dc:creator>
				<category><![CDATA[Informàtica]]></category>
		<category><![CDATA[Programació]]></category>
		<category><![CDATA[Sistemes Operatius]]></category>

		<guid isPermaLink="false">http://www.elvoldelhomeocell.net/blog/archives/217</guid>
		<description><![CDATA[A mi personalment em cansen de seguida els fons de pantalla, cada dos o tres dies haig de canviar-lo. Però a banda no m&#8217;agrada perdre el temps buscant un bon fons d&#8217;escriptori, així que em vaig decidir per programar una &#8230; <a href="http://www.elvoldelhomeocell.net/archives/217">Continua llegint <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A mi personalment em cansen de seguida els fons de pantalla, cada dos o tres dies haig de canviar-lo. Però a banda no m&#8217;agrada perdre el temps buscant un bon fons d&#8217;escriptori, així que em vaig decidir per programar una xicoteta utilitat per al <a href="http://www.gnome.org" target="_blank">GNOME</a> (que és el gestor de finestres que utilitze) que fes aquesta tasca per mi.</p>
<p>La idea inicial era fer una espècie de <em>daemon</em> que estigués sempre executant-se i que cada cert temps canviés automàticament el fons d&#8217;escriptori. Però com que els meus coneixements sobre <em>Python</em> (que és el llenguatge que he utilitzat per programar la utilitat) no són massa extensos, de moment em conforme amb aquesta versió 0.1 del Canvpan.</p>
<p><strong>Com funciona per dins?</strong><br />
Canvpan es connecta a <a href="http://www.socwall.com/" target="_blank"><em>socwall.com</em></a> i fa una recerca en busca de fonts d&#8217;escriptori que complisquen un requisits (especificats en l&#8217;arxiu <em>config</em>, bàsicament grandària i categoria). Com que la gent de <em>socwall.com</em> no té disponible cap API per connectar-se a la seva base de dades, com si tenen els de <a href="http://www.flickr.com" target="_blank">Flickr</a>, el meu <em>programeta</em> ha de filtrar TOT el contingut de l&#8217;arxiu HTML generat en el servidor de <em>socwall.com</em> (cosa que el fa lent). Per això utilitze una llibreria que em presenta l&#8217;arxiu HTML en un <a href="http://es.wikipedia.org/wiki/DOM" target="_blank">DOM</a>, cosa que facilita enormement la recerca d&#8217;enllaços a les imatges que m&#8217;interessen.</p>
<p>Les imatges que es troben en la recerca es guarden en una llista i es fa un <em>random</em> entre els elements d&#8217;aquesta. L&#8217;element elegit es descarregat (amb la funció <em>urlretrieve</em> de la llibreria <em>urllib</em>) i es col·locat com a fons d&#8217;escriptori fent ús d&#8217;una fantàstica llibreria que incorpora Python per entendre&#8217;s amb el GNOME (la llibreria <em>gconf</em>).</p>
<p><strong>I cara a l&#8217;usuari?</strong></p>
<ul>
<li> Per canviar de fons d&#8217;escriptori:</li>
</ul>
<blockquote><p> $python canvpan.py change</p></blockquote>
<ul>
<li>Per canviar el directori de descàrrega:</li>
</ul>
<blockquote><p> $python canvpan.py dir /nou/directori</p></blockquote>
<ul>
<li>Per canviar la grandària del fons:</li>
</ul>
<blockquote><p> $python canvpan.py size [Standard, Widescreen, Dual%20Monitor, All]</p></blockquote>
<ul>
<li>Per canviar la categoria del fons:</li>
</ul>
<blockquote><p> $python canvpan.py  cat [Everything, Abstract, Anime, Art, Buildings, Computer%20Related, Creatures, Fantasy, Games, Music, Nature, People, Products, Sci-Fi, Seasonal, Space, Sports, Transportation, TV%20and%20Movies]</p></blockquote>
<p><strong>La configuració per defecte</strong><br />
Arxiu <em>conf</em>:</p>
<blockquote><p>/home/<em>usuari</em><br />
Default<br />
Everything</p></blockquote>
<p>Evidentment hauràs de canviar el directori al teu home o a qualsevol altre lloc on tingues permisos d&#8217;escriptura. Allí es crearà l&#8217;arxiu <em>.temp_wallpaper.jpg</em> (recordeu que el punt de davant significa que és un arxiu ocult) que contindrà la imatge descarregada de <em>socwall.com.</em></p>
<p>Per configurar el <em>programeta,</em> utilitzeu els comandaments que he mencionat abans. El programa és molt sensible als salts de línia, espais en blanc i demés, així que si no us voleu arriscar a fer malbé quelcom, utilitzeu els comandaments <em>dir</em>, <em>size</em> i <em>cat</em>. I apunteu a un directori, a una grandària i a una categoria vàlides. Confie en vosaltres <img src='http://www.elvoldelhomeocell.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p><strong>Pròximes millores </strong><br />
El pròxim que faré (i ja estic fent alguna cosa), quant tinga més temps, és fer-lo més ràpid. Com? Doncs he pensat en guardar en un arxiu la llista amb els enllaços a les imatges de <em>socwall.com</em> i fer un <em>random</em> dels elements d&#8217;aquesta llista i eliminar el seleccionat, fins que la llista quede buida i aleshores es torne a carregar de la mateixa forma. Així no hauríem de descarregar la llista d&#8217;imatges cada vegada.</p>
<p>Se vos n&#8217;acudeix alguna més?</p>
<p>Pegueu-li una <em>miradeta</em> al codi font i perfeccioneu-lo, això si&#8230; compartiu-lo amb nosaltres!</p>
<p><strong>Arxius</strong><br />
<a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2007/11/libxml2dom-0.4.4.tar.gz"> limxml2dom-0.4.4.tar.gz</a> (Llibreria necessària per llegir l&#8217;HTML en DOM).<br />
<a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2007/11/canvpan.tgz" target="_blank"> canvpan.tgz</a> (El meu<em> programeta</em>).</p>
<p><a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2007/11/screenshot-canvpan.png" title="Fons d’escriptori obtingut del canvpan" rel="lightbox[217]"></a></p>
<p style="text-align: center"><a href="http://www.elvoldelhomeocell.net/wp-content/uploads/2007/11/screenshot-canvpan.png" title="Fons d’escriptori obtingut del canvpan" rel="lightbox[217]"><img src="http://www.elvoldelhomeocell.net/wp-content/uploads/2007/11/screenshot-canvpan_mini.png" title="Fons d’escriptori obtingut del canvpan" alt="Fons d’escriptori obtingut del canvpan" /></a></p>
<div class="al2fb_like_button"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=269247799756783&amp;xfbml=1" type="text/javascript"></script>
<fb:like href="http://www.elvoldelhomeocell.net/archives/217" layout="standard" show_faces="true" width="450" action="like" font="arial" colorscheme="light" ref="AL2FB"></fb:like></div>]]></content:encoded>
			<wfw:commentRss>http://www.elvoldelhomeocell.net/archives/217/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

