Syntactic Confectionery Delight PerlMonks

### Re^2: Self-constructing Japh

by golux (Hermit)
 on Nov 13, 2016 at 01:29 UTC ( #1175799=note: print w/replies, xml ) Need Help??

in reply to Re: Self-constructing Japh

Sure, I'll try my best. :)

Here's what I did originally:

```

\$| = 1;                 # Don't buffer output
print "\e[H\e[J\n";     # Clear the screen

\$S='|';
japh('82>2  ^7    22>5');                           # 'J'
japh('88^4  59>4  48/^2  812^6 29>2  />1');         # 'A'
japh('815^4 515>4 415/^3 419^2 216>2 />1');         # 'P'
japh('822^4 522>4 422/^3 825^7');                   # 'H

exit;

#
#  This subroutine prints each letter of the word "JAPH"
#  It writes the words bottom-up, since going top-down
#  overwrites part of the letters that ultimately have to
#  be hidden by the sides.
#
sub japh {
my \$s = pop;
\$s =~ s/\s//g;
while(\$s) {
\$s =~ s/^(\d)(\d+)// and (\$y,\$x) = (\$1,\$2);
\$s =~ s|^/|| and \$S = \$&;
\$s =~ s/^([>^])(\d)// and map { block(\$1) } (1..\$2);
}
}

#
#  This subroutine draws a single block, based on
#  the current values of the (\$X, \$Y) coordinates.
#
sub block {
\$s = "___ /  /|/__/ ||  | \$S|__|/";
\$S = '|';
(\$X, \$Y, \$Z) = (3*\$x, 2*\$y, 0);
while (\$b = substr(\$s,0,\$Z+++4,"")) {
print "\e[".\$Y++.";\$X"."H\$b";
\$Z>2? \$Z=2: --\$X;
}
select\$d,\$e,\$f,.1;

\$_[0] eq '^'? \$y--: \$x++;
}

__END__

Commands:  *YX   go to coordinates (Y,X)
/     set symbol \$S to '/' (normally '|')
>N    move/draw N pixels (right)
^N    move/draw N pixels (up)

81>2^721>5
88^4811^75
'815^4515>4515/^3216>3');               # 'P'
822^4 522>4 422/^3 825^7

It's got some notes at the end, and I've added more comments to it just now, but it's essentially the same functionality as the final obfuscation with slightly differently formatted letters (the "H" got wider in the final version), and there wasn't any color added yet.

Note that the reason it's drawn bottom-up is because to-down would obscure parts of the characters that have to be in "front", but would be overwritten by the sides that themselves need to be obscured. The easiest way to achieve this was to cheat and do it bottom-up.

In contrast, here's the obfuscated version which has been fairly de-obfuscated:

```eval(
q{
\$| = print"\e[2J\n";
\$k = '|';
s,,2220;3500731;3522735071;1600715074;1622713,;
y;0-4;8|_/%;;
s;5;\e[103m;g;
s,6,\e[102m,g;
s;7;\e[m;g;
\$/ = \$_;
\$_ = q|hb2Gbb5hhDei4dh0BhlFbi201hoC4do0CdsBbp201hvDev5dv0ChzG|
+;
s;[1-9];>\$&;g;
s;[A-I];^\$&;g;
y|A-I|1-9|;

{
s;^(\w)(\w);; ?
(\$y = -97 + ord \$1, \$x = -97 + ord \$2):
s,^0,, ?
\$k = '/':
s,^([>^])(\d),, ?
map {
\$c = \$1;
\$X = 1 + 3 * \$x;
\$Y = \$y * 2;
\$Z = 4;
\$" = \$/ =~ s;%;\$k;r;
map { print "\e[\${\\$Y++};\${X}H\$_"; \$X-- if
+ ++\$Z < 7 } split ';', \$";
\$k = '|';
select \$J,\$a,\$p,\$ARGV[0] || .1;
'^' eq \$c? \$y--: \$x++
} 1..\$2:
last;
redo
}
} =~ y/8 \n/ /dr
);

die "\e[22H\n"      # ANSI Escape sequence -- jumps to line 22

There's a lot of standard "tricks" going on here, like using special variables in place of regular ones (such as \$/ and \$", and assigning \$| to the print command, which simply turns off buffered output. And using \$_ lets me do regex substitutions without the =~ operator, to keep the code size down.

The redo command jumps back to reenter the large { ... } block, also with a minimum of chars. And chaining four ternary operators (...) ? (...) : (...) together makes it even harder to read.

Anywhere you see \e[NNNm, you know it's doing something with Ansi colors -- 103 is yellow, 102 is green, and \e[m turns the color off.

The sequence         s,,2220;3500731;3522735071;1600715074;1622713,; constructs an encoded value into \$_ "out of thin air". Then if you add some debugging:

```        \$_ = q|hb2Gbb5hhDei4dh0BhlFbi201hoC4do0CdsBbp201hvDev5dv0ChzG|
+;
print "Debug:  \$_\n";
s;[1-9];>\$&;g;
print "Debug:  \$_\n";
s;[A-I];^\$&;g;
print "Debug:  \$_\n";
y|A-I|1-9|;
print "Debug:  \$_\n";
you can see how the encoded string is converted back a set of commands:
```Debug:  hb2Gbb5hhDei4dh0BhlFbi201hoC4do0CdsBbp201hvDev5dv0ChzG
Debug:  hb>2Gbb>5hhDei>4dh0BhlFbi>20>1hoC>4do0CdsBbp>20>1hvDev>5dv0Chz
+G
Debug:  hb>2^Gbb>5hh^Dei>4dh0^Bhl^Fbi>20>1ho^C>4do0^Cds^Bbp>20>1hv^Dev
+>5dv0^Chz^G
Debug:  hb>2^7bb>5hh^4ei>4dh0^2hl^6bi>20>1ho^3>4do0^3ds^2bp>20>1hv^4ev
+>5dv0^3hz^7

which still need to get parsed, but are a lot closer to the original sequence in the original program.

If you have any further questions don't hesitate to ask. And thanks for your interest! :D

say  substr+lc crypt(qw \$i3 SI\$),4,5

Create A New User
Node Status?
node history
Node Type: note [id://1175799]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (2)
As of 2017-12-13 00:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
What programming language do you hate the most?

Results (342 votes). Check out past polls.

Notices?