SOLUTION
--------

... to my submission to the category Most Powerful (1)
in the 3rd Annual Obfuscated Perl Contest.

Geoff Simmons
<gs@cityline.net>
-----------------

This program takes as input any string that Perl can convert into a
double, and prints as output a representation of that number using one
of the standard prefixes such as 'Kilo', 'Mega', 'milli', or 'micro'.

For inputs whose absolute values lie between 10**-18 and 10**18, it
returns a number whose absolute value lies between 1 and 1000 and one
of the following prefixes:

  10**3 : Kilo     10**-3 : milli
  10**6 : Mega     10**-6 : micro
  10**9 : Giga     10**-9 : nano
  10**12: Tera     10**-12: pico
  10**15: Peta     10**-15: femto
  10**18: Exa      10**-18: atto

For inputs whose absolute values lie between 1 and 1000, the prefix is
the empty string (this is true if the input is 0 as well). For numbers
out of range (absolute values greater/less than 10**+-18), the prefix
for the largest or smallest order of magnitude is chosen (i.e. 'Exa'
or 'atto'), and the numeric component of the result may be greater
than 1000 or less than one. Finally, inputs that Perl cannot convert
into a double are returned unchanged. Hence we have the following:

	INPUT				OUTPUT
	-----				------
	123123				123.123 Kilo
	0.0000000234			23.4 nano
	-347628734.45345345		-347.628734453453 Mega
	-0.000000000340234032		-340.234032 pico
	0				0
	734.93847			734.93847
	324.2344e7			3.242344 Giga
	123e-12				123 pico
	-1.123e-14			-11.23 femto
	4876487236872368723762837623	4876487236.87237 Exa
	0.000000000000000000000234234	0.000234234 atto
	foobar				foobar
	123123foobar			123.123 Kilo


HOW IT WORKS
------------
Here's the program with line numbers, better layout and the 'use'
statement in the usual place:

1:	#! /usr/bin/perl -pl
2:	use POSIX (strtod,floor);
3:	next unless strtod($_);
4:	$n = $_;
5:	while(<DATA>) {
6:		chomp;
7:		($. & 1 ? @b : @a) = split / /, pack "H*", $_;
8:	}
9:	$b ||= unpack "n", shift @b;
10:	$a = abs $n;
11:	$f = floor(log($a)/log($b));
12:	$l = $f > $#a ? $#a : -$f > $#b ? -$#b : $f;
13:	$_ = join ' ', $n/$b**$l, $a > 1 ? $b[$l] : $a[-$l];
14:	__END__
15:	03e820204b696c6f204d65676120476967612054657261205065746120457861
16:	206d696c6c69206d6963726f206e616e6f207069636f2066656d746f206174746f

Line 3 rejects input that cannot be converted into a double, and also
rejects 0, since strtod() returns 0 for such inputs. Rejected input is
left in $_, so that the -p switch causes it to be printed. If the
input is not rejected, then line 4 saves it in $n.

The while loop in lines 5-8 reads from the DATA filehandle, which
contains the prefixes as packed hex strings, and stores them in the
arrays @b and @a, so that:

    @b = ('', 'Kilo',  'Mega',  'Giga', 'Tera', 'Peta',  'Exa')
    @a = ('', 'milli', 'micro', 'nano', 'pico', 'femto', 'atto')
    
... except that @b initially has a packed string representing the
number 1000 as its first element, which is assigned to $b in line 9.
Note that the while loop and the assignment in line 9 are only
executed the first time through the program, since after that the DATA
filehandle is at end-of-file and $b has a true value.

Lines 10 and 11 compute the index into the prefix arrays by dividing
the log of the input's absolute value by log(1000), and rounding the
result towards negative infinity using floor(). Note that this result
is negative for inputs whose absolute values are less than one. The
result is assigned to $f.

Line 12 takes care of the out-of-range situation by assigning $f to $l
unless $f is out of range, i.e. if its absolute value is greater than
the highest index in @a or @b. In that case, $l is set to the highest
index.

Line 13 then computes the numeric component of the final result as the
input divided by 1000 raised to the power $l. The prefix is chosen
from the appropriate array @a or @b (depending on whether the absolute
value of the input was greater or less than one), and the whole thing
is assigned to $_, so that the -p switch causes it to be printed. And
then we start over.
