29
\$\begingroup\$

A radiation-hardened program is a program where, if any character of the code is removed, the program will still function the same. For this question, we'll be writing a program that detects when it is irradiated.

Write a program or function that, when any single byte is removed, the resulting program will output that byte and only that byte. (You may output that byte multiple times, as long as you don't output any other byte)

Rules:

  • The program has to contain at least 2 distinct bytes. (No solutions of just 0s ;)
  • It doesn't matter what the original program does
  • No reading your own source code.
  • The code will be scored on the number of distinct bytes, where the highest amount wins. For example, abc = 3 points, ababba = 2 points, abc wins.
    • Tie-breaker is the smaller byte count, followed by the earlier submission time

Good luck!

\$\endgroup\$
22
  • \$\begingroup\$ Sandbox Post (deleted) Related, related, related \$\endgroup\$
    – Jo King
    Jan 29, 2018 at 8:18
  • \$\begingroup\$ I missed that line. Shame on me! \$\endgroup\$
    – user45941
    Jan 29, 2018 at 8:34
  • 5
    \$\begingroup\$ "The code will be scored on the number of distinct characters, where the highest amount wins." I expect that most (if not all) solutions will have some form of string somewhere which they can just pad with arbitrary characters without actually changing the solution (so it just comes down to whether your language is restricted to ASCII, extended ASCII or Unicode). \$\endgroup\$ Jan 29, 2018 at 9:17
  • 3
    \$\begingroup\$ ... The sandbox is not perfect. :( / You can just measure "distinct bytes" instead of "distinct characters", because characters are related to encoding and other problems. \$\endgroup\$
    – DELETE_ME
    Jan 29, 2018 at 9:57
  • 1
    \$\begingroup\$ Can the program take any input? \$\endgroup\$
    – gggg
    Feb 15, 2018 at 20:47

7 Answers 7

15
\$\begingroup\$

05AB1E, 9 7 bytes (Score of 3)

22'''rr

Try it online!

Removing a '

With any ' removed, 22''rr will result in 22 being the first thing on the stack and a ' being the last thing on the stack, which when reversed twice results in '.

Removing an r

With any r removed, 22'''r results in 22 being the first thing on the stack, a ' being the second thing on stack, and an r being the last thing on the stack. This r, however, was preceeded by a ' which makes it the literal string "r" (as opposed to the command reverse stack), which is implicitly printed.

Removing a 2

With any 2 removed, 2'''rr will result in a 2 being the 1st thing on the stack, ' being the 2nd thing on the stack and finally r being the last thing on the stack, which when reversed once results in 2.

Therefore, this answer is valid. With nothing removed it outputs ', which is irrelevant. This works for any number other than 2 as well.


Created a validity checker, you can use it to compete in 05AB1E*.

*I'm not 100% sure how many solutions are even possible in 05AB1E...


More valid solutions that are Worse or the Same

  • 1-Point (invalid)
  • 2-Point
    • '''''''VV, '''''''XX or '''''''<any command that pops a without pushing>x2
    • Any odd # of ' above 3 followed by any even # of s above 1 (E.G. '''''''''ssss).
    • '''.. with any number of periods above 1 and any odd number of ' above 2.
  • 3-Point
    • '\\'''rr - same idea as 22'''rr but \ is 'remove last stack item'.
\$\endgroup\$
5
  • \$\begingroup\$ Normal output of ' is irrelevant by the rules, as you say. But it does invalidate the nominal goal of detecting anomalies, which is a bit funny. \$\endgroup\$
    – gggg
    Feb 15, 2018 at 20:51
  • 1
    \$\begingroup\$ @gggg I'm fairly certain at least ONE of my alternatives prints nothing lol. \$\endgroup\$ Feb 16, 2018 at 16:52
  • 1
    \$\begingroup\$ @MagicOctopusUrn You're welcome. Just thought I may as well edit instead of commenting. \$\endgroup\$
    – boboquack
    Feb 16, 2018 at 20:39
  • \$\begingroup\$ @boboquack did my original tag (@boboquack) work, or did you find it by viewing the post again? I'm trying to figure out how tags work when the user never commented lol. \$\endgroup\$ Feb 16, 2018 at 20:41
  • \$\begingroup\$ @boboquack I meant did you get a notification from my "thank you"? Also, we should probably delete this thread up until my +1 for your "You're welcome". \$\endgroup\$ Feb 16, 2018 at 20:52
11
\$\begingroup\$

Brainfuck, Score 3

May be noncompeting as output is only seen through a memory dump.

+++++++++++++++++++++++++++++++++++++++++++++,-

Assuming input is empty and EOF leaves the cell unchanged. Uses an interpreter that dumps the memory to an output, such as this one.

Remove a plus, and the memory is the unicode value for "+" , else it is the unicode value for ",". Its more of a rule bender than a answer though. Pretty much the same with "-". Abuses the fact that these three characters are after each other in the unicode-characterset.

\$\endgroup\$
9
  • \$\begingroup\$ Smart, to be entirely honest, don't think it's a loophole. \$\endgroup\$ Feb 14, 2018 at 22:04
  • \$\begingroup\$ You're assuming EOF leaves the cell unchanged, yes? \$\endgroup\$
    – Jo King
    Feb 14, 2018 at 22:06
  • \$\begingroup\$ Yeah, and as long as there is no input, it should be fine 😊 \$\endgroup\$ Feb 14, 2018 at 22:07
  • \$\begingroup\$ I'm tempted to allow this, but do you have an interpreter that has a memory dump that would output only changed cells and leaves the cell unchanged on EOF? \$\endgroup\$
    – Jo King
    Feb 14, 2018 at 22:11
  • 1
    \$\begingroup\$ copy.sh/brainfuck This one should work fine. Just run it and hit "view memory". \$\endgroup\$ Feb 14, 2018 at 22:14
11
\$\begingroup\$

A Pear Tree, 256 distinct bytes, 975 bytes

Unfortunately, the question pretty much requires an optimal solution to contain a NUL byte somewhere (as it needs to contain all 256 bytes somewhere). This means that a) I can't give you a TIO link (because TIO dislikes NUL in programs, or at the least, I haven't figured out a way to type it that my browser can cope with), and b) I can't paste the program into Stack Exchange literally. Instead, I've placed an xxd reversible hexdump hidden behind the "code snippet" link beneath.

00000000: 0a24 7a7b 242f 7d2b 2b3b 242f 3d24 5c3d  .$z{$/}++;$/=$\=
00000010: 2440 3b21 247a 7b24 5f7d 3f24 7a7b 245f  $@;!$z{$_}?$z{$_
00000020: 7d3d 313a 6465 6c65 7465 247a 7b24 5f7d  }=1:delete$z{$_}
00000030: 666f 7220 7370 6c69 742f 2f2c 3c44 4154  for split//,<DAT
00000040: 413e 3b70 7269 6e74 206b 6579 7325 7a3e  A>;print keys%z>
00000050: 353f 225c 6e22 3a6b 6579 7325 7a3b 5f5f  5?"\n":keys%z;__
00000060: 4441 5441 5f5f 2000 0102 0304 0506 0708  DATA__ .........
00000070: 090b 0c0d 0e0f 1011 1213 1415 1617 1819  ................
00000080: 1a1b 1c1d 1e1f 2326 2728 292a 2b2d 2e30  ......#&'()*+-.0
00000090: 3334 3536 3738 3942 4345 4647 4849 4a4b  3456789BCEFGHIJK
000000a0: 4c4d 4e4f 5051 5253 5556 5758 595a 5b5d  LMNOPQRSUVWXYZ[]
000000b0: 5e60 6162 6367 686a 6d71 7576 7778 7c7e  ^`abcghjmquvwx|~
000000c0: 7f80 8182 8384 8586 8788 898a 8b8c 8d8e  ................
000000d0: 8f90 9192 9394 9596 9798 999a 9b9c 9d9e  ................
000000e0: 9fa0 a1a2 a3a4 a5a6 a7a8 a9aa abac adae  ................
000000f0: afb0 b1b2 b3b4 b5b6 b7b8 b9ba bbbc bdbe  ................
00000100: bfc0 c1c2 c3c4 c5c6 c7c8 c9ca cbcc cdce  ................
00000110: cfd0 d1d2 d3d4 d5d6 d7d8 d9da dbdc ddde  ................
00000120: dfe0 e1e2 e3e4 e5e6 e7e8 e9ea ebec edee  ................
00000130: eff0 f1f2 f3f4 f5f6 f7f8 f9fa fbfc fdfe  ................
00000140: ff4b 3d20 ab0a 247a 7b24 2f7d 2b2b 3b24  .K= ..$z{$/}++;$
00000150: 2f3d 245c 3d24 403b 2124 7a7b 245f 7d3f  /=$\=$@;!$z{$_}?
00000160: 247a 7b24 5f7d 3d31 3a64 656c 6574 6524  $z{$_}=1:delete$
00000170: 7a7b 245f 7d66 6f72 2073 706c 6974 2f2f  z{$_}for split//
00000180: 2c3c 4441 5441 3e3b 7072 696e 7420 6b65  ,<DATA>;print ke
00000190: 7973 257a 3e35 3f22 5c6e 223a 6b65 7973  ys%z>5?"\n":keys
000001a0: 257a 3b5f 5f44 4154 415f 5f20 0001 0203  %z;__DATA__ ....
000001b0: 0405 0607 0809 0b0c 0d0e 0f10 1112 1314  ................
000001c0: 1516 1718 191a 1b1c 1d1e 1f23 2627 2829  ...........#&'()
000001d0: 2a2b 2d2e 3033 3435 3637 3839 4243 4546  *+-.03456789BCEF
000001e0: 4748 494a 4b4c 4d4e 4f50 5152 5355 5657  GHIJKLMNOPQRSUVW
000001f0: 5859 5a5b 5d5e 6061 6263 6768 6a6d 7175  XYZ[]^`abcghjmqu
00000200: 7677 787c 7e7f 8081 8283 8485 8687 8889  vwx|~...........
00000210: 8a8b 8c8d 8e8f 9091 9293 9495 9697 9899  ................
00000220: 9a9b 9c9d 9e9f a0a1 a2a3 a4a5 a6a7 a8a9  ................
00000230: aaab acad aeaf b0b1 b2b3 b4b5 b6b7 b8b9  ................
00000240: babb bcbd bebf c0c1 c2c3 c4c5 c6c7 c8c9  ................
00000250: cacb cccd cecf d0d1 d2d3 d4d5 d6d7 d8d9  ................
00000260: dadb dcdd dedf e0e1 e2e3 e4e5 e6e7 e8e9  ................
00000270: eaeb eced eeef f0f1 f2f3 f4f5 f6f7 f8f9  ................
00000280: fafb fcfd feff 4b3d 20ab 0a24 7a7b 242f  ......K= ..$z{$/
00000290: 7d2b 2b3b 242f 3d24 5c3d 2440 3b21 247a  }++;$/=$\=$@;!$z
000002a0: 7b24 5f7d 3f24 7a7b 245f 7d3d 313a 6465  {$_}?$z{$_}=1:de
000002b0: 6c65 7465 247a 7b24 5f7d 666f 7220 7370  lete$z{$_}for sp
000002c0: 6c69 742f 2f2c 3c44 4154 413e 3b70 7269  lit//,<DATA>;pri
000002d0: 6e74 206b 6579 7325 7a3e 353f 225c 6e22  nt keys%z>5?"\n"
000002e0: 3a6b 6579 7325 7a3b 5f5f 4441 5441 5f5f  :keys%z;__DATA__
000002f0: 2000 0102 0304 0506 0708 090b 0c0d 0e0f   ...............
00000300: 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f  ................
00000310: 2326 2728 292a 2b2d 2e30 3334 3536 3738  #&'()*+-.0345678
00000320: 3942 4345 4647 4849 4a4b 4c4d 4e4f 5051  9BCEFGHIJKLMNOPQ
00000330: 5253 5556 5758 595a 5b5d 5e60 6162 6367  RSUVWXYZ[]^`abcg
00000340: 686a 6d71 7576 7778 7c7e 7f80 8182 8384  hjmquvwx|~......
00000350: 8586 8788 898a 8b8c 8d8e 8f90 9192 9394  ................
00000360: 9596 9798 999a 9b9c 9d9e 9fa0 a1a2 a3a4  ................
00000370: a5a6 a7a8 a9aa abac adae afb0 b1b2 b3b4  ................
00000380: b5b6 b7b8 b9ba bbbc bdbe bfc0 c1c2 c3c4  ................
00000390: c5c6 c7c8 c9ca cbcc cdce cfd0 d1d2 d3d4  ................
000003a0: d5d6 d7d8 d9da dbdc ddde dfe0 e1e2 e3e4  ................
000003b0: e5e6 e7e8 e9ea ebec edee eff0 f1f2 f3f4  ................
000003c0: f5f6 f7f8 f9fa fbfc fdfe ff4b 3d20 ab    ...........K= .

Explanation

This program consists of three identical parts. (Concatenating multiple identical portions of a program is something of a theme for me in programs.) Every A Pear Tree requires a checksum somewhere to let the interpreter know which parts of the program to run; it rotates any portion of the program for which the checksum succeeds to the start before running it (or prints a partridge if no checksum matches). In this case, we have a checksum on each of the three parts, and thus a non-irradiated part will move to the start. So we can assume that the program consists of an unmodified part, followed by two other parts (one of which may have been modified).

Each part starts with a newline, then continues with the following code (I've added whitespace and comments below):

$z{$/}++;      # In the hash table %z, set the key "\n" to 1
$/=$\=$@;      # Turn off newline handling when reading ($/ = undef);
               # Also don't add newlines when printing ($\ = undef)
               # $@ is set to undef by default
!$z{$_}?       #   If the current character is not in the hash table %z
  $z{$_}=1:    #   place it in the hash table %z
  delete$z{$_} #   else remove it from the hash table %z
for split//,   # for each character in
    <DATA>;    # the text appearing from the line beneath __DATA__ to EOF
print          # Print the following (no newline because $\ was undefined):
  keys%z>5?    # if the hash table %z contains more than 5 elements:
  "\n":        #   a newline; otherwise
  keys%z;      #   every key of %z, separated by spaces
__DATA__       # Start a string literal running from after this line to EOF

After that comes a copy of every octet that hasn't been used in the program so far (purely to run the score up), and finally the checksum. (There's no trailing newline; parts start with a newline but don't end with one.)

There are three distinct cases here:

  • A character other than a newline was deleted. In this case, it'll appear an odd number of times in the second and third parts. That means it'll be added and/or removed from %z an odd number of times, finally ending up in the hash table. In fact, it'll be the only key in the hash table (as the string runs from after the newline of the second part to the end of the third part, and the hash table started with just a single newline), so it'll just be printed out on its own.
  • The first or third newline was deleted. In this case, the program will be rotated such that it's the third of the newlines that's missing, effectively merging the second and third parts into a single line. The string literal accessed via <DATA> contains every character an even number of times, so the hash table will have its original content, a single newline, and that'll get printed.
  • The second newline was deleted. In this case, the program won't be rotated (as the first part has a valid checksum), so the second part will be moved onto the same line as the first part. <DATA> only starts reading from the line below __DATA__, so it'll only see the third part. This has more than five characters that appear an odd number of times, so it'll trigger the special case to print a newline.

Verification

One final thing that has to be checked for pretty much any radiation-hardened A Pear Tree program is whether a deletion happens to randomly cause an unwanted section of the code to checksum correctly and rotate the code into the wrong place; given that we're using 32-bit checksums, this is unlikely but not impossible. I used the following brute-force script to ensure that this doesn't happen for any deletion:

use 5.010;
use IPC::Run qw/run/;
use warnings;
use strict;
use Data::Dumper;
$Data::Dumper::Useqq=1;
$Data::Dumper::Terse=1;
$Data::Dumper::Indent=0;
undef $/;
$| = 1;
my $program = <>;

for my $x (0 .. (length($program) - 1)) {
    my $p = $program;
    my $removed = substr $p, $x, 1, "";
    alarm 4;
    say Dumper($p);
    run [$^X, '-M5.010', 'apeartree.pl'], '<', \$p, '>', \my $out, '2>', \my $err;
    if ($out ne $removed) {
        print "Unexpected output deleting character $x ($removed)\n";
        print "Output: {{{\n$out}}}\n";
        print "Errors: {{{\n$err}}}\n";
        exit;
    }
}

say $program;
run [$^X, '-M5.010', 'apeartree.pl'], '<', \$program, '>', \my $out, '2>', \my $err;
if ($out ne '') {
    print "Unexpected output not mutating\n";
    print "Output: {{{\n$out}}}\n";
    print "Errors: {{{\n$err}}}\n";
    exit;
}

say "All OK!";

The verification script confirms that this program works correctly.

\$\endgroup\$
7
\$\begingroup\$

Stax, 11 bytes (Score of 4)

'''cc'~~'dd

Run and debug online!

It is my honor to have the first (chronologically) answer to this challenge with a score higher than or equal to 4. Maybe the score can be even higher though.

In Stax, a string literal that is composed of a single character is written with ', so '', 'c, 'd, '~ are all string literals. The corresponding commands for c d and ~ means duplicate the top of the main stack, pop the top of the main stack, and pop the top of the main stack and push to the input stack, respectively. For this challenge, input stack does not affect output and is not important, hence we can say d and ~ are identical.

Explanation

It is best to divide the code into several parts and consider them separately.

When it is not tampered with, '''cc pushes a literal ' and a literal c to the main stack, and duplicates the top, so the stack would be (from to bottom) c,c,'.

When not tampered with, '~~ pushes the literal ~ and then pops it (and push to the input stack), which is basically a no-op for the main stack.

When not tampered with, 'dd pushes the literal d and then pops it, another no-op for the main stack.

At the end of the program, since no explicit output is done, the top of the main stack will be implicitly printed out.

If the program is running as-is, the final stack is still c,c,' and will output c.

If the first part becomes ''cc, then we have a literal ', and two copy instructions, the final stack will be ',','. Given that the two other parts are no-op, the result will be '.

If the first part becomes '''c, the result is basically the same with the untampered one, but the c is not duplicated. So the stack will be c,'. After two no-op's the top of the stack is c.

So we can detect radiation in the first part.

The second part and the third part work in exactly the same way. I will take the third part as an example.

If the third part is tampered with, then the first two parts are kept as-is and the stack before running the third part is c,c,'

If the third part becomes 'd, a literal d is pushed to the top of the main stack and nothing further is done. The top of the main stack is now d which will be output.

If the third part becomes dd, two elements are popped from the main stack and now the top of the stack is ' and is output.

Hence we can detect radiation in the third part. For the same reason we can detect radiation in the second part.

\$\endgroup\$
5
+200
\$\begingroup\$

05AB1E, score 2, 6 bytes

„"""„„

Prints double the removed character sometimes. Doesn't contain '.

How it works:

Removing the first

"""„„

Try it online!

First, we push an empty string literal to the stack. Then we push „„, which is printed implicitly.

Removing a "

„""„„

Try it online!

First, we push "" to the stack with the 2-char string instruction. Then we try to get another 2-character string, but this is aborted (I'm not exactly sure why) and the "" is printed.

Removing the second or third

„"""„

Try it online!

First, we push "" to the stack with the 2-char string instruction. Then we push , which is printed implicitly.

\$\endgroup\$
5
\$\begingroup\$

Jelly, 5 bytes, score 2

”””ḷḷ

Try it online!

With any removed:

””ḷḷ

Try it online!

The character begins a one byte character literal. This programs begins with ”” which yields the string . The dyad takes it's left argument. The string just gets passed through the two instances of .

With any removed:

”””ḷ

Try it online!

In this program ”” yields the character then ”ḷ yields the character and only this is output.


Other solutions

  • Lots of other characters such as a or o would have worked in place of for this submission.
  • ⁾⁾⁾⁾FFF. This works in a similar way. is like but it starts a two byte string literal. The "irradiated" programs output the deleted byte twice which was ruled valid in the comments.

Here is a (much less fancy) Jelly version of Magic Octopus Urn's validity checker. The left column of the output is the deleted character and the right column is the output of the resulting program.

\$\endgroup\$
1
  • \$\begingroup\$ My validity checker isn't thaaat fancy. It fails for the other solution posted ;). \$\endgroup\$ Feb 20, 2018 at 19:34
2
\$\begingroup\$

Vyxal, 65 bytes, score 22

\\\::\__\⅛⅛\££\→→\((\[[\‟‟\**\••\--\oo\PP\ḞḞ\↳↳\↲↲\⋏⋏\ǑǑ\FF\jj\∇∇

Try it Online!

Based on Weijun Zhou's Stax answer.

In Vyxal, \ takes the next character as a single character. So, the bit at the start \\\:: pushes "\", pushes ":", then duplicates it with the operation :.

The stack is now ["\", ":", ":"].

If either : is removed, the : operation is not run and the stack is just ["\", ":"]. If any \ is removed, the stack becomes ["\","\","\"].

The rest of the program is chunks of \xx, where x is some operation that effectively does nothing but remove a string from the stack. These chunks normally do nothing, as they effectively push and pop a value.

If a backslash is removed, an operation that effectively pops the stack is run twice, removing the two ":" from the stack and leaving the backslash we pushed at the start.

If either x is removed, the string "x" is pushed to the stack and not removed.

Finally, the top of the stack is implicitly output.

Operations, and why they work

For these, x is the value already on the stack and y is the value

  • _ - Simply pops y
  • - Pushes y to the global array.
  • £ - Stores y to the register
  • - Stores y to the empty variable
  • ( - starts a for loop over y. As it's a 1-character string the code inside is run once
  • [ - If y is truthy, execute the remaining code. It will always be truthy.
  • - Rotate y to the bottom of the stack.
  • * - Ring translate x by y. Since the strings share no characters, nothing happens.
  • - Give x the casing of y. Since this occurs before anything alphabetical, nothing happens.
  • - - Remove y from x
  • o - Remove y from x
  • P - Strip y from the outside of x
  • - Replace spaces in x with y. There are no spaces in x.
  • - Pad x according to y
  • - Pad x according to y
  • - Center x according to y
  • Ǒ - Remove y from x until x doesn't change
  • F - Remove characters in y from x
  • j - Join y by x. This does nothing to a 1-character x.
  • - Rotate the top three items of the stack. Has to be at the end.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.