SOLUTION file

"tpj", by Keith Winstein
         <keithw@imsa.edu>

This submission is not really a "lie", in the sense that it does exactly what
it says it does.

There is only one statement in the main flow:

	print ocr(<<TPJ);
	 #  # # ## ##  ## ##  #    #  #  # # ##  #  #  #  #
	### # # #  # # #  # # #    # # # # # # # ## # # # #
	 #  ### ## ##  ## ##  #    # # # # # ##  # ## ### #
	 #  # # #  #   #  # # #  # # # # # # # # #  # # # #
	 #  # # ## #   ## # # ## ###  #  ### # # #  # # # ##
	TPJ

The real meat of the program, then, is in the "ocr" subroutine, which
actually does implement a simple optical character recognition engine based
on an algorithm described by Kurzweil. It first splits apart the ASCII
art into letters by looking for columns of whitespace, putting each
letter separately into the @| array. It then sends "sensors" in from
each column and row, counting the number of "transitions" in each
direction (black to white and white to black). The letters are then
matched against pre-calculated data.

The original implementation was relatively adaptive, trying to
recognize letters in various sizes and weights, but in the pursuit of
a higher goal (obfuscation) much of the adaptivity was removed.

Here is the original pre-obfuscated implementation:

#!/usr/bin/perl -w

@h[65..90] = qw(2 1.4 1 1.6 0.4 0.6 1.4 1.6 1.2 1.8 2.2 0.8 2.4 
                2.4 2 1.2 1.8 2 1.6 1.6 2 2.8 2.4 2.8 2.4 1.2);
@v[65..90] = qw(1.8 2.7 2 1.3 3.2 2.4 2.8 1.2 1.6 1.8 2 0.8 1.3
                1.2 2 1.7 2.8 2 3.2 0.8 1 1.4 1.3 2.8 1.4 2.4);

sub ocr ($) {
  @lines = split "\n", $_[0];
  $height = scalar @lines;
  $width = length ((sort { length $b <=> length $a } @lines)[0]);
  
  $row = 0;
  for (@lines) {
    @{$element[$row++]} = split '', ($_ . " " x ($width - length($_)));
  }

  for $row (0 .. ($height - 1)) {
    for $col (0 .. ($width - 1)) {
      $blank{ $col }++ if ($element[$row][$col] eq ' ');
    }
  }
  @bound = (-1);
  for (sort { $a <=> $b } keys %blank) {
    push @bound, $_ if ($blank{ $_ } == $height);
  }
  push @bound, $width;
  
  for $lnum (0 .. ($#bound - 1)) {
    for $row (0 .. ($height - 1)) {
      @{$letter[$lnum][$row]} = @{$element[$row]}[($bound[$lnum] + 1) ..
                                                  ($bound[$lnum + 1] - 1)];
    }
  }

  for (@letter) {
    *me = $_;
    ($height, $width) = (scalar @me, scalar @{$me[0]});
    ($htrans, $vtrans) = (0,0);
    
    for $row (0 .. ($height - 1)) {
      $currstate = $me[$row][0];
      for $col (1 .. ($width - 1)) {
        $htrans++ if ($me[$row][$col] ne $currstate);
        $currstate = $me[$row][$col];
      }
    }
    
    $htrans /= $height;
    
    for $col (0 .. ($width - 1)) {
      $currstate = $me[0][$col];
      for $row (1 .. ($height - 1)) {
        $vtrans++ if ($me[$row][$col] ne $currstate);
        $currstate = $me[$row][$col];
      }
    }

    $vtrans /= $width;

    push @l, chr ((sort { ($v[$a] - $vtrans)**2 + ($h[$a] - $htrans)**2 <=>
                            ($v[$b] - $vtrans)**2 + ($h[$b] - $htrans)**2 }
                   (65 .. 90))[0]);
  }

  return join "", @l;
}

$hello = <<HELLO;
#   # ##### #     #      ##
#   # #     #     #     #  #
##### ##### #     #     #  #
#   # #     #     #     #  #
#   # ##### ##### #####  ##
HELLO

print ucfirst lc ocr $hello, ".\n";
