saltycracker

Sudoku4x4.pl

Oct 30th, 2020 (edited)
303
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 4.13 KB | None | 0 0
  1. #! /usr/bin/env perl
  2.  
  3. use warnings;
  4. use strict;
  5. use utf8;
  6. use feature qw<say>;
  7. use boolean;
  8. use List::Util qw<any uniq>;
  9.  
  10. my @cells;
  11.  
  12. my %posToElem = (
  13.   11 => 0,
  14.   12 => 1,
  15.   13 => 2,
  16.   14 => 3,
  17.   21 => 4,
  18.   22 => 5,
  19.   23 => 6,
  20.   24 => 7,
  21.   31 => 8,
  22.   32 => 9,
  23.   33 => 10,
  24.   34 => 11,
  25.   41 => 12,
  26.   42 => 13,
  27.   43 => 14,
  28.   44 => 15
  29. );
  30.  
  31. my @sudokuPos = (
  32.   [11, [12, 13, 14, 21, 22, 31, 41]],
  33.   [12, [11, 13, 14, 21, 22, 32, 42]],
  34.   [13, [11, 12, 14, 23, 24, 33, 43]],
  35.   [14, [11, 12, 13, 23, 24, 34, 44]],
  36.   [21, [22, 23, 24, 11, 12, 31, 41]],
  37.   [22, [21, 23, 24, 11, 12, 32, 42]],
  38.   [23, [21, 22, 24, 13, 14, 33, 43]],
  39.   [24, [21, 22, 23, 13, 14, 34, 44]],
  40.   [31, [32, 33, 34, 41, 42, 11, 21]],
  41.   [32, [31, 33, 34, 41, 42, 12, 22]],
  42.   [33, [31, 32, 34, 43, 44, 13, 23]],
  43.   [34, [31, 32, 33, 43, 44, 14, 24]],
  44.   [41, [42, 43, 44, 31, 32, 11, 21]],
  45.   [42, [41, 43, 44, 31, 32, 12, 22]],
  46.   [43, [41, 42, 44, 33, 34, 13, 23]],
  47.   [44, [41, 42, 43, 33, 34, 14, 24]]
  48. );
  49.  
  50. sub getSudokuCells {
  51.   my $sudokuStr;
  52.  
  53.   {
  54.     local $/ = undef;
  55.     chop($sudokuStr = <DATA>);
  56.   }
  57.  
  58.   map {int($_)} (split(//, $sudokuStr));
  59. }
  60.  
  61. sub fixedCell {
  62.   my ($num) = @_;
  63.   $num == 0 ? false : true;
  64. }
  65.  
  66. sub calValidSet {
  67.   my($cells, $edges) = @_;
  68.   my @ans;
  69.   for my $elem (@$cells) {
  70.     if (any{$_ == $elem} (@$edges)) {
  71.       push(@ans, $elem);
  72.     }
  73.   }
  74.   \@ans;
  75. }
  76.  
  77. sub buildSudokuStructure {
  78.   my ($r_cells, $p_to_e) = @_;
  79.   my @ans;
  80.   while (my ($index, $elem) = each (@$r_cells)) {
  81.     my @edges;
  82.     for my $e (@{$sudokuPos[$index]->[1]}) {
  83.       push(@edges, \$r_cells->[$p_to_e->{$e}]);
  84.     }
  85.     push(
  86.       @ans,
  87.       {
  88.         fixed => fixedCell($elem),
  89.         elem => $elem,
  90.         pos => $sudokuPos[$index]->[0],
  91.         edges => \@edges
  92.         });
  93.   }
  94.   \@ans;
  95. }
  96.  
  97. sub startingNumbers {
  98.   my ($edges) = @_;
  99.   my @nums;
  100.   my @ans;
  101.   for my $n (@$edges) {#ref to cell value
  102.     push(@nums, $$n) if $$n;
  103.   }
  104.   @nums = uniq @nums;
  105.   for my $elem (1..4) {
  106.     push(@ans, $elem) unless any {$elem == $_} @nums;
  107.   }
  108.   \@ans;
  109. }
  110.  
  111. sub generateStartingNums {
  112.   my ($sudoku) = @_;
  113.   for my $elem (@$sudoku) {
  114.     if ($elem->{fixed}) {
  115.       $elem->{startingNums} = [];
  116.     }else {
  117.       $elem->{startingNums} = startingNumbers($elem->{edges});
  118.     }
  119.   }
  120. }
  121.  
  122. sub validateTry {
  123.   my ($edges, $value) = @_;
  124.   for my $elem (@$edges) {
  125.     return false if ($$elem == $value);
  126.   }
  127.   true;
  128. }
  129.  
  130. sub solveSudoku {
  131.   my ($sudoku) = @_;  
  132.   if ($sudoku->[0]->{fixed}) {
  133.     solveSudokuAux($sudoku, 1);
  134.   }else {
  135.     for my $elem (@{$sudoku->[0]->{startingNums}}) {
  136.       if (validateTry($sudoku->[0]->{edges}, $elem)) {
  137.         my $old_value = $cells[0];
  138.         @cells[0] = $elem;
  139.         solveSudokuAux($sudoku, 1);
  140.         @cells[0] = $old_value;
  141.       }
  142.     }
  143.   }
  144.  
  145.   say "The solving is all done";
  146. }
  147.  
  148. sub solveSudokuAux {
  149.   my ($sudoku, $pos) = @_;
  150.   if ($pos < 16) {
  151.     if ($sudoku->[$pos]->{fixed}) {
  152.       solveSudokuAux($sudoku, ++$pos);
  153.     }else {
  154.       for my $elem (@{$sudoku->[$pos]->{startingNums}}) {
  155.         if (validateTry($sudoku->[$pos]->{edges}, $elem)) {
  156.           my $old_value = $cells[$pos];
  157.           my $old_pos = $pos;
  158.           @cells[$pos] = $elem;
  159.           solveSudokuAux($sudoku, ++$pos);
  160.           @cells[$old_pos] = $old_value;
  161.           $pos = $old_pos;
  162.         }
  163.       }
  164.     }
  165.   }else {
  166.     my $g_counter = 0;
  167.     my $l_counter = 0;
  168.     my $s_counter = 0;
  169.     for my $elem (@cells) {
  170.       ++$g_counter;
  171.       ++$l_counter;
  172.       ++$s_counter;
  173.       print $elem, " ";
  174.       if ($g_counter > 1) {
  175.         print " ";
  176.         $g_counter = 0;
  177.       }
  178.       if ($l_counter > 3) {
  179.         print "\n";
  180.         $l_counter = 0;
  181.       }
  182.       if ($s_counter > 7) {
  183.         print "\n";
  184.         $s_counter = 0;
  185.       }
  186.     }
  187.   }
  188. }
  189.  
  190. @cells = getSudokuCells();
  191.  
  192. my $sudokuStr = buildSudokuStructure(\@cells, \%posToElem);
  193.  
  194. generateStartingNums($sudokuStr);
  195.  
  196. solveSudoku($sudokuStr);
  197.  
  198. exit(0);
  199. #0340400210030210
  200. #0000430000420000-
  201. #0010400000020300
  202. #2000003004000001-
  203. #1040000000000102
  204. __DATA__
  205. 0010400000000000
Add Comment
Please, Sign In to add comment