This is actually a rather straightforward JAPH. The two biggest features of it is the splitting of the data string that makes up most of the "image", and the semi-recursive printing.
This is the code I get when I clean up the formatting
my ($j,$a,$p,$h);
$j = sub {
print( chr( $p += $a->[$h++] ) );
$j
};
;;
$a = [0, split "[: \n]+", # the split regex
q/43 -002:1 # input string start: q/ ...
-084 065:13
0001 000005
-0012 -00003
000013 -82 00048
21:13:-6.00:-76:72
-007.:02:00008.00
:::-6.00:::013
-70:3::-70:.64
/]; # input string end: .../
# print Dumper $a; # <--- this is my line
$p = 0x4a;;
$h=0;
$j->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->()->();
The first part is the declaration and assignment of the 4 main variables:
$j
$j
is a code reference that prints a character, then returns a reference to itself. The print consists of a few steps:
$a->[$h++]
iterates over the @$a
array, returning one element
$p += ...
that element is added to $p
print chr( $p ... )
then $p
is returned to chr() and the resulting character is printed.
Last in the sub block is $j
, which means each iteration, the return value of the sub will be a reference to itself. This is the part that allows for the semi-recursive feature.
$a
$a
is a reference to an array that consists of 0 and the result of a split on the input string. Here also a few things are happening in one line of code:
q/43 .../
this is a regular q()
single quoted string with the delimiter slash /
. It ends right before the closing bracket ]
that denotes the array reference.
split "[: \n]+",
this is a split on a character class, repeated 1 or more times. There are extra spaces inside it (which I have removed here) to fill out the space in the JAPH itself. Basically this removes all colon, space and newline and returns the resulting list.
$a = [0, ... ]
the list of the split is added to a list of 0
(just one element) and everything is surrounded with brackets to denote an array reference, which is then stored in $a
.
I assume the list starts with 0
because the code has a one-off error, in that $p
's original value is the first letter in the output.
This is the Data::Dumper
output of $a
:
$VAR1 = [
0,
'43',
'-002',
'1',
'-084',
'065',
'13',
'0001',
'000005',
'-0012',
'-00003',
'000013',
'-82',
'00048',
'21',
'13',
'-6.00',
'-76',
'72',
'-007.',
'02',
'00008.00',
'-6.00',
'013',
'-70',
'3',
'-70',
'.64'
];
$p and $h
$p
and $h
are only numbers, and their role in this is source number for the chr()
function and iterator for the @$a
array, respectively.
The last line is the part where the $j
subroutine is run and the JAPH is printed. The chained ->()
syntax means that the return value of each previous iteration is used for the next execution. And $j
returns a reference to itself, which makes it a semi-recursive affair, only the values change.
I guess it is similar to doing this:
$x = $j->();
$y = $x->();
$z = $y->();
...
So lets walk through the first few steps
$j->()
the execution
$a->[$h++]
$h
is incremented to 1, returns 0 to the $a
substript, which returns the first element of $a
, which is 0
.
$p += 0
This 0
is added to $p
, and this returns the value of $p
(74) to chr
print chr(74)
this now prints a J
to standard output
$j
is returned.
->()
another execution is performed on the return value, so $j
is run again.
$a->[$h++]
$h
is incremented to 2, returns 1 to $a
which returns the second element which is 43
.
$p += 43
74 + 43 = 117 is returned to chr
print chr(117)
this prints u
The elements of $a
are both positive and negative, moving the number where it needs to be. In the end, all the letters printed form: Just another Perl hacker,
Here's a rundown on the 10 first executions:
p => 74 += 0 = 74 output => chr( 74) J
p => 74 += 43 = 117 output => chr(117) u
p => 117 += -002 = 115 output => chr(115) s
p => 115 += 1 = 116 output => chr(116) t
p => 116 += -084 = 32 output => chr( 32)
p => 32 += 065 = 97 output => chr( 97) a
p => 97 += 13 = 110 output => chr(110) n
p => 110 += 0001 = 111 output => chr(111) o
p => 111 += 000005 = 116 output => chr(116) t
p => 116 += -0012 = 104 output => chr(104) h