# Schrödinger's cat program [closed]

Sandbox

Your challenge is to write a program that when first run, will do one of the actions below at random with equal chances of both:

• A cat program

• A standard cat program: read everything from STDIN and put it on STDOUT (or your language's closest equivalent).
• Do nothing and halt

• This shouldn't output anything.

The behaviour is permanent - once the program chooses between the two options, it should do that no matter how much times you run the script. It's fine if this resets when you reboot.

Please provide an explanation on how to reset the program (which file to delete for example)

Standard loopholes are forbidden.

This is a , so the shortest code (in bytes or equivalent) wins.

• Must it be a full program or may it be a function? Dec 27 '21 at 21:17
Dec 27 '21 at 21:24
• @Adám yes, but the wording above, in multiple places, seems to imply the OP is after a full program here. Dec 27 '21 at 21:27
• @JonathanAllan I don't see where that's implied.
Dec 27 '21 at 21:27
• If a function is allowed, it's not obvious to me whether it should be tested by multiple function calls in one run, or re-executing the code and calling the function once each time. The first seems much easier to accomplish.
– xnor
Dec 28 '21 at 0:15

# Python 3, 94 bytes

from random import*
open(__file__,"w").write(s)
exec(s)


Try it online!

Picks one of ​ or print(open(0).read()) and replaces the contents of the file with it. Then, executes that code once.

To reset it, you will have to copy-paste this code into the file again, since it overwrites the file itself. This perseveres so long as the file exists and is not modified, so it is remembered through reboots and even if you move the file to another computer.

-5 bytes thanks to Jonathan Allan
(Also -5 thanks to Jakque by using choice(["print(open(0).read())",""]) instead of randint(0,1)*"print(open(0).read())" - both are excellent golfs; I just chose the first one.)

• s="print(open(0).read())"*randint(0,1) saves five. Dec 27 '21 at 20:58
• s=choice(["print(open(0).read())",""]) also works for -5 Dec 28 '21 at 0:58
• You can use import os;s=ord(os.urandom(1))%2*... to save a couple more bytes. Dec 28 '21 at 22:45

# R, 37 36 bytes

Edit: -1 byte thanks to Giuseppe

{q=rt(1,1)<0;function(x)if(q)cat(x)}


Try it online!

Function that acts randomly as cat or no-op on first call, and then stays with this behaviour forever (or until deleted).

# R, 83 bytes

if(!F)write(paste("F=",F<-sample(1:2,1)),".Rprofile");if(F<2)show(scan("stdin",""))


Try it online!

Full program: saves state into ".Rprofile" file in directory from which R or Rscript is launched: delete this to reset program behaviour.

• rt(1,1) should be a byte shorter? Dec 27 '21 at 23:29

This method uses no special files. In fact it doesn't store data anywhere.

To set up your randomize_va_space should be set to zero (linux).

You can check this with:

sysctl -anr "e_v"


I won't tell you how to set it to 0 since in general this should not be set to 0, and setting it to 0 represents a possible security risk. Don't play with your kernel unless you know what you are doing or have nothing to lose on the device.

import Unsafe.Coerce
main=([[interact id],[pure()]]>>=([0..7]>>))!!mod(unsafeCoerce(+))16


Try it online!

TIO is stuck on cat and I have no way to reset it. You can switch the + to a : to see a version that is stuck on the noop.

To reset it locally it should be enough to set the randomize_va_space to 2 run the program once and then set it back to 0.

## Explanation

More detailed explanation here

In Haskell, all complex objects including functions are internally represented as a pointer. This is a number in binary that "points" to a specific location in memory. This is because we want to pass these values by reference, since copying the whole thing is expensive, and since Haskell disallows mutation we can with no problem.

However simple objects like ints are passed by value since they are so small that copying them is about as expensive as copying a pointer would be. unsafeCoerce is a super unsafe function which just takes the raw bytes from one object and reinterprets it as the raw bytes for another type.

So if we use unsafeCoerce from a function to an Int, the resulting Int is just the value of the pointer to the object. And the value of that simple object is dependent only on where the complex object is located not anything about what it is.

When randomize_va_space is on, this means the value of unsafeCoerce(+) is a random multiple of 8. However when it's off, it is fixed to one value which depends on some factors about the machine.

• Grats on breaking TIO Dec 28 '21 at 18:57

# APL (Dyalog Unicode), 15 bytes

Anonymous lambda. Takes one or two dummy arguments. Requires 0-based indexing.

{6::∇a∘←?2⋄a:⍞}


Try it online!

You can reset the program by erasing its global state a.

{} "dfn":

6:: if we hit a value error:

a∘← globally assign to a:

?2 a random 0 or 1

⋄ now try:

a: if a [is 1]:

⍞ read STDIN [and implicitly return and print it]

• Is this a progam or just a function? (Looks to me like a is something that exists at the program scope and we are re-running a function rather than a program.) Dec 27 '21 at 21:03
• @JonathanAllan This is a function that takes an argument just to run; it doesn't use the argument.
Dec 27 '21 at 21:03
• I read "it should do it no matter how much times you run the script." as "this must be a full program, which has some way to enforce the repeated behaviour between runs". Dec 27 '21 at 21:05
• Program or function doesn't really matter for that, imo. It is trivial to rewrite as a full program. The argument has nothing to do with the saved state; it uses a global variable for that.
Dec 27 '21 at 21:06
• As written it looks to me like we must write a full program, but I've asked. (It might make a huge difference for some languages!) Dec 27 '21 at 21:17

# C (gcc), 149 bytes

Stores either s or u into the user.a extended attribute of the executable. setxattr() doesn't replace an already-existing value, so I just write the value and then retrieve it to see whether to cat the input (s) or not (u).

To reset the program, run setfattr -x user.a {programname}

main(a,v,s)char*v,*s;{char r[]="user.a";srand(time(0));s=r+rand()%2;setxattr(*v,r,s,1,1);getxattr(*v,r,s,1);if(*s&2)while(~(a=getchar()))putchar(a);}


Try it online!

# JavaScript (ES2020), browser, 56 52 bytes

(localStorage.d||=Math.random())>.5&&alert(prompt())


Sets the d property of localStorage if it's undefined. Stacksnippets doesn't like setting localstorage, so run this in your console to see.

Full program. -4 thanks to tsh.

• Maybe you can save the random number and then test >.5 every time the program run.
– tsh
Dec 28 '21 at 1:04
• @tsh Nice idea! Dec 28 '21 at 2:09
• But typically, a cat support multiple lines input.
– tsh
Dec 28 '21 at 2:48
• @tsh That's a system limitation :P Dec 28 '21 at 2:49
• Saving +new Date and checking %2 should shave 5 more bytes. However I'm not sure this really qualifies as a "Full program" since the Storage API needs a Document, I think the shortest would thus be an HTML one <script>your-code</script>, but I guess this will depend on how the question gets edited anyway. Dec 29 '21 at 14:37

## Batch, 53 bytes

@if "%c%"=="" set/ac=%random%%%2
@if %c%==1 find/v""


Use set c= to reset the flag. Explanation: If c is empty, the first line sets c to a random value that is either 0 or 1, then the second line copies STDIN to STDOUT only if c is 1. I don't know why the builtin find command fails to find the empty string in any input, but it's consistent, so we can simply invert the condition, thus turning find into a cat program.

• As usual for weird arcane history of Microsoft stuff, Raymond Chen wrote about this ten years ago! Dec 28 '21 at 5:41

# AWK, 48 bytes

BEGIN{a=systime()%2;getline a<"_";print a>"_"}
a


Try it online!

systime() is used to decide whether to print or not. State is saved in the file _. getline does not clobber variables if it doesn't read anything.

# Python 3, 66 62 bytes

import random
if random.randint(1,2)==1:print(str(input("I")))


Gets a random value and if it's 1, it gets and prints user input. I just put an I (for input) because my Python interpreter allows you to give input even when not asked for.

# Zsh, 35 bytes

((RANDOM&1))&&p='<&0'&&<&0
<<<$p>$0


Try it online!

Randomly overwrites the file with either <&0 (equivalent to cat) or nothing.

# MATLAB/Octave, 80 60 bytes

global x;if x;else;x=randi(1:2);end;if x>1;input('','s');end


Will either do nothing, or whatever the user inputs to ans= (considered "STDOUT" for our purpose), then stick with that choice.

When first used a global variable (x here) is empty. Empty values evaluate to false. If x is false, it will set it to a random integer of either 1 or 2. This will then never evaluate false again, so the first part of the program will then never run again.

If x is 2, then the program will request user input (considered "STDIN" for our purpose). If x is 1, will do nothing at all.

Relies on the fact that a global variable is persistent once created, and will only reset if the user clears all variables ("reboots" for our purpose).

I would add a TIO link, but unfortunately that doesn't seem to want to handle global variables.