{"id":583,"date":"2011-05-05T01:33:16","date_gmt":"2011-05-05T00:33:16","guid":{"rendered":"http:\/\/julia2.lucaamore.com\/?p=583"},"modified":"2025-11-29T20:23:47","modified_gmt":"2025-11-29T18:23:47","slug":"cammelli-labirinti-e-depth-first-search-realizzazione-di-un-generatore-e-risolutore-di-labirinti-in-perl","status":"publish","type":"post","link":"https:\/\/www.lucaamore.com\/?p=583","title":{"rendered":"Cammelli labirinti e depth-first search: realizzazione di un generatore e risolutore di labirinti in Perl"},"content":{"rendered":"\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2023\/01\/lukelv_airview_of_a_very_intricated_maze_with_a_shape_of_a_face_9ee29fac-f51e-41d9-8904-6c40ee8dd26f.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" data-id=\"1614\" src=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2023\/01\/lukelv_airview_of_a_very_intricated_maze_with_a_shape_of_a_face_9ee29fac-f51e-41d9-8904-6c40ee8dd26f-1024x1024.png\" alt=\"\" class=\"wp-image-1614\" srcset=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2023\/01\/lukelv_airview_of_a_very_intricated_maze_with_a_shape_of_a_face_9ee29fac-f51e-41d9-8904-6c40ee8dd26f-1024x1024.png 1024w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2023\/01\/lukelv_airview_of_a_very_intricated_maze_with_a_shape_of_a_face_9ee29fac-f51e-41d9-8904-6c40ee8dd26f-300x300.png 300w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2023\/01\/lukelv_airview_of_a_very_intricated_maze_with_a_shape_of_a_face_9ee29fac-f51e-41d9-8904-6c40ee8dd26f-150x150.png 150w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2023\/01\/lukelv_airview_of_a_very_intricated_maze_with_a_shape_of_a_face_9ee29fac-f51e-41d9-8904-6c40ee8dd26f-768x768.png 768w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2023\/01\/lukelv_airview_of_a_very_intricated_maze_with_a_shape_of_a_face_9ee29fac-f51e-41d9-8904-6c40ee8dd26f-1536x1536.png 1536w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2023\/01\/lukelv_airview_of_a_very_intricated_maze_with_a_shape_of_a_face_9ee29fac-f51e-41d9-8904-6c40ee8dd26f.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Se <a title=\"T\u00e9seo\" href=\"http:\/\/it.wikipedia.org\/wiki\/Teseo\">T\u00e9seo<\/a> (\u0398\u03b7\u03c3\u03b5\u03cd\u03c2), eroe spregiudicato nonch\u00e8 figlio del re ateniese <a title=\"Egeo\" href=\"http:\/\/it.wikipedia.org\/wiki\/Egeo\">\u00c8geo<\/a> (\u0391\u1f30\u03b3\u03b5\u03cd\u03c2), avesse conosciuto qualche rudimento di Perl, avrebbe potuto risolvere brillantemente il problema del <a title=\"Labirinto di Cnosso\" href=\"http:\/\/it.wikipedia.org\/wiki\/Labirinto_di_Cnosso\">Labirinto di Cnosso<\/a> adottando l&#8217;algoritmo <a href=\"http:\/\/en.wikipedia.org\/wiki\/Depth-first_search\">deep-first search<\/a>, sconfiggere il <a title=\"Minotauro\" href=\"http:\/\/it.wikipedia.org\/wiki\/Minotauro\">Minotauro<\/a> (\u039c\u03b9\u03bd\u03ce\u03c4\u03b1\u03c5\u03c1\u03bf\u03c2) Asterione ma &#8211; soprattutto &#8211; non avrebbe spezzato il cuore della povera <a title=\"Arianna\" href=\"http:\/\/it.wikipedia.org\/wiki\/Arianna_%28mitologia%29\">Arianna<\/a> (\u0391\u03c1\u03b9\u03ac\u03b4\u03bd\u03b7), figlia di Minosse e Pasifae (ed anche madre del Minotauro), seducendola per ottenere il risolutivo gomitolo di filo rosso (un surrogato di stack analogico ideato da <a title=\"Dedalo\" href=\"http:\/\/it.wikipedia.org\/wiki\/Dedalo\">Dedalo<\/a> ) per poi abbandonarla ancora dormiente nell&#8217;isola deserta di <a title=\"Nasso\" href=\"http:\/\/it.wikipedia.org\/wiki\/Nasso\">Nasso<\/a> (pare pure dopo una lunga notte di &#8220;festeggiamenti&#8221; nella sua nave).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze20x20.png\"><img loading=\"lazy\" decoding=\"async\" width=\"200\" height=\"200\" src=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze20x20.png\" alt=\"\" class=\"wp-image-612\" srcset=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze20x20.png 200w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze20x20-150x150.png 150w\" sizes=\"auto, (max-width: 200px) 100vw, 200px\" \/><\/a><figcaption class=\"wp-element-caption\">labirinto 20 x 20 generato da maze.pl<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">A chi mi obietta &#8211; ingiustamente &#8211; che ai tempi non era disponibile un interprete Perl cos\u00ec come un notebook agevolmente trasportabile in un Labirinto, ma anche a tutti gli altri che gridano vendetta contro il comportamento di T\u00e9seo nei confronti della povera Arianna, consiglio vivamente la lettura dell&#8217;avvincente <a title=\"Minotauro\" href=\"http:\/\/it.wikipedia.org\/wiki\/Minotauro\">leggenda del Minotauro<\/a>; scoprirete che la storia di T\u00e9seo, per opera di Poseidone, si conclude in modo tragico a causa dell&#8217;inversione di un&#8217;informazione booleana (1 bit) ma vitale: il colore delle vele della sua imbarcazione.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dopo questa mitologica premessa, certo di esser perdonato per eventuali errori sulla mitologia greca, sperando di non deludere il forse unico temerario lettore che avr\u00e0 avuto l&#8217;ardore di proseguire nella lettura di questo articolo, vi presento un semplicissimo<strong> generatore e risolutore di labirinti scritto interamente in Perl<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze60x40.png\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"400\" src=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze60x40.png\" alt=\"\" class=\"wp-image-620\" srcset=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze60x40.png 600w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze60x40-300x200.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/a><figcaption class=\"wp-element-caption\">Labirinto 60 x 40 generato da maze.pl<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Questo progetto \u00e8 ispirato da <a title=\"Maze in Python\" href=\"http:\/\/mornie.org\/blog\/2007\/08\/02\/generating-maze-using-python\/\">un articolo<\/a> che ho letto nel blog di Eriol in cui il problema viene affrontato in Python.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In rete esistono anche molti riferimenti sui labirinti (storia, classificazione, generazione, risoluzione, miti e leggende) dove \u00e8 piacevole perdersi:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a title=\"Maze Generation\" href=\"http:\/\/en.wikipedia.org\/wiki\/Maze_generation\">Maze Generation<\/a><\/li>\n\n\n\n<li><a title=\"Think Labyrinth: Maze algorithms\" href=\"http:\/\/www.astrolog.org\/labyrnth\/algrithm.htm\" rel=\"nofollow\">Think Labyrinth: Maze algorithms<\/a><\/li>\n\n\n\n<li><a title=\"Maze Solving Algorithm\" href=\"http:\/\/en.wikipedia.org\/wiki\/Maze_solving_algorithm\">Maze Solving Algorithm<\/a><\/li>\n\n\n\n<li><a title=\"Maze\" href=\"http:\/\/en.wikipedia.org\/wiki\/Maze\">Maze<\/a><\/li>\n\n\n\n<li><a title=\"Mazework - how to build a maze\" href=\"http:\/\/web.archive.org\/web\/20150716070736\/http:\/\/www.mazeworks.com:80\/mazegen\/mazetut\/\">Mazework &#8211; How to build a Maze<\/a> citato nell&#8217;articolo<\/li>\n\n\n\n<li><a title=\"Labirinto\" href=\"http:\/\/it.wikipedia.org\/wiki\/Labirinto\">Labirinto<\/a><\/li>\n\n\n\n<li><a title=\"Labirinti e matematica\" href=\"https:\/\/web.archive.org\/web\/20210420073125\/https:\/\/areeweb.polito.it\/didattica\/polymath\/htmlS\/probegio\/GAMEMATH\/Labirinti\/Matematica%20e%20labirinti.htm\" rel=\"nofollow\">labirinti e matematica<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Nella mia implementazione, esaltando alcune caratteristiche tipiche del Perl, ho progettato delle strutture dati leggere ed efficienti (memorizzo solo le aperture del labirinto) ed ho adottato la versione dell&#8217;algoritmo <a title=\"depth-first search\" href=\"http:\/\/en.wikipedia.org\/wiki\/Depth-first_search\">depth-first search<\/a> ricorsiva sia per la costruzione del labirinto (metodo <em>Maze::asterione)<\/em> che per la ricerca del percorso che conduce dall&#8217;ingresso all&#8217;uscita (metodo&nbsp;<em>Maze::teseo<\/em>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sono disponibili:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">l&#8217;output del labirinto generato e risolto in modalit\u00e0 ASCII (<em>Maze::toText<\/em>):<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2021\/10\/Schermata-2021-10-17-alle-17.48.35.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"904\" src=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2021\/10\/Schermata-2021-10-17-alle-17.48.35-1024x904.png\" alt=\"\" class=\"wp-image-1351\" srcset=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2021\/10\/Schermata-2021-10-17-alle-17.48.35-1024x904.png 1024w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2021\/10\/Schermata-2021-10-17-alle-17.48.35-300x265.png 300w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2021\/10\/Schermata-2021-10-17-alle-17.48.35-768x678.png 768w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2021\/10\/Schermata-2021-10-17-alle-17.48.35.png 1308w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">l&#8217;output in formato PNG(<em>Maze::toImage<\/em>):<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x100.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1000\" height=\"500\" src=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x100.png\" alt=\"\" class=\"wp-image-614\" srcset=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x100.png 1000w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x100-300x150.png 300w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/a><figcaption class=\"wp-element-caption\">labirinto 200 x 100 generato da maze.pl<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Per la generazione dell&#8217;immagine si richiedono le librerie GD.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Il tutto sarebbe ottimizzabile e migliorabile ma al momento sono gi\u00e0 abbastanza soddisfatto dei risultati ottenuti!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x200.avif\"><img loading=\"lazy\" decoding=\"async\" width=\"1000\" height=\"1000\" src=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x200.avif\" alt=\"\" class=\"wp-image-2589\" srcset=\"https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x200.avif 1000w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x200-300x300.avif 300w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x200-150x150.avif 150w, https:\/\/www.lucaamore.com\/wp-content\/uploads\/2011\/05\/maze200x200-768x768.avif 768w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><a title=\"repository maze (github)\" href=\"https:\/\/github.com\/lookee\/maze\">Potete scaricare i sorgenti di maze.pl nel repository del progetto su github<\/a> (software libero rilasciato sotto licenza GNU\/GPL v. 3)<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: perl; gutter: false; title: ; notranslate\" title=\"\">\n#!\/usr\/bin\/perl\n\nuse strict;\nuse warnings;\n\npackage Maze;\n\nuse Carp qw(croak verbose);\nuse GD;\n\nsub new {\n    my ($class, $x, $y) = @_; \n\n    my $self = { \n        x =&gt; $x, \n        y =&gt; $y,\n        doors =&gt; &#x5B;], \n        solution =&gt; &#x5B;],\n    };\n\n    bless $self;\n    $self-&gt;openWall(0, 0, &#039;N&#039;);\n    $self-&gt;openWall($x - 1, $y - 1, &#039;S&#039;);\n\n    return $self;\n}\n\nsub _getWallIndex($$$){\n    my ($self, $x, $y, $dir) = @_;\n\n    my @idx =\n        $dir eq &#039;N&#039; ? ($x,      $y,     &#039;N&#039;) :\n        $dir eq &#039;S&#039; ? ($x,      $y + 1, &#039;N&#039;) :\n        $dir eq &#039;W&#039; ? ($x,      $y,     &#039;E&#039;) :\n        $dir eq &#039;E&#039; ? ($x + 1,  $y,     &#039;E&#039;) :\n            croak &quot;wrong direction&quot;;\n\n    return @idx;\n}\n\nsub isWallOpen($$$){\n    my ($self, $x, $y, $dir) = @_;\n\n    my ($wx, $wy, $wdir) = $self-&gt;_getWallIndex($x, $y, $dir);    \n\n    return $self-&gt;{door}&#x5B;$wx]&#x5B;$wy]{$wdir} || 0;\n}\n\nsub openWall($$$) {\n    my ($self, $x, $y, $dir) = @_;\n\n    my ($wx, $wy, $wdir) = $self-&gt;_getWallIndex($x, $y, $dir);    \n\n    $self-&gt;{door}&#x5B;$wx]&#x5B;$wy]{$wdir} = 1;\n}\n\nsub getCellNeighbors($$$){\n    my ($self, $x, $y) = @_;\n    grep {\n        $_-&gt;&#x5B;0] &gt;= 0 and $_-&gt;&#x5B;0] &amp;lt; $self-&gt;{x} and\n        $_-&gt;&#x5B;1] &gt;= 0 and $_-&gt;&#x5B;1] &amp;lt; $self-&gt;{y}\n    } (\n        &#x5B;$x - 1, $y    , &#039;W&#039;],\n        &#x5B;$x + 1, $y    , &#039;E&#039;],\n        &#x5B;$x    , $y - 1, &#039;N&#039;],\n        &#x5B;$x    , $y + 1, &#039;S&#039;]\n    );\n}\n\nsub getCellOpenedNeighbors($$$){\n    my ($self, $x, $y) = @_;\n    grep { \n        my (undef, undef, $dir) = @$_;\n        $self-&gt;isWallOpen($x, $y, $dir)\n    } $self-&gt;getCellNeighbors($x, $y);\n}\n\nsub isCellExit($$$){\n    my ($self, $x, $y) = @_;\n    return \n        ($x == $self-&gt;{x} -1 ) &amp;amp;&amp;amp; ($y == $self-&gt;{y} -1 );\n} \n\nsub markSolution($$$){\n    my ($self, $x, $y) = @_;\n    $self-&gt;{solution}&#x5B;$x]&#x5B;$y] = 1;\n}\n\nsub isSolution($$$){\n    my ($self, $x, $y) = @_;\n    $self-&gt;{solution}&#x5B;$x]&#x5B;$y];\n}\n\n# generate maze\nsub asterione($$$$){\n    no warnings &#039;recursion&#039;;\n    my ($self, $x, $y, $visited) = @_;\n    $visited-&gt;&#x5B;$x]&#x5B;$y] = 1;\n    return if $self-&gt;isCellExit($x,$y);\n    my @neighbors = $self-&gt;getCellNeighbors($x, $y);\n    while (scalar @neighbors){\n        my ($tox, $toy, $dir) = \n            @{ splice(@neighbors, rand(@neighbors), 1) };\n        next if $visited-&gt;&#x5B;$tox]&#x5B;$toy];\n        $self-&gt;openWall($x, $y, $dir);\n        $self-&gt;asterione($tox, $toy, $visited);\n    }\n}\n\n# solve maze\nsub teseo($$$$){\n    no warnings &#039;recursion&#039;;\n    my ($self, $x, $y, $visited) = @_;\n    $visited-&gt;&#x5B;$x]&#x5B;$y] = 1;\n    if ($self-&gt;isCellExit($x, $y)){\n        $self-&gt;markSolution($x, $y);\n        return 1;\n    }\n    my @neighbors = $self-&gt;getCellOpenedNeighbors($x, $y);\n    while (scalar @neighbors){\n        my ($tox, $toy, $dir) = \n            @{ splice(@neighbors, rand(@neighbors), 1) };\n        next if $visited-&gt;&#x5B;$tox]&#x5B;$toy];\n        my $isSolution = $self-&gt;teseo($tox, $toy, $visited);\n        if ($isSolution){\n            $self-&gt;markSolution($x, $y);\n            return 1;\n        }\n    }\n    return 0;\n}\n\nsub toText(){\n\n    my $self = shift;\n\n    my ($x, $y, @l1, @l2);\n    my $out = &#039;&#039;;\n    for ($y = 0; $y &amp;lt; $self-&gt;{y}; $y++){\n        @l1 = @l2 = ();\n        for ($x = 0; $x &amp;lt; $self-&gt;{x}; $x++){\n            my $solution = $self-&gt;isSolution($x, $y) ? &#039;.&#039; : &#039; &#039;;\n            push(@l1, $self-&gt;isWallOpen($x, $y, &#039;N&#039;) ? $solution x 2 : &#039;-&#039; x 2);\n            push(@l2, $self-&gt;isWallOpen($x, $y, &#039;W&#039;) ? &#039; &#039; : &#039;|&#039;);\n            push(@l2, $solution x 2);\n        }\n        push(@l2, $self-&gt;isWallOpen($x, $y, &#039;E&#039;) ? &#039; &#039; : &#039;|&#039;);\n        $out .= \n            &#039;+&#039; . join(&#039;+&#039;,@l1) . &#039;+&#039; . &quot;\\n&quot; . \n            join(&#039;&#039;,@l2) . &quot;\\n&quot;;\n    }\n\n    @l1 = ();\n    for ($x = 0; $x &amp;lt; $self-&gt;{x}; $x++){\n        my $solution = $self-&gt;{solution}&#x5B;$x]&#x5B;$self-&gt;{y} -1] ? &#039;.&#039; : &#039; &#039;;\n        push(@l1, \n            $self-&gt;isWallOpen($x, $self-&gt;{y} -1, &#039;S&#039;) ? \n                $solution x 2 : &#039;-&#039; x 2\n        );\n    }\n\n    $out .= &#039;+&#039; . join(&#039;+&#039;, @l1) . &#039;+&#039; . &quot;\\n&quot;;\n\n    print $out;\n}\n\nsub toImage($$){\n\n    my ($self, $FILENAME) = @_;\n\n    my ($WX, $WY) = (10, 10);\n\n    my ($SIZEX, $SIZEY) = ($self-&gt;{x} * $WX, $self-&gt;{y} * $WY);\n\n    my $img = new GD::Image-&gt;newTrueColor($SIZEX,$SIZEY)\n        or croak &quot;Can&#039;t create GD::Image&quot;;\n \n    my $cl_white = $img-&gt;colorAllocate(255,255,255);\n    my $cl_black = $img-&gt;colorAllocate(  0,  0,  0);\n    my $cl_red   = $img-&gt;colorAllocate(255,  0,  0);\n    \n    $img-&gt;fill( 0, 0, $cl_white);\n\n    open(my $fh, &#039;&gt;&#039;, $FILENAME)\n        or croak &quot;Can&#039;t open $FILENAME: $!&quot;;\n\n    binmode $fh;\n\n    my ($xx, $yy);\n\n    YY: for ($yy = 0; $yy &amp;lt; $self-&gt;{y}; $yy++){\n\n        XX: for ($xx = 0; $xx &amp;lt; $self-&gt;{x}; $xx++){\n\n            $img-&gt;filledRectangle(\n                $xx * $WX, $yy * $WY, ($xx + 1) * $WX, ($yy + 1) * $WY, \n                $cl_red\n            )\n                if $self-&gt;isSolution($xx, $yy);\n            \n            $img-&gt;line(\n                    $xx * $WX, $yy * $WY, ($xx + 1) * $WX, $yy * $WY, \n                    $cl_black\n            )\n                unless $self-&gt;isWallOpen($xx, $yy, &#039;N&#039;);\n\n            $img-&gt;line(\n                    $xx * $WX, $yy * $WY, $xx * $WX, ($yy + 1) * $WY, \n                    $cl_black\n            )\n                unless $self-&gt;isWallOpen($xx, $yy, &#039;W&#039;);\n        }\n\n        $img-&gt;line(\n            $xx * $WX - 1, $yy * $WY, $xx * $WX -1, ($yy + 1) * $WY, \n            $cl_black\n        )\n            unless $self-&gt;isWallOpen($xx - 1, $yy, &#039;E&#039;);\n    }\n\n    for ($xx = 0; $xx &amp;lt; $self-&gt;{x}; $xx++){\n        $img-&gt;line(\n            $xx * $WX, $yy * $WY - 1, ($xx + 1) * $WX, $yy * $WY - 1, \n            $cl_black\n    )\n                unless $self-&gt;isWallOpen($xx, $yy - 1, &#039;S&#039;);\n    }\n\n    print $fh $img-&gt;png(0);\n    close $fh;\n}\n\npackage main;\n\n# init\nmy $m = Maze-&gt;new(60,40);\n\n# generate paths\n$m-&gt;asterione(0,0,&#x5B;]);\n\n# solve maze\n$m-&gt;teseo(0,0,&#x5B;]);\n\n# generate PNG\n$m-&gt;toImage(&#039;out.png&#039;);\n\n# print ASCII\n#$m-&gt;toText();\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"<p>Se T\u00e9seo (\u0398\u03b7\u03c3\u03b5\u03cd\u03c2), eroe spregiudicato nonch\u00e8 figlio del re ateniese \u00c8geo (\u0391\u1f30\u03b3\u03b5\u03cd\u03c2), avesse conosciuto qualche rudimento di Perl, avrebbe potuto risolvere brillantemente il problema del Labirinto di Cnosso adottando l&#8217;algoritmo deep-first search, sconfiggere il Minotauro (\u039c\u03b9\u03bd\u03ce\u03c4\u03b1\u03c5\u03c1\u03bf\u03c2) Asterione ma &#8211; soprattutto &hellip; <a href=\"https:\/\/www.lucaamore.com\/?p=583\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":1576,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_sitemap_exclude":false,"_sitemap_priority":"","_sitemap_frequency":"","footnotes":""},"categories":[16,35,32,26,37,36,12,166,165],"tags":[81,80,71],"class_list":["post-583","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-deepth-first-search","category-freesoftware","category-gd","category-labirinto","category-maze","category-perl","category-programming","category-top","tag-algorithms","tag-maze","tag-perl"],"_links":{"self":[{"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=\/wp\/v2\/posts\/583","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=583"}],"version-history":[{"count":84,"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=\/wp\/v2\/posts\/583\/revisions"}],"predecessor-version":[{"id":2614,"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=\/wp\/v2\/posts\/583\/revisions\/2614"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=\/wp\/v2\/media\/1576"}],"wp:attachment":[{"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=583"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=583"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lucaamore.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=583"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}