Design a function or program that, when run normally, outputs the triangular numbers. However, when any single character is deleted, the program/function should not function in the original programming language, but instead produce the triangular numbers in one other programming language.
Scoring
Your score will be the number of characters in your program for which the program is not valid in your second chosen language.
Lowest score wins, tiebreaker is byte count.
Specific Rules
You may infinitely output triangular numbers, produce a list of the first N with a positive integer input N, or produce the Nth triangular number. Each of the programs may have different behavior in this respect.
Your original program may run in the second language, but it can't produce the correct output.
Your programs may also output in different bases/use different indexing/use different output formats, as long as that format would be valid in a sequence challenge.
No more than 20% of your characters, rounded down, may be invalid.
An invalid character is any character that, when removed, creates no program or function that outputs triangular numbers in your second chosen language.
Any time you remove a character from the original code, it should break it.
Separate versions of programming languages ARE permitted to be treated as different languages.
-
\$\begingroup\$ Can you confirm (or not): is it Ok to have some nonzero number of characters that, when deleted, still allow the program to function in the first language (and that these are counted as 'invalid characters')? \$\endgroup\$Dominic van Essen– Dominic van Essen2022年05月18日 08:13:58 +00:00Commented May 18, 2022 at 8:13
-
2\$\begingroup\$ Can the initial program work in the second language? Your challenge to my best reading doesn't seem to rule it out (only the other way around), but I think it would be a good rule. Otherwise you just make a radiation hardened program that's also a polyglot. \$\endgroup\$Wheat Wizard– Wheat Wizard ♦2022年05月18日 09:51:03 +00:00Commented May 18, 2022 at 9:51
-
\$\begingroup\$ I agree with @WheatWizard that ruling this out would be a good rule. Currently my answer does work in the second language, and I must admit that this made it fairly low effort... \$\endgroup\$Dominic van Essen– Dominic van Essen2022年05月18日 10:35:18 +00:00Commented May 18, 2022 at 10:35
-
2\$\begingroup\$ "Your original program may run in the original language, but it can't produce the correct output." I think you mean "...run in the second chosen language"...? \$\endgroup\$Dominic van Essen– Dominic van Essen2022年05月18日 16:21:45 +00:00Commented May 18, 2022 at 16:21
-
1\$\begingroup\$ Changed. I think that's about what's left on scoring, but we'll see. \$\endgroup\$Romanp– Romanp2022年05月18日 18:26:13 +00:00Commented May 18, 2022 at 18:26
1 Answer 1
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
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.
Explore related questions
See similar questions with these tags.