From Newsgroup: rec.puzzles
"Carl G." <
carlgnews@microprizes.com> posted:
An OCR Puzzle.
I once wrote software that would try to "clean up" OCR text based on something I knew about the data (e.g., the characters were supposed to
be coordinates).
Here is a "5!mPI_E" puzzle based on writing such a program. Assume that
the text below is a message that was written by hand using only the
digits 0 to 9 and spaces. The original message was encrypted into 7-bit ASCII numbers separated by spaces (e.g., "99 97 116" represents "cat").
The message was then scanned using OCR. Unfortunately, the OCR had trouble distinguishing between similar characters (e.g., reading "Q"
instead of "0", or "g" instead of "9") and sometimes missed or added
spaces. Your challenge is to write a short computer program that
reveals the original message (i.e., figures out the ASCII numbers, then turns the ASCII into text). The OCR text is between quotes:
"6G I O132 |1 $ [I7i1#10I 3z li6![ ]32i0o 1i4 !OSl1Oio~/ 32 1Zl 1lI
!i7 [ ]H32 ~/9|18 gT i0& 1 16 lO5 i]o IQ]"
If your code works out the message, DON'T POST THE MESSAGE, just post
your code that converts the OCR text into the solution. This will help prevent "spoilers". Extra points for using a more-esoteric computer language (INTERCAL, LISP, FORTH, etc.), a very short program (e.g., a one-liner or grep expression), or something that looks inexplicable.
The following C# program decodes this message:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConvertToAscii
{
class ConvertToAscii
{
static private List<string> characters =
new List<string> { "OQo", "Iil!|[]", "Zz", "", "H#", "S$", "G", "T~", "&", "g" };
static void Main(string[] args)
{
if (args.Length == 1)
{
ConvertText(args[0]);
}
else
{
Console.WriteLine("Usage: ConvertToAscii <Text string with ASCII codes>");
}
}
static private void ConvertText(string text)
{
int number = 0;
StringBuilder ascii = new StringBuilder();
for (int n = 0; n < text.Length; n++)
{
char letter = text[n];
if (letter == ' ')
{
if (number >= 32)
{
ascii.Append((char)number);
number = 0;
}
}
else
{
int digit;
if (letter < '0' || letter > '9')
{
digit = DigitFromLetter(letter.ToString());
}
else
{
digit = letter - '0';
}
if (digit >= 0)
{
number = 10 * number + digit;
}
if (number >= 32)
{
ascii.Append((char)number);
number = 0;
}
}
}
Console.WriteLine(ascii);
}
static private int DigitFromLetter(string letter)
{
for (int n = 0; n < characters.Count; n++)
{
if (characters[n].Contains(letter))
{
return n;
}
}
return -1;
}
}
}
--- Synchronet 3.21a-Linux NewsLink 1.2