
sub layout_crossword { 
my (@input, @output, $rows, $cols); 

$rows = @_; 

# Convert puzzle array into array of arrays; 
# die if puzzle rows are different lengths 
for(@_) { 
  $cols ||= length; 
  die "Uneven row lengths\n" unless length == $cols; 
  push @input, [ split //, $_ ]; 
} 

# Glyphs w/ different sizes really mess things up... 

# Check height 
my $sqHeight = @empty_square; 
@full_square != $sqHeight and die "Glyphs not the same height\n"; 

# Check width 
my $sqWidth; 
for(@empty_square, @full_square) { 
  $sqWidth ||= length; 
  length != $sqWidth and die "Glyphs not consistent width\n"; 
} 

# For each puzzle row, do not output the bottom line of 
# each square because it's the same as the top line of the 
# square below. We'll add an extra line at the end. 

$sqHeight--; 

# Figure length of that part of an empty-glyph string  
# which will be replaced by spaces and/or numbers 
# (ie. all but first & last positions) 

$sqWidth = $sqWidth - 2; 

# Does a given empty square need a number? 
# Returns true if yes; false if no; 
# Square gets number if either: 
# 1) Square above is full or out-of-bounds 
#      AND square below is in-bounds and empty 
# 2) Square to left is full or out-of-bounds 
#      AND square to right is in-bounds and empty 

my $needsNumber = sub { 
  my ($r, $c) = @_; 
  ((((($r-1) < 0) or ($input[$r-1][$c] eq 'X')) 
     and ((($r+1) < $rows) and ($input[$r+1][$c] ne 'X'))) 
  or 
  (((($c-1) < 0) or ($input[$r][$c-1] eq 'X')) 
     and ((($c+1) < $cols) and ($input[$r][$c+1] ne 'X')))); 
}; 

# Iterate over each matrix row and for each string of output 
# for this row (ie. each line of the square glyphs), look 
# to see if the current column is full or empty. If full, 
# concatenate the current string from the appropriate glyph 
# to the output line. If empty and if it's the 2nd line of 
# the glyph, decide if it needs a number. Then use substr 
# to insert number and/or spaces in the current line of the 
# appropriate glyph. Die if the number is too long. 
# Concatenate updated string to output line. If it's the 
# glyph's 1st line add it to output line; if it's any other 
# line of the glyph, remove non-space chars from internal 
# positions. Each time we concatenate a glyph string to the 
# output line add a "\b" character to backtrack over 
# common/shared lines of adjacent squares. 
# Finally, push output line onto output list whenever 
# we reach the bottom of a glyph or the bottom of the matrix. 

my $cnt; 
foreach my $row (0.. $#input) { 
  foreach my $lineCntr (0.. $sqHeight) { 
    my $line = ''; 
    foreach my $col (0.. $cols-1) { 
      my $str = $empty_square[$lineCntr]; 
      if($input[$row][$col] eq 'X') { 
        $line .= "$full_square[$lineCntr]\b"; 
      } elsif($lineCntr == 1) { 
        if($needsNumber->($row, $col)) { 
          (length ++$cnt > $sqWidth) 
          and (die "Number $cnt longer than square width\n"); 
          substr($str, 1, -1) = sprintf "%-${sqWidth}s", $cnt; 
        } else { 
          substr($str, 1, -1) = sprintf "%-${sqWidth}s", ' '; 
        } 
        $line .= "$str\b"; 
      } elsif(($lineCntr == 0) or ($lineCntr == $sqHeight)) { 
        $line .= "$empty_square[$lineCntr]\b"; 
      } else { 
        substr($str, 1, -1) = sprintf "%-${sqWidth}s", ' '; 
        $line .= "$str\b"; 
      } 
    } 
    push @output, "$line\n" 
      if(($lineCntr != $sqHeight) or ($row == $#input)); 
  } 
} 
chomp @output;
return @output; 
} 
####################################################################



