<?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/"
	>

<channel>
	<title>blog</title>
	<atom:link href="http://blog.vfiack.fr/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.vfiack.fr</link>
	<description>blog.vfiack.fr</description>
	<pubDate>Fri, 26 Mar 2010 08:49:22 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>La méthode Monte-Carlo appliquée au go, pour les nuls</title>
		<link>http://blog.vfiack.fr/93-la-methode-monte-carlo-appliquee-au-go-pour-les-nuls/</link>
		<comments>http://blog.vfiack.fr/93-la-methode-monte-carlo-appliquee-au-go-pour-les-nuls/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 08:49:22 +0000</pubDate>
		<dc:creator>vfiack</dc:creator>
		
		<category><![CDATA[Développement]]></category>

		<category><![CDATA[Jeu de go]]></category>

		<category><![CDATA[Monte Carlo]]></category>

		<guid isPermaLink="false">http://blog.vfiack.fr/?p=93</guid>
		<description><![CDATA[J&#8217;avais découvert le jeu de go en 2004 suite a un article sur les difficultés d&#8217;implémentation d&#8217;un programme efficace.
J&#8217;ai appris les règles a ce moment la, et bricolé un goban en tissus, puis tout laissé tombé en moins d&#8217;un mois faute de partenaires.
J&#8217;ai repris cet été, et je passe mon temps a jouer sur Internet [...]]]></description>
			<content:encoded><![CDATA[<p>J&#8217;avais découvert le jeu de go en 2004 suite a un article sur les difficultés d&#8217;implémentation d&#8217;un programme efficace.</p>
<p>J&#8217;ai appris les règles a ce moment la, et bricolé un goban en tissus, puis tout laissé tombé en moins d&#8217;un mois faute de partenaires.</p>
<p>J&#8217;ai repris cet été, et je passe mon temps a jouer sur Internet (KGS, IGS et wBaduk de temps en temps). Je pense que je suis bien accroc ce coup-ci.<br />
Et pour boucler la boucle, je viens d&#8217;écrire un petit programme afin de comprendre comment ceux-ci peuvent fonctionner, a partir d&#8217;un algorithme de référence (je n&#8217;ai rien inventé).</p>
<p>Je vais essayer de le décrire ici. </p>
<h2>Le programme de référence</h2>
<p>Le <a href="http://cgos.boardspace.net/public/javabot.zip">programme de référence (jrefgo)</a> utilise la méthode Monte-Carlo avec une évaluation en All Moves As First (AMAF). </p>
<p>Et si vous avez compris cette phrase, vous n&#8217;avez pas besoin de lire cette note, puisque c&#8217;est précisément ce que je vais tenter d&#8217;expliquer.</p>
<p>Ce programme a l&#8217;avantage d&#8217;être concis : une classe pour <a href="http://www.lysator.liu.se/~gunnar/gtp/">GTP (Go Text Protocol)</a>, un lanceur, et une classe principale qui gère tout le reste.</p>
<p>Malheureusement, il n&#8217;est pas aussi clair qu&#8217;il le pourrait, les variables ont des noms abscons, il y a des manipulations de bits qui ne sont pas forcément nécessaires, et beaucoup d&#8217;attributs utilisés comme des variables globales. Il reste néanmoins une bonne base, et je me suis plus ou moins contenté de le réarranger a ma sauce, sans en changer le fonctionnement.</p>
<p>Attention: je suis un développeur, pas un statisticien, il est donc possible que j&#8217;ai introduit des erreurs ou mal compris un point. N&#8217;hésitez pas a me corriger si vous voyez une bourde.</p>
<h2>Pourquoi le jeu de go est difficile pour un ordinateur</h2>
<p>Pour la plupart des jeux de stratégies de ce type, une intelligence artificielle est composée de deux éléments principaux :</p>
<ul>
<li>un arbre des coups possibles pour chaque joueur</li>
<li>une fonction d&#8217;évaluation d&#8217;une position donnée</li>
</ul>
<p>A partir de la, on peut évaluer les positions obtenues après X coups, et prendre le coup qui amène a la meilleure de ces positions.</p>
<p>Cette méthode n&#8217;est pas applicable au go pour deux raisons : </p>
<ul>
<li>le nombre de coups possibles est gigantesque, il n&#8217;est pas possible de générer un arbre d&#8217;une profondeur acceptable</li>
<li>il est très dur d&#8217;évaluer une position (Ce territoire est-il définitif ? Ce groupe est-il vraiment vivant ? Combien vaut cette influence ? Et la pierre en bas, elle est morte, mais a-t-elle encore du potentiel ?)</li>
</ul>
<p>Il a donc fallu trouver un autre angle d&#8217;approche.</p>
<h2>La méthode Monte-Carlo</h2>
<p>L&#8217;idée est assez simple, et je suis moi-même étonné de voir qu&#8217;elle fonctionne aussi bien :<br />
puisqu&#8217;on n&#8217;est capable d&#8217;évaluer une position qu&#8217;en fin de partie, il suffit de la finir ! </p>
<p>Ben oui, mais comment ? En jouant des coups au hasard. C&#8217;est ce qu&#8217;on appelle un &#8220;playout&#8221;. Ça fait une fin de partie absolument non réaliste, et peu fiable.<br />
Mais si on joue 10 000 playouts ou plus, on commence a avoir des résultats intéressants. C&#8217;est une approche probabiliste. </p>
<p>En divisant le nombre de victoires par le nombre de playouts, on obtient une probabilité de victoire, le winrate. Le score ne compte pas vraiment, gagner de 0.5 ou de 30 points n&#8217;a pas d&#8217;importance. Si une position a un winrate > 0.5, la position est favorable, et inversement. </p>
<p>Corolaire : le coup qui amène a une position ayant le meilleur winrate est probablement le meilleur coup.</p>
<h2>All Moves As First</h2>
<p>Reste a savoir comment on mémorise le winrate pour chaque coup ou position. L&#8217;approche AMAF, c&#8217;est de ne pas tenir compte de l&#8217;ordre des coups, et juger toutes les pierres jouées entre la position initiale et la position finale. Par exemple, si 50 coups sont joués entre la position pour laquelle on veut trouver un coup, et la fin d&#8217;un playout, on comptabilise une victoire pour chacun des coups qui ont été joués.</p>
<p>L&#8217;avantage de cette méthode est le stockage du résultat : un tableau de la taille d&#8217;un goban suffit, avec un score pour chaque case. On obtient le meilleur coup après<br />
simulation de toutes les fins de parties en parcourant ce tableau, et en conservant le coup avec le meilleur winrate.</p>
<p>L&#8217;inconvénient majeur de cette méthode est que le coup ayant le plus de chance de marcher contre un adversaire jouant au hasard n&#8217;est pas forcément le meilleur coup.<br />
Un humain ne rate pas un simple shicho et ne se met pas en auto-atari en espérant que son adversaire l&#8217;ignore&#8230;</p>
<h2>Implémentation</h2>
<p>Il nous faut certaines fonction de base que je ne décrirais pas en détail, mais dont vous pouvez voir le source :</p>
<ul>
<li>une structure contenant une position (<a href="http://bitbucket.org/vfiack/weiqibot/src/c710f149ec48/src/main/java/fr/vfiack/go/Board.java#cl-27">classe Board</a>)</li>
<li>un moyen d&#8217;avoir le score d&#8217;une position finale (<a href="http://bitbucket.org/vfiack/weiqibot/src/c710f149ec48/src/main/java/fr/vfiack/go/Scorer.java#cl-3">classe Scorer</a>)</li>
<li>un moyen de vérifier la validité d&#8217;un coup et de le jouer (<a href="http://bitbucket.org/vfiack/weiqibot/src/c710f149ec48/src/main/java/fr/vfiack/go/MoveManager.java#cl-4">classe MoveManager</a>)</li>
</ul>
<p>Une fois qu&#8217;on a ces éléments, on peut rentrer dans le cœur du problème : la génération des playouts, les statistiques, et enfin la sélection du coup a jouer.</p>
<p><strong>Génération d&#8217;un playout</strong><br />
CODE: <a href="http://bitbucket.org/vfiack/weiqibot/src/c710f149ec48/src/main/java/fr/vfiack/go/generators/McAmafGenerator.java#cl-134">McAmafGenerator.playout</a></p>
<ol>
<li>on récupère la liste des intersections libres</li>
<li>tant qu&#8217;il reste des intersections libres, on en sélectionne une au hasard qu&#8217;on déplace pour ne pas la resélectionner plus tard</li>
<li>si l&#8217;intersection est valide, on la joue pour le joueur courant, sinon on recommence la sélection avec un autre coup</li>
<li>si le coup capture des pierres adverses, on récupère a nouveau la liste des intersections libres et on recommence au début, avec la position actuelle</li>
<li>lorsqu&#8217;il ne reste plus de coup valide, on passe. Après 2 passes consécutives, la simulation est terminée</li>
<li>on regarde qui gagne la partie dans la position finale, et on sauve les statistiques</li>
</ol>
<p><strong>Sauvegarde des statistiques après chaque playout</strong><br />
CODE: <a href="http://bitbucket.org/vfiack/weiqibot/src/c710f149ec48/src/main/java/fr/vfiack/go/generators/McAmafGenerator.java#cl-226">McAmafGenerator.trackStatistics</a></p>
<p>Pour chaque coup joué dans le playout par le joueur pour lequel on veut trouver un coup :</p>
<ol>
<li>vérifier qu&#8217;il n&#8217;a pas déjà été joué avant depuis la position initiale, par aucun des deux joueurs</li>
<li>s&#8217;il n&#8217;a pas encore été joué, ajoute 1 ou -1 au score du coup selon le résultat final de la partie, et incrémente le nombre de simulations contenant ce coup.</li>
</ol>
<p>L&#8217;ordre des coups n&#8217;a pas d&#8217;importance, mais on ne compte chaque coup qu&#8217;une seule fois au maximum par playout.</p>
<p><strong>Sélection du coup a jouer</strong><br />
CODE: <a href="http://bitbucket.org/vfiack/weiqibot/src/c710f149ec48/src/main/java/fr/vfiack/go/generators/McAmafGenerator.java#cl-55">McAmafGenerator.generateMove</a></p>
<ol>
<li>on remet les statistiques a zéro pour ne pas être influencé par les résultats des évaluations précédentes</li>
<li>on joue plein de playouts aléatoires</li>
<li>on récupère la liste de toutes les intersections du goban, qu&#8217;on mélange pour ne pas avoir toujours le même ordre de sélection en cas de winrates identiques</li>
<li>on récupère le winrate pour chaque intersection, si elle correspond un coup légal qui ne remplit pas un de ses propres yeux. S&#8217;il est meilleur que celui du coup actuellement sélectionné, on sélectionne le coup correspondant</li>
<li>s&#8217;il n&#8217;y a aucun coup légal restant, on passe</li>
<li>si le winrate de la position de départ est vraiment trop faible, on abandonne.</li>
</ol>
<h2>Pour aller plus loin</h2>
<p>Les programmes de ce types évoluent généralement de deux façons :</p>
<ul>
<li>en conservant l&#8217;ordre des coups dans un arbre (ex: UCT)</li>
<li>en ne faisant pas des playouts totalement aléatoires, mais plus plausibles (heavy playouts), en utilisant des heuristiques basées sur de la reconnaissance de forme.</li>
</ul>
<h2>Liens sur le sujet</h2>
<p>Sur Wikipedia :<br />
<a href="http://fr.wikipedia.org/wiki/Jeu_de_go_%28informatique%29">http://fr.wikipedia.org/wiki/Jeu_de_go_(informatique)</a></p>
<p>Le programme de référence :<br />
<a href="http://cgos.boardspace.net/public/javabot.zip">http://cgos.boardspace.net/public/javabot.zip</a></p>
<p>Un port dans le langage &#8220;Google Go&#8221; :<br />
<a href="http://github.com/skybrian/Gongo">http://github.com/skybrian/Gongo</a></p>
<p>Archives de la liste Computer-Go :<br />
<a href="http://groups.google.com/group/computer-go-archive">http://groups.google.com/group/computer-go-archive</a></p>
<p>Mon source :<br />
<a href="http://bitbucket.org/vfiack/weiqibot/">http://bitbucket.org/vfiack/weiqibot/</a></p>
<p>Pages sur Sensei&#8217;s Library :<br />
<a href="http://senseis.xmp.net/?ComputerGoAlgorithms">http://senseis.xmp.net/?ComputerGoAlgorithms</a><br />
<a href="http://senseis.xmp.net/?MonteCarlo">http://senseis.xmp.net/?MonteCarlo</a><br />
<a href="http://senseis.xmp.net/?UCT">http://senseis.xmp.net/?UCT</a></p>
<p>Un PDF sur les valeurs intéressantes :<br />
<a href="http://www.fun.ac.jp/~kishi/pdf_file/AAAI06YoshimotoH.pdf">http://www.fun.ac.jp/~kishi/pdf_file/AAAI06YoshimotoH.pdf</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vfiack.fr/93-la-methode-monte-carlo-appliquee-au-go-pour-les-nuls/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Polska after Sven Donat</title>
		<link>http://blog.vfiack.fr/82-polska-after-sven-donat/</link>
		<comments>http://blog.vfiack.fr/82-polska-after-sven-donat/#comments</comments>
		<pubDate>Sat, 13 Jun 2009 07:08:04 +0000</pubDate>
		<dc:creator>vfiack</dc:creator>
		
		<category><![CDATA[coup de coeur]]></category>

		<category><![CDATA[nyckelharpa]]></category>

		<guid isPermaLink="false">http://blog.vfiack.fr/?p=82</guid>
		<description><![CDATA[De temps en temps, on tombe sur des perles. Ici, il s&#8217;agit d&#8217;une polka jouée par Magnus Holmstr&#246;m.

Je connaissais déjà la nyckelharpa, cet instrument suédois dont le spécialiste régionnal est Jean-Claude Condi, mais je ne l&#8217;avais jamais entendue avec un son si propre. Par moments, on a du mal a croire qu&#8217;il n&#8217;y a qu&#8217;un [...]]]></description>
			<content:encoded><![CDATA[<p>De temps en temps, on tombe sur des perles. Ici, il s&#8217;agit d&#8217;une polka jouée par <a href="http://www.magnusholmstrom.com/">Magnus Holmstr&ouml;m</a>.</p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/D93OD5IYDx4&#038;hl=fr&#038;fs=1&#038;rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/D93OD5IYDx4&#038;hl=fr&#038;fs=1&#038;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>
<p>Je connaissais déjà la <a href="http://fr.wikipedia.org/wiki/Nyckelharpa">nyckelharpa</a>, cet instrument suédois dont le spécialiste régionnal est <a href="http://www.nyckelharpa-condi.com/">Jean-Claude Condi</a>, mais je ne l&#8217;avais jamais entendue avec un son si propre. Par moments, on a du mal a croire qu&#8217;il n&#8217;y a qu&#8217;un seul musicien sur scène.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vfiack.fr/82-polska-after-sven-donat/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Protégé&#160;: How not to design a license server</title>
		<link>http://blog.vfiack.fr/71-how-not-to-design-a-license-serve/</link>
		<comments>http://blog.vfiack.fr/71-how-not-to-design-a-license-serve/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 07:31:44 +0000</pubDate>
		<dc:creator>vfiack</dc:creator>
		
		<category><![CDATA[Développement]]></category>

		<category><![CDATA[citrix]]></category>

		<guid isPermaLink="false">http://blog.vfiack.fr/?p=71</guid>
		<description><![CDATA[Il n&#8217;y pas d&#8217;extrait, car cet article est protégé.]]></description>
			<content:encoded><![CDATA[<form action="http://blog.vfiack.fr/wp-pass.php" method="post">
<p>Cet article est protégé par mot de passe. Pour le lire, veuillez saisir votre mot de passe ci-dessous&nbsp;:</p>
<p><label for="pwbox-71">Mot de passe&nbsp;:<br />
<input name="post_password" id="pwbox-71" type="password" size="20" /></label><br />
<input type="submit" name="Submit" value="Envoyer" /></p></form>
]]></content:encoded>
			<wfw:commentRss>http://blog.vfiack.fr/71-how-not-to-design-a-license-serve/feed/</wfw:commentRss>
		</item>
		<item>
		<title>La note mystère</title>
		<link>http://blog.vfiack.fr/62-la-note-mystere/</link>
		<comments>http://blog.vfiack.fr/62-la-note-mystere/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 12:25:52 +0000</pubDate>
		<dc:creator>vfiack</dc:creator>
		
		<category><![CDATA[Musique]]></category>

		<guid isPermaLink="false">http://blog.vfiack.fr/?p=62</guid>
		<description><![CDATA[En ce moment, je travaille la Sarabande de la première suite de Bach pour violoncelle seul. 
C&#8217;est une œuvre pour laquelle nous n&#8217;avons pas de manuscrit autographe, mais uniquement des manuscrits de copistes (un par Anna Magdalena, sa seconde épouse, et deux autres que je n&#8217;ai jamais vu). Ces manuscrits ne sont pas forcément d&#8217;accord [...]]]></description>
			<content:encoded><![CDATA[<p>En ce moment, je travaille la Sarabande de la première <a href="http://fr.wikipedia.org/wiki/Suites_pour_violoncelle_seul_(Bach)">suite de Bach pour violoncelle seul</a>. </p>
<p>C&#8217;est une œuvre pour laquelle nous n&#8217;avons pas de manuscrit autographe, mais uniquement des manuscrits de copistes (<a href="http://imslp.org/wiki/Suites_for_Violoncello_Solo%2C_BWV_1007-1012_(Bach%2C_Johann_Sebastian)#Manuscripts">un par Anna Magdalena</a>, sa seconde épouse, et deux autres que je n&#8217;ai jamais vu). Ces manuscrits ne sont pas forcément d&#8217;accord entre eux, que ce soit sur les liaisons ou même sur les notes, et on arrive donc a des éditions modernes qui comportent des différence.</p>
<p>Pour ce qui me concerne, voici l&#8217;extrait du manuscrit d&#8217;Anna Magdalena:<br />
<img src="http://blog.vfiack.fr/wp-content/uploads/2009/02/sarabande.png" alt="Début de la sarabande de la première suite" title="Début de la sarabande de la première suite"  /></p>
<p>La dernière double croche de la ligne n&#8217;est pas très lisible. <a href="http://icking-music-archive.org/scores/bach/cello_suites/vc100712.pdf">L&#8217;édition que j&#8217;utilise</a> m&#8217;indique un la, <a href="http://www.mutopiaproject.org/cgibin/make-table.cgi?collection=bachcello&#038;preview=1">celle de mutopia</a> indique un sol.</p>
<p>Laquelle détient la vérité ?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vfiack.fr/62-la-note-mystere/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Le même avec ANTLR</title>
		<link>http://blog.vfiack.fr/50-le-meme-avec-antlr/</link>
		<comments>http://blog.vfiack.fr/50-le-meme-avec-antlr/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 08:33:49 +0000</pubDate>
		<dc:creator>vfiack</dc:creator>
		
		<category><![CDATA[Développement]]></category>

		<guid isPermaLink="false">http://blog.vfiack.fr/?p=50</guid>
		<description><![CDATA[Juste pour la forme, j&#8217;avais parsé mon document avec jparsec, voici la même chose, mais ce coup-ci avec ANTLR.
ANTLR, c&#8217;est beaucoup plus classique : une grammaire dans un langage particulier, et on génère le code du parser a partir de cette grammaire. Son gros point fort, c&#8217;est ANTLRWorks, un chouette outil d&#8217;édition et surtout de [...]]]></description>
			<content:encoded><![CDATA[<p>Juste pour la forme, j&#8217;avais <a href="http://blog.vfiack.fr/7-un-parser-tres-basique-avec-jparser/">parsé mon document avec jparsec</a>, voici la même chose, mais ce coup-ci avec <a href="http://www.antlr.org/">ANTLR</a>.</p>
<p>ANTLR, c&#8217;est beaucoup plus classique : une grammaire dans un langage particulier, et on génère le code du parser a partir de cette grammaire. Son gros point fort, c&#8217;est <a href="http://www.antlr.org/works/index.html">ANTLRWorks</a>, un chouette outil d&#8217;édition et surtout de débug de grammaires. C&#8217;est encore perfectible, surtout au niveau de l&#8217;ergonomie, mais ça remplit son office.</p>
<p>Le document à parser :</p>

<div class="wp_syntax"><div class="code"><pre class="json" style="font-family:monospace;">{abc|123|tralala}
{cde||youpie|tsoin tsoin|}</pre></div></div>

<p>Chaque ligne est une étiquette, le nombre de champs est variable, et les champs vides sont autorisés. On veut récupérer un arbre :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="antlr" style="font-family:monospace;">grammar Etiquettes;
&nbsp;
options { output=AST; }
tokens { ETIQUETTE; FIELD; }</pre></td></tr></table></div>

<p>Par convention, les tokens arbitraires sont tout en majuscules, les règles du lexer commencent par une majuscule, et les règles du parser par une minuscule. La règle principale s&#8217;appelle expr, et décrit l&#8217;ensemble du document.</p>
<p>La liste des tokens que le lexer doit repérer est assez claire :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>5
6
7
8
9
</pre></td><td class="code"><pre class="antlr" style="font-family:monospace;">Opening	:	'{';
Closing	:	'}';
Separator:	'|';
EndOfLine :	'n';
Text	:	~(Separator | Opening | Closing | EndOfLine)+;</pre></td></tr></table></div>

<p>Le texte, c&#8217;est tout ce qui n&#8217;est pas autre chose. J&#8217;imagine qu&#8217;il doit y avoir un moyen plus simple de le spécifier, mais je ne l&#8217;ai pas trouvé.</p>
<p>A partir de cet ensemble de tokens, on peut enfin construire notre document :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>10
11
12
</pre></td><td class="code"><pre class="antlr" style="font-family:monospace;">expr	:	etiquette+;
etiquette:	Opening field (Separator field)* Closing EndOfLine? -&gt; ^(ETIQUETTE field+);
field	:	Text? -&gt; ^(FIELD Text?);</pre></td></tr></table></div>

<p>On veut toujours parser une ou plusieurs étiquettes.<br />
Une étiquette est construite à partir d&#8217;une ouverture, puis d&#8217;un ensemble de champs, d&#8217;une fermeture, et optionnellement d&#8217;une fin de ligne. Ce qui suit les flèches (->), c&#8217;est ce qu&#8217;on veut remonter dans l&#8217;arbre.</p>
<p>Avec tout ça, on peut enfin lancer le débugger d&#8217;ANTLRWorks sur notre petit document, et on obtient ceci :<br />
<img src="http://blog.vfiack.fr/wp-content/uploads/2009/01/antlr-etiquettes.png" alt="Arbre généré" title="Arbre généré" width="630" height="176" class="aligncenter size-full wp-image-53" /></p>
<p>Il reste encore a récupérer l&#8217;arbre coté Java, mais <a href="http://www.antlr.org/wiki/display/ANTLR3/Interfacing+AST+with+Java">c&#8217;est assez simple</a>.</p>
<p>Si je voulais comparer avec ma version précédente utilisant jparsec, ça prends plus de code, ça demande une génération de code + parcours manuel de l&#8217;arbre, mais c&#8217;est plus clair. Je n&#8217;ai pas comparé les performances.</p>
<p>Je pense que pour des documents plus complexe, je préfèrerais utiliser ANTLR, c&#8217;est plus simple a tester.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vfiack.fr/50-le-meme-avec-antlr/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Variations sur un thème</title>
		<link>http://blog.vfiack.fr/17-variations-sur-un-theme/</link>
		<comments>http://blog.vfiack.fr/17-variations-sur-un-theme/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 14:46:02 +0000</pubDate>
		<dc:creator>vfiack</dc:creator>
		
		<category><![CDATA[Développement]]></category>

		<guid isPermaLink="false">http://blog.vfiack.fr/?p=17</guid>
		<description><![CDATA[De temps en temps, j&#8217;essaye d&#8217;écrire Monarques sous forme de jeu vidéo. Je n&#8217;en finirai sans doute jamais aucune version, mais ça m&#8217;occupe, et me permet de simplifier le jeu papier.
Un des points que j&#8217;aime bien, c&#8217;est la définition d&#8217;un château. Dans Monarques, c&#8217;est tout simplement une série de cases adjacentes, qui peuvent recruter des [...]]]></description>
			<content:encoded><![CDATA[<p>De temps en temps, j&#8217;essaye d&#8217;écrire <a href="http://monarques.vfiack.fr">Monarques</a> sous forme de jeu vidéo. Je n&#8217;en finirai sans doute jamais aucune version, mais ça m&#8217;occupe, et me permet de simplifier le jeu papier.</p>
<p>Un des points que j&#8217;aime bien, c&#8217;est la définition d&#8217;un château. Dans Monarques, c&#8217;est tout simplement une série de cases adjacentes, qui peuvent recruter des unités. Il faut pouvoir vérifier si deux cases font partie d&#8217;un même château, afin d&#8217;éviter que deux armées débutent au même endroit.</p>
<p>Les variations qui suivent sont bâties sur un principe identique :</p>
<ul>
<li>on part d&#8217;une case (x, y)</li>
<li>si c&#8217;est une case d&#8217;un château, et que le château en cours de construction ne la contient pas déjà, on l&#8217;ajoute</li>
<li>et on récurse sur les cases voisines</li>
</ul>
<p><strong>Variation impérative / objet</strong><br />
La première que j&#8217;ai écrite. Très simple, mais un peu laid, au niveau de la récursion sur les cases adjacentes. Peut mieux faire.</p>

<div class="wp_syntax"><div class="code"><pre class="java java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Castle
<span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Map</span> map;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Collection</span> elems;
&nbsp;
	<span style="color: #000000; font-weight: bold;">protected</span> Castle<span style="color: #009900;">&#40;</span><span style="color: #003399;">Map</span> map, <span style="color: #000066; font-weight: bold;">int</span> x, <span style="color: #000066; font-weight: bold;">int</span> y<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">map</span> <span style="color: #339933;">=</span> map;
		<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">elems</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ArrayList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
		MapElement elem <span style="color: #339933;">=</span> map.<span style="color: #006633;">getElementAt</span><span style="color: #009900;">&#40;</span>x, y<span style="color: #009900;">&#41;</span>;
		buildCastle<span style="color: #009900;">&#40;</span>elem<span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> buildCastle<span style="color: #009900;">&#40;</span>MapElement elem<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>elem <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span> || <span style="color: #339933;">!</span>elem.<span style="color: #006633;">canRecruitUnits</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> || elems.<span style="color: #006633;">contains</span><span style="color: #009900;">&#40;</span>elem<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
			 <span style="color: #000000; font-weight: bold;">return</span>;
&nbsp;
		elems.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>elem<span style="color: #009900;">&#41;</span>;
&nbsp;
		Coordinates coord <span style="color: #339933;">=</span> elem.<span style="color: #006633;">getCoordinates</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
		buildCastle<span style="color: #009900;">&#40;</span>map.<span style="color: #006633;">getElementAt</span><span style="color: #009900;">&#40;</span>coord.<span style="color: #006633;">getX</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span>, coord.<span style="color: #006633;">getY</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
		buildCastle<span style="color: #009900;">&#40;</span>map.<span style="color: #006633;">getElementAt</span><span style="color: #009900;">&#40;</span>coord.<span style="color: #006633;">getX</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span>, coord.<span style="color: #006633;">getY</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
		buildCastle<span style="color: #009900;">&#40;</span>map.<span style="color: #006633;">getElementAt</span><span style="color: #009900;">&#40;</span>coord.<span style="color: #006633;">getX</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span>, coord.<span style="color: #006633;">getY</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
		buildCastle<span style="color: #009900;">&#40;</span>map.<span style="color: #006633;">getElementAt</span><span style="color: #009900;">&#40;</span>coord.<span style="color: #006633;">getX</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, coord.<span style="color: #006633;">getY</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
		buildCastle<span style="color: #009900;">&#40;</span>map.<span style="color: #006633;">getElementAt</span><span style="color: #009900;">&#40;</span>coord.<span style="color: #006633;">getX</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, coord.<span style="color: #006633;">getY</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
		buildCastle<span style="color: #009900;">&#40;</span>map.<span style="color: #006633;">getElementAt</span><span style="color: #009900;">&#40;</span>coord.<span style="color: #006633;">getX</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span>, coord.<span style="color: #006633;">getY</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
		buildCastle<span style="color: #009900;">&#40;</span>map.<span style="color: #006633;">getElementAt</span><span style="color: #009900;">&#40;</span>coord.<span style="color: #006633;">getX</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span>, coord.<span style="color: #006633;">getY</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
		buildCastle<span style="color: #009900;">&#40;</span>map.<span style="color: #006633;">getElementAt</span><span style="color: #009900;">&#40;</span>coord.<span style="color: #006633;">getX</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span>, coord.<span style="color: #006633;">getY</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Variation fonctionnelle</strong><br />
J&#8217;ai gardé le type de données, les conditions d&#8217;arrêt sont identiques. La récursion est un peu plus complexe a cause du foldl, mais on a une liste de cases adjacentes plutôt que du code dupliqué, c&#8217;est toujours ça de pris.</p>

<div class="wp_syntax"><div class="code"><pre class="haskell haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">data</span> Castle <span style="color: #339933; font-weight: bold;">=</span> Castle <span style="color: green;">&#123;</span> castleCoords <span style="color: #339933; font-weight: bold;">::</span> <span style="color: green;">&#91;</span>Coords<span style="color: green;">&#93;</span> <span style="color: green;">&#125;</span>
&nbsp;
buildCastle <span style="color: #339933; font-weight: bold;">::</span> Map <span style="color: #339933; font-weight: bold;">-&gt;</span> Castle <span style="color: #339933; font-weight: bold;">-&gt;</span> Coords <span style="color: #339933; font-weight: bold;">-&gt;</span> Castle
buildCastle m c xy
  | <span style="font-weight: bold;">not</span> <span style="color: green;">&#40;</span>canRecruitUnits m xy<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> c
  | xy `<span style="font-weight: bold;">elem</span>` <span style="color: green;">&#40;</span>castleCoords c<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> c
  | <span style="font-weight: bold;">otherwise</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">foldl</span> <span style="color: green;">&#40;</span>buildCastle m<span style="color: green;">&#41;</span> c' <span style="color: green;">&#40;</span>near xy<span style="color: green;">&#41;</span>
  <span style="color: #06c; font-weight: bold;">where</span>
    c' <span style="color: #339933; font-weight: bold;">=</span> Castle <span style="color: green;">&#40;</span>xy:<span style="color: green;">&#40;</span>castleCoords c<span style="color: green;">&#41;</span><span style="color: green;">&#41;</span>
    variations x <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span>x<span style="color: #339933; font-weight: bold;">-</span><span style="color: red;">1</span><span style="color: #339933; font-weight: bold;">,</span> x<span style="color: #339933; font-weight: bold;">,</span> x<span style="color: #339933; font-weight: bold;">+</span><span style="color: red;">1</span><span style="color: green;">&#93;</span>
    near <span style="color: green;">&#40;</span>x<span style="color: #339933; font-weight: bold;">,</span> y<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#91;</span><span style="color: green;">&#40;</span>a<span style="color: #339933; font-weight: bold;">,</span> b<span style="color: green;">&#41;</span> | a <span style="color: #339933; font-weight: bold;">&lt;-</span> variations x<span style="color: #339933; font-weight: bold;">,</span> b <span style="color: #339933; font-weight: bold;">&lt;-</span> variations y<span style="color: #339933; font-weight: bold;">,</span> <span style="color: green;">&#40;</span>a<span style="color: #339933; font-weight: bold;">,</span> b<span style="color: green;">&#41;</span> `isInMap` m <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> <span style="color: green;">&#40;</span>a<span style="color: #339933; font-weight: bold;">,</span> b<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">/=</span> <span style="color: green;">&#40;</span>x<span style="color: #339933; font-weight: bold;">,</span> y<span style="color: green;">&#41;</span><span style="color: green;">&#93;</span></pre></div></div>

<p><strong>Variation simplifiée</strong><br />
La dernière en date. Finalement, je n&#8217;ai pas besoin de type de données particulier, vérifier si les deux coordonnées sont dans la liste qui constitue un château me suffit. J&#8217;ai repris l&#8217;idée de la liste des cases adjacentes (growable), mais l&#8217;itération dessus me semble plus claire que le foldl.</p>

<div class="wp_syntax"><div class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Board:
  <span style="color: #808080; font-style: italic;">#...</span>
  <span style="color: #ff7700;font-weight:bold;">def</span> buildCastle<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, x, y, accumulator<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>x, y<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">in</span> accumulator <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: black;">isCastleArea</span><span style="color: black;">&#40;</span>x, y<span style="color: black;">&#41;</span>:
      <span style="color: #ff7700;font-weight:bold;">return</span> accumulator
&nbsp;
    accumulator.<span style="color: black;">append</span><span style="color: black;">&#40;</span> <span style="color: black;">&#40;</span>x, y<span style="color: black;">&#41;</span> <span style="color: black;">&#41;</span>
    growable = <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> a <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span>x-<span style="color: #ff4500;">1</span>, x, x+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
                       <span style="color: #ff7700;font-weight:bold;">for</span> b <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span>y-<span style="color: #ff4500;">1</span>, y, y+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
                       <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">isInBoard</span><span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">in</span> accumulator<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> x, y <span style="color: #ff7700;font-weight:bold;">in</span> growable:
      <span style="color: #008000;">self</span>.<span style="color: black;">buildCastle</span><span style="color: black;">&#40;</span>x, y, accumulator<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> accumulator</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.vfiack.fr/17-variations-sur-un-theme/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Un parser très basique avec JParsec</title>
		<link>http://blog.vfiack.fr/7-un-parser-tres-basique-avec-jparsec/</link>
		<comments>http://blog.vfiack.fr/7-un-parser-tres-basique-avec-jparsec/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 21:51:16 +0000</pubDate>
		<dc:creator>vfiack</dc:creator>
		
		<category><![CDATA[Développement]]></category>

		<category><![CDATA[JParsec]]></category>

		<guid isPermaLink="false">http://blog.vfiack.fr/?p=7</guid>
		<description><![CDATA[Un exemple très simple d'utilisation de JParsec.]]></description>
			<content:encoded><![CDATA[<p>Juste pour ma mémoire, comme j&#8217;ai passé la matinée là dessus sans trouver comment renvoyer des données&#8230;</p>
<p>On a un document très simple à parser :</p>

<div class="wp_syntax"><div class="code"><pre class="json" style="font-family:monospace;">{abc|123|tralala}
{cde||youpie|tsoin tsoin|}</pre></div></div>

<p>On veut évidement récupérer des listes de chaines, sans se poser de question. Tellement simple qu&#8217;on pourrait le faire a la main. Mais voilà, moi, j&#8217;avais envie d&#8217;essayer <a href="http://jparsec.codehaus.org/">JParsec</a>, et tous les exemples sont terriblement plus compliqués (et surtout, plus orientés langages et opérations).</p>
<p>L&#8217;idée de parsec, c&#8217;est de faire des parsers directement dans le langage du programme, et de les combiner, plutôt que de rédiger une grammaire qui sera convertie (genre <a href="http://www.antlr.org/">antlr</a>). Ce qui me plait la dedans, c&#8217;est l&#8217;impression de pouvoir y aller progressivement.</p>
<p>Bref.</p>
<p>L&#8217;essentiel du boulot est dans la classe <a href="http://jparsec.codehaus.org/jparsec2/api/org/codehaus/jparsec/Scanners.html">Scanners</a>. Pensez à regarder les méthodes, et pas que les champs, c&#8217;est ce qui m&#8217;a foutu dedans ce matin (on va dire que j&#8217;étais fatigué).</p>
<p>Donc pour éviter d&#8217;avoir a préfixer tout ce qu&#8217;on va appeler :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="java java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">codehaus</span>.<span style="color: #006633;">jparsec</span>.<span style="color: #006633;">Scanners</span>.*;</pre></td></tr></table></div>

<p>Et on combine. Commençons par ce qu&#8217;on veut récupérer, c&#8217;est a dire les caractères entre les pipes :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="java java" style="font-family:monospace;">Parser<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;</span> content <span style="color: #339933;">=</span> notAmong<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;|}&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">many</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">source</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>La méthode source(), c&#8217;est l&#8217;astuce pour récupérer le texte qui matche. Je ne comprends pas pourquoi ces parseurs ne renvoient pas la chaine directement.</p>
<p>Une fois qu&#8217;on a cette chaine, on peut récupérer une liste, puis la ligne complète :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>2
3
</pre></td><td class="code"><pre class="java java" style="font-family:monospace;">Parser<span style="color: #339933;">&lt;</span>List<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;&gt;</span> enclosed <span style="color: #339933;">=</span> content.<span style="color: #006633;">sepBy</span><span style="color: #009900;">&#40;</span>isChar<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'|'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
Parser<span style="color: #339933;">&lt;</span>List<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;&gt;</span> line <span style="color: #339933;">=</span> enclosed.<span style="color: #006633;">between</span><span style="color: #009900;">&#40;</span>isChar<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'{'</span><span style="color: #009900;">&#41;</span>, isChar<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'}'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>Il ne nous reste plus qu&#8217;a boucler sur les lignes :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>4
5
6
</pre></td><td class="code"><pre class="java java" style="font-family:monospace;">Parser<span style="color: #339933;">&lt;</span>Void<span style="color: #339933;">&gt;</span> eof <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Parser<span style="color: #339933;">&lt;</span>Void<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span>Parsers.<span style="color: #006633;">EOF</span>; 
Parser<span style="color: #339933;">&lt;</span>Void<span style="color: #339933;">&gt;</span> endOfLine <span style="color: #339933;">=</span> among<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;rn&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">or</span><span style="color: #009900;">&#40;</span>eof<span style="color: #009900;">&#41;</span>;
Parser<span style="color: #339933;">&lt;</span>List<span style="color: #339933;">&lt;</span>List<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;&gt;&gt;</span> lines <span style="color: #339933;">=</span> line.<span style="color: #006633;">endBy</span><span style="color: #009900;">&#40;</span>endOfLine<span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>Et voilà, on y est :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>7
</pre></td><td class="code"><pre class="java java" style="font-family:monospace;"><span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>lines.<span style="color: #006633;">parse</span><span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>=> <code>[[abc, 123, tralala], [cde, , youpie, tsoin tsoin, ]]</code></p>
<p>Résultat des opérations : 6 lignes de code pour récupérer des données structurées.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vfiack.fr/7-un-parser-tres-basique-avec-jparsec/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>

