Perl 5 -M5.010
+ A Pear Tree, score 0, tiebreak score 96 bytes
$_='{length==86&&6&&say$T0+=++$b9F;redo}{print$tYC+=++$nKy;redo}#{print$tYC+=++$nKy;redo}#';eval
Try it online! (Perl)
Try it online! (A Pear Tree)
A Pear Tree was designed for polyglot challenges and radiation-hardening challenges. I think, however, this is the first time I've used it on a challenge that falls into both categories.
This was annoyingly time-consuming to verify – my normal radiation-hardening verifier programs don't handle infinite loops well, and yet an infinite loop is shorter to write than a "loop up to input" is in Perl, so I ended up having to check all the irradiated programs manually.
The -M5.010
argument to Perl is a version selection argument that's basically standard in golfing at this point (and used to be allowed without penalty even back when we penalised for command-line arguments) – I would add it out of habit even if it didn't do anything (although it's required here).
Explanation
Perl
Most of the program is stored in a string, $_
, which is immediately evaluated:
$_='…';eval
$_='…' initialize variable $_
eval evaluate {$_} as a program
($_
is chosen as the variable because it's the default variable that most commands use when an operand is missing, so this helps out the tiebreak score a little.)
The program itself does the following:
{length==86&&6&&say$T0+=++$b9F;redo}{…}#…
{ ;redo} infinite loop
say print
$T0 the value of $T0
+= after adding
$b9F the value of $b9F to it
++ after adding 1 to that
&& but only if
length the length {of $_}
==86 is 86
&& and
6 6 is truthy
{…} unreachable code
#… comment
The actual calculation of the triangular numbers is very simple (although confusing because there are two assignments inside the expression) – $T0
holds the triangular number itself, and $b9F
its index, and we repeatedly add 1 to $b9F
and then add $b9F
to $T0
in order to produce the sequence of triangular numbers. Perl variables are initialised with undef
, which acts like 0 when you increment it or add numbers to it. (The variable names don't matter to the Perl program, and are as weird as they are due to how A Pear Tree works.)
The unreachable code – part of the A Pear Tree program – is syntactically valid, but never runs because there's an infinite loop immediately before it.
The length==86
check is used to ensure that none of the irradiated versions of the program print the triangular numbers in Perl. Deleting most things outside the long string literal, or its delimiters, produces a syntax error. Deleting characters from eval
is not a syntax error, but the resulting program does nothing when run, because the string is never evaluated. Some deletions inside the string produce syntax errors; these are caught by eval
(thus no error message is printed), but prevent the string being evaluated. For other deletions inside the string, the length==86
check will prevent anything actually being printed (it will either be intact, or be corrupted into something falsey), so the code still doesn't output the triangular numbers.
The check for 6 being truthy is mostly irrelevant – it was added purely so that I could have two &&
s in there, thus preventing the scenario in which a lone &&
(short-circuiting AND) gets irradiated into &
(bitwise AND) and causes the say
statement to run uncondtionally. (With the two &&
s, if either of them gets corrupted into &
, the other still prevents the say
statement running because its left-hand side will be falsey.)
A Pear Tree
To write an A Pear Tree program, you need to decide which substrings of the program are going to be checked for corruption by the interpreter – the interpreter will rotate the largest such part to the start before running the program (and error out if there is no such portion). The substrings in question are marked implicitly by changing irrelevant internal details of them in such a way that their CRC32 is 0.
In this program, there are three such sections with a CRC32 of 0 – the entire program, and the two {print$tYC+=++$nKy;redo}#
substrings.
In a non-irradiated run of the program, the largest section is the program itself, so it runs unrotated, and is has effectively identical control flow to the Perl. However, say
is not a keyword in A Pear Tree (the "print with newline" builtin is called print
there, in one of its very minor differences from Perl), so the program hits an error when it tries to execute say
(which is caught by the eval
and the program exits naturally). It would be possible to exploit other differences between the languages (e.g. $\
is falsey in Perl but truthy in A Pear Tree), but using the existence/nonexistence of say
is terser.
If you delete any character from the program, the program as a whole will no longer have a CRC32 of 0, so one of the {print$tYC+=++$nKy;redo}#
substrings (whichever one didn't get irradiated, or the first one if they're both intact) is rotated to the start, followed by the rest of the program. However, the #
at the end of the substring comments the rest of the program out, so we just end up with a small loop that calculates triangular numbers. This is identical to the triangular number calculation part of the Perl code, except for the variable names and the use of print
rather than say
. (Incidentally, although A Pear Tree often allows you to omit the $
before a variable name, it doesn't allow this after the ++
operator and wouldn't save bytes after the print
, so for once all the $
s are present.)
In order to mark the appropriate substrings of the code, I changed the variable names (and other details like the specific truthy constant in the Perl code – obviously, any truthy constant would work for Perl, not just 6
, but 6
worked best for A Pear Tree), which is why they're so weird.