pastebin light

pastebin is a collaborative debugging tool allowing you to share and modify code snippets while chatting on IRC, IM or a message board.

pastebin light //misacek

Posted by 8puzzle on Sun 30 Oct 2011 22:40:13 CET
download | new post

  1. #!/usr/bin/perl -w
  2. package EightPuzzle;
  3. use strict;
  4. use warnings;
  5.  
  6. my $gamesize = 9;
  7. my @x;
  8. my @y;
  9. my @goal = (1,2,3,8,0,4,7,6,5);
  10. my @game;
  11. my @game_bak;
  12. my $MAX_MOVES = 50000;
  13.  
  14. main();
  15.  
  16. sub main {
  17. create_grid();
  18. my @res;
  19. my $bad_sum = 0;
  20. my $manh_sum = 0;
  21.  
  22. my $bad_moves = 0;
  23. my $manh_moves = 0;
  24.  
  25. for(my $i= 1; $i < 6; $i++) {
  26. print "=== $i. zadani ===\n";
  27. create_game();
  28. backup_game();
  29.  
  30. @res = @{solve(\&fitness_h1)};
  31. $bad_moves += $res[0];
  32. $bad_sum += $res[1];
  33. print_bad(@res);
  34.  
  35. restore_game();
  36.  
  37. @res = @{solve(\&fitness_h2)};
  38. $manh_moves += $res[0];
  39. $manh_sum += $res[1];
  40. print_manh(@res);
  41.  
  42. clear_game();
  43. }
  44.  
  45. print "\nCelkem spatne umistenych kostek: $bad_sum v $bad_moves tazich.\n";
  46. print "Celkova suma manhattanskych vzdalenosti: $manh_sum v $manh_moves tazich.\n";
  47.  
  48. }
  49.  
  50. sub print_bad {
  51. print "\nPocet spatne umistenych je ".$_[1]." s poctem kroku ".$_[0].".\n"
  52. }
  53.  
  54. sub print_manh {
  55. print "\nSuma manhattanskych vzdalenosti je ".$_[1]." s poctem kroku ".$_[0].".\n";
  56. }
  57.  
  58. sub backup_game {
  59. @game_bak = @game;
  60. }
  61.  
  62. sub restore_game {
  63. @game = @game_bak;
  64. }
  65.  
  66. sub clear_game {
  67. @game = ();
  68. @game_bak = ();
  69. }
  70.  
  71. sub solve {
  72. my $fitness_sub = shift;
  73. my $i = 0;
  74. print ">>> VSTUP <<<\n";
  75. print_game();
  76.  
  77. print "(probiha vypocet, prosim cekejte)\n";
  78.  
  79. while(++$i < $MAX_MOVES && &$fitness_sub > 0) {
  80. move($fitness_sub);
  81. }
  82.  
  83. print "\n<<< VYSTUP >>>\n";
  84. print_game();
  85.  
  86. # return statistic information
  87. my @ret = ($i, &$fitness_sub);
  88. return \@ret;
  89.  
  90. }
  91.  
  92. sub create_grid {
  93. my $gss = sqrt $gamesize;
  94. my $k = 0;
  95. for(my $i=0; $i < $gss; $i++) {
  96. for(my $j=0; $j < $gss; $j++) {
  97. $x[$k] = $i;
  98. $y[$k] = $j;
  99. $k++;
  100. }
  101. }
  102. }
  103.  
  104. sub print_game {
  105. my $gss = sqrt $gamesize;
  106. for(my $i = 0; $i < $gss; $i++) {
  107. for(my $j = 0; $j < $gss; $j++) {
  108. print $game[$gss*$i+$j];
  109. }
  110. print "\n";
  111. }
  112. }
  113.  
  114. sub create_game {
  115. for(my $i=0;$i<$gamesize-1;$i++) {
  116. my $num = int(rand($gamesize-1))+1;
  117. while(grep /$num/, @game) {
  118. $num = int(rand($gamesize-1))+1;
  119. }
  120. push @game, $num;
  121. }
  122.  
  123. @game[3..8] = @game[2..7];
  124. $game[2] = 0;
  125. }
  126.  
  127. sub fitness_h1 {
  128. my $right_count = 0;
  129. my $goal_count = scalar @goal;
  130. for(my $i = 0; $i < $goal_count; $i++) {
  131. if($game[$i] eq $goal[$i]) {
  132. ++$right_count;
  133. }
  134. }
  135. return ($goal_count - $right_count);
  136. }
  137.  
  138. sub fitness_h2 {
  139. my $total = 0;
  140. my $goal_count = scalar @goal;
  141.  
  142. for(my $i=0;$i < $goal_count;$i++) {
  143. my $goal_index;
  144. for(my $j=0; $j < $goal_count; $j++) {
  145. if($goal[$j] eq $game[$i]) {
  146. $goal_index = $j;
  147. $j = $goal_count;
  148. }
  149. }
  150. $total += (abs ($x[$i] - $x[$goal_index]) + abs($y[$i] - $y[$goal_index]));
  151. }
  152. return $total;
  153. }
  154.  
  155.  
  156. sub move {
  157. my $fitness_sub = shift;
  158.  
  159. my @pm = @{possible_moves()};
  160. my @pm_bak = @pm;
  161. my @equal_fitness;
  162.  
  163. my $zero_idx = undef;
  164. for(my $i = 0; $i < scalar @game; $i++) {
  165. $zero_idx = $i if $game[$i] eq 0;
  166. }
  167.  
  168. my $bak_fitness = &$fitness_sub;
  169. my @bak = @game;
  170.  
  171. my $best_move = $pm[0];
  172. my $curr_fitness = 5000;
  173.  
  174. while(my $idx = shift @pm) {
  175. @game = @bak;
  176. $game[$zero_idx] = $game[$idx];
  177. $game[$idx] = 0;
  178.  
  179. my $new_fitness = &$fitness_sub;
  180.  
  181. my @f = ($idx, $new_fitness);
  182. push @equal_fitness, \@f;
  183.  
  184. if($new_fitness < $curr_fitness) {
  185. $curr_fitness = $new_fitness;
  186. $best_move = $idx;
  187. }
  188. }
  189.  
  190. @game = @bak;
  191.  
  192. $game[$zero_idx] = $game[$best_move];
  193. $game[$best_move] = 0;
  194. }
  195.  
  196. sub possible_moves {
  197. my $zero_idx;
  198. my $pos;
  199. my @ret;
  200.  
  201. for(my $i = 0; $i < scalar @game; $i++) {
  202. if($game[$i] eq 0) {
  203. $zero_idx = $i;
  204. $i = scalar @game; # break-command emulation
  205. }
  206. }
  207. my $zero_x = $x[$zero_idx];
  208. my $zero_y = $y[$zero_idx];
  209.  
  210. $pos = get_index($zero_x-1, $zero_y);
  211. push @ret, $pos if defined $pos;
  212. $pos = get_index($zero_x+1, $zero_y);
  213. push @ret, $pos if defined $pos;
  214. $pos = get_index($zero_x, $zero_y-1);
  215. push @ret, $pos if defined $pos;
  216. $pos = get_index($zero_x, $zero_y+1);
  217. push @ret, $pos if defined $pos;
  218.  
  219. @ret = sort { int(rand(3)-1) } @ret;
  220.  
  221. return \@ret;
  222. }
  223.  
  224. sub get_index {
  225. my $xpos = shift;
  226. my $ypos = shift;
  227.  
  228. if($xpos > (sqrt $gamesize - 1) || $ypos > (sqrt $gamesize - 1) || $xpos < 0 || $ypos < 0) {
  229. }
  230.  
  231. return ((sqrt $gamesize)*$xpos + $ypos);
  232. }

Syntax highlighting: