#!/usr/bin/perl -w use strict; # # Renumber, rotate, and otherwise modify a Sudoku board # Print the result on stdout # my $board_name = ""; my $renumber_string; my $rotate; my @board = (); my $debug = 0; # **************************************************************** # Process arguments while ($_ = shift) { my $arg = $_; if ($arg =~ /^-debug/) { $debug = 1; } elsif ($arg eq "-board") { $board_name = shift; } elsif ($arg eq "-sequence") { $renumber_string = shift; } elsif ($arg eq "-rotate" || $arg eq "-rotate_right" || $arg eq "-right") { $rotate = 1; } elsif ($arg eq "-rotate_left" || $arg eq "-left") { $rotate = -1; } elsif ($arg =~ /^[1-9]/) { $renumber_string = $arg; } else { $board_name = $arg; } } # **************************************************************** # Read the board open BD, "<$board_name" or die "Can't open input board $board_name"; my $line_no = 1; my @vals = (); while () { my $line = $_; if ($debug) { print "Read board line '${line}'\n"; } if ($line !~ /^\s*([0-9-])\s*([0-9-])\s*([0-9-])\s*([0-9-])\s*([0-9-])\s*([0-9-])\s*([0-9-])\s*([0-9-])\s*([0-9-])/) { next; } if ($debug) { print "Matched line; read values $1,$2,$3,$4,$5,$6,$7,$8,$9\n"; } push @vals, $1,$2,$3,$4,$5,$6,$7,$8,$9; $line_no++; if ($line_no > 9) { last; } } if (scalar(@vals) < 81) { my $vc = scalar(@vals); die "Didn't find enough values: found $vc\n"; } # Check to see if we're supposed to do something ... anything. if (!defined($renumber_string) && !defined($rotate)) { die "No action requested\n"; } if (defined($renumber_string)) { # Clean up the renumber string, in case it's got any extra stuff in it $renumber_string =~ s/[ ,]//g; if ($debug) { print "Renumber string: '$renumber_string'\n"; } if (length($renumber_string) != 9) { die "Renumber string must contain exactly 9 digits\n"; } # Translate the values my @renumber_list = split (//, $renumber_string); foreach my $i (0..$#renumber_list) { # Count the instances of everything on the list my $list_char = $renumber_list[$i]; if ($debug) { print "Checking character '$list_char' from the renumber list\n"; } if (! ($list_char =~ /[1-9]/)) { die "Character $list_char on the renumber list is not a digit between 1 and 9\n"; } my $ct = 0; foreach my $j (0..$#renumber_list) { my $d = $renumber_list[$j]; if ($list_char eq $d) { $ct++; } } if ($ct != 1) { die "Character '$list_char' appears $ct times on the renumber list\n"; } } my @to_list = split (//, "123456789"); my @trans_vals = (); foreach my $i (0..$#vals) { my $char = $vals[$i]; foreach my $j (0..$#renumber_list) { my $from = $renumber_list[$j]; if ($char eq $from) { if ($debug) { print " Mapping $from --> $to_list[$j]\n"; } $char = $to_list[$j]; last; } } push @trans_vals, $char; } @vals = @trans_vals; } # Should we rotate it? if (defined($rotate)) { my @rot_vals = (); foreach my $i (0..8) { foreach my $j (0..8) { my ($to_i, $to_j); if ($rotate > 0) { $to_i = $j; $to_j = 8 - $i; } else { $to_i = 8 - $j; $to_j = $i; } my $from_index = ($i * 9) + $j; my $to_index = ($to_i * 9) + $to_j; $rot_vals[$to_index] = $vals[$from_index]; } } @vals = @rot_vals; } # Print the new version of the board my $row = 0; foreach my $i (0..$#vals) { my $v = $vals[$i]; if ($v eq '0') { $v = "-"; } print "$v"; if (($i+1) % 9) { # Not at the end of a line? print " "; if ((($i + 1) % 3) == 0) { # At the end of a box? If so throw an extra space print " "; } } else { # At the end of a line? print "\n"; $row++; if ($i < 80 && !($row % 3)) { # Put an extra newline after each row of boxes print "\n"; } } }