# Shortest code in your language to persist a string across a reboot

You'll write two programs (both in the same language). The storage program takes a string from STDIN and stores it somewhere persistent (see below) and then exits without error. The retrieval program takes no input, retrieves the string that was stored, and prints it to STDOUT.

### Objective test of Persistence:

You should be able to run the storage program on your local machine, then power-cycle your local machine, then call the retrieval program on your local machine. You can stash the string however you want (even on the web) as long as you pass this reboot test.

### Test Cases:

Storage then retrieval:

echo foo | Store
Retrieve
foo


Repeated Stores should overwrite (like a set() method):

echo foo | Store
echo bar | Store
Retrieve
bar


Repeated Retrieval is non-destructive (like a get() method):

echo foo | Store
Retrieve
foo
Retrieve
foo


Retrieval before any invocation of Storage:

You don't need to worry about this. Your retrieval program can assume that the storage program has been run at some point in the past.

### Input/Output flexibility.

People have asked me to expand this from strict STDIN/STDOUT to the standard IO rules. I can't because it would introduce too many loopholes. Some standard IO options already have the input stored in a persistent way, eg "programs may take input from a file". I'd like to be more flexible than just strict STDIN and STDOUT, but without opening the floodgates.

From the standard IO rules thread I'm cherry-picking the ones that don't break the challenge:

If you use an alternate it must be user-interactive. The user shouldn't have to do any other work besides piping their input to your program, typing it into a prompt your program provides, or typing input as a command-line-arg of your program. The user shouldn't have to do anything other than running your retrieve program to see the output displayed on screen or sent to STDOUT or STDERR.

### Allowed assumptions:

• Your two programs will be run in the same directory
• Files you create will survive the reboot (not in a temp dir)
• One trailing newline that wasn't part of the string is allowed. No other trailing whitespace

• so just echo $@>x and cat x is valid? – Adám Jul 5 '18 at 23:30 • Your spec doesn't mention the ability to store multiple times, but you do have an example case that does so. May we assume a clean environment for each invocation of Store? – Adám Jul 5 '18 at 23:40 • @EriktheOutgolfer Why would it not be valid? Even if there is a loophole discussed on meta that doesn't prevent a challenge from specifically allowing it. – dylnan Jul 5 '18 at 23:45 • Web restrictions are usually about pulling stuff from the web as a loophole to get out of doing the work of creating that stuff. In this case, if it's on the web it's because you did the work of putting it there. – Jared K Jul 6 '18 at 0:18 • Somebody needs to write an answer for a computer with magnetic-core memory. – Mark Jul 6 '18 at 23:30 ## 40 Answers ## zsh, 4 bytes Store: >f (reads from STDIN and writes to a file called f) Retrieve: <f (writes the contents of f to STDOUT) • I think we have a winner. – Adám Jul 6 '18 at 0:06 • @Adám unless there is a token to write input to file in 1 byte :P – FreezePhoenix Jul 6 '18 at 0:08 • @FreezePhoenix There is probably none unless you write a new language now which is not allowed... – Chromium Jul 6 '18 at 10:37 • @Chromium check Z80 answer: some existing languages can write from a 0 bytes program. – Cœur Jul 6 '18 at 16:20 # TI-BASIC (Z80), 1 byte? Store: (just enter the string) Retrieve: Ans (byte 27) But if that isn't valid: # TI-BASIC (Z80), 7 6 bytes -1 thanks to Jakob. Store: Prompt Str0 (bytes DD AA 09) Retrieve: disp Str0 (bytes ED AA 09) • Are you sure that's 5 bytes? – FreezePhoenix Jul 5 '18 at 23:49 • @FreezePhoenix TI-Basic uses tokens. – Adám Jul 5 '18 at 23:53 • Hmm...Why not take input through Ans and persist it in the same variable? An empty store program and just Ans for retrieve should work: 1 byte! – Jakob Jul 6 '18 at 5:23 • @Arthur Yep, Ans persists. In fact, a lot of state persists, including (I think) all user variables, equations, and history. From the user's perspective, powered off is basically the TI calculator equivalent of a sleep state for a PC, so it doesn't disrupt much. – Jakob Jul 6 '18 at 15:29 • @JaredK I definitely agree that the 1-byte solution smells of rule abuse (even though I was the one who suggested it). However, I would say the store program exits, since other programs can be run after it (though they interfere with the operation of the solution). My interpretation of your "objective test of persistence" was that the programs would be run directly before and after the power cycle. If that is incorrect, perhaps you could require the 1-byte solution to be marked noncompeting? – Jakob Jul 7 '18 at 21:57 # Browser JS, 44 bytes Store: localStorage.a=prompt()  Retrieve: alert(localStorage.a)  • Will prompt() read from STDIN? – pipe Jul 6 '18 at 11:19 • Does a graphical web browser have an STDIN? No. prompt() pops up an alert that asks for you to enter text, and returns the result. – Dev Jul 6 '18 at 12:40 • @Dev Of course a graphical web browser have a STDIN, just like every other process. If you can't use it from a specific language is another question and if the answer is "No", then I maybe it can be used in this challenge. – pipe Jul 6 '18 at 14:02 • @Dev The default I/O methods include input via GUI prompt and output via GUI display. Unless OP meant to override the standard, this should be valid. I'll clarify. – Esolanging Fruit Jul 6 '18 at 16:29 • I've edited the challenge to allow more IO, but I'm only expanding it to a limited subset of the default IO methods. This answer is within my subset though. I like it. – Jared K Jul 6 '18 at 17:52 # POSIX shell sh/bash/... 8 bytes store: dd>f  get: dd<f  • Nice one, beats even cat... – cmaster Jul 6 '18 at 19:40 # Python 3, 46 bytes ### store, 45 bytes: open(*'fw').write('print(%r)'%open(0).read())  The retrieve program is built by the store command, a file named f. (1 byte for the file name) • Surely you can use input()? – Artemis Fowl Jul 6 '18 at 21:28 • @ArtemisFowl input() only receives up to the first newline. open(0).read reads all of STDIN – Jo King Jul 22 '18 at 8:53 • You probably posted when things were still ambiguous, but as-is this answer doesn't meet the current spec. I originally intended the STDIN/STDOUT requirement to be strict, with defaults not allowed. I've expanded it, but only to a subset of the defaults. Your retrieve program, if it doesn't use STDOUT, still needs to display the output on screen. If I allowed the full defaults, the solution for every language would be 'takes input in a file' , 'gives output in a file', zero bytes. – Jared K Jul 24 '18 at 16:50 • @JaredK I don't think you quite get how this works. The store-program reads the input from STDIN and then stores a Python program that prints this input in f. Example: STORE is called with an input of abc. It then writes print('abc') to f. If you now call f (RETRIEVE), it prints abc to STDOUT. – ovs Jul 24 '18 at 17:32 • @JaredK I asked you in a comment whether it was allowed to for STORE to modify RETRIEVE. – ovs Jul 24 '18 at 17:33 # Batch, 16 bytes COPY CON A TYPE A  # Powershell - 4 Bytes Storage: ac  (alternative also sc) Retrieval gc  Edit: I just noticed the output is not allowed any user input... so it jumps from 4 to either 6 or 8 bytes Storage: ac f  (alternative also sc f) for the 8 byte version ac  (and specify f as path) for the 6 byte Version Retrieval gc f  # Rust, 136 bytes ## Store (84 bytes) use std::{fs::*,io::*};  ||{let mut v=vec![];stdin().read_to_end(&mut v);write("a",v)}  ## Retrieve (52 bytes) ||print!("{}",std::fs::read_to_string("a").unwrap())  ## Acknowledgments • You can save a byte by changing the import to use std::{io::*,fs::*} and then using write instead of std::fs::write. – Esolanging Fruit Jul 6 '18 at 16:42 • How about write("a",String::from_iter(stdin().chars()))? – Bergi Jul 8 '18 at 16:51 • @Bergi Nice. But chars triggers error[E0658]: use of unstable library feature 'io' in stable Rust. – Jakob Jul 8 '18 at 17:25 • Hm, it seems chars() is deprecated in favour of String::from_utf8(stdin().bytes()). (Also I used the nightly docs, not sure whether that's the culprit) – Bergi Jul 8 '18 at 17:44 • @Bergi I tried a few variations with bytes() or chars() but none of them were very short because the iterator item is wrapped in io::Result. – Esolanging Fruit Jul 9 '18 at 7:38 # Bash, 12 11 10 bytes ## store, 7 6 5 bytes cat ->f # no need for -, stdin is default cat >f # no need for space, > separates as well cat>f  ## retrieve, 5 bytes cat f  • No need for - in the store program. – Konrad Rudolph Jul 6 '18 at 10:54 • No need for the space between "cat" and ">", either! – psmears Jul 6 '18 at 14:11 • You should be able to do the same as in the zsh post for writing and use >f. I am not sure if <f is valid for reading, though. – allo Jul 10 '18 at 12:01 • @allo At least on Cygwin, >f works like echo '' > f (emptying the file if it exists, creating if it doesn't), while <f seems to be a no-op. – sundar - Reinstate Monica Jul 20 '18 at 12:04 # HP 49G RPL, 48 bytes To save: :2: A DUP PURGE STO, 26.5 bytes To restore: :2: A RCL, 21.5 bytes If we can leave in the backup battery, we get: # HP 49G RPL, 0 bytes To save: , 0 bytes To restore: , 0 bytes, since the HP 49G leaves the stack untouched across reboots. • The zero-byte solution should work for a variety of caluclators. I'll bust out my 42s when I get home. – SIGSTACKFAULT Jul 7 '18 at 23:15 • I think your zero-byte solution, and the others being run on calculators that reboot non-destructively, are failing to meet two parts of the question: "You will make two programs." What you've got is a single program that survives the reboot. And "Store reads from STDIN and then exits without error." Your program is still waiting for the user to press a key. Your program's stack and execution state are still mutable. I think that means it is still running, and hasn't exited. – Jared K Jul 9 '18 at 14:49 • @JaredK The question never stipulated that the two programs couldn't be identical. As for the exiting part: traditionally in RPL input to programs is given on the stack. That is the standard input. – Jason Jul 9 '18 at 15:36 • Would the stack survive a power cycle? Maybe a soft power-off via the calculator's buttons, but I'm guess not removing the battery. So maybe it depends what a power cycle is. – user Jul 9 '18 at 15:42 • @user No, stack doesn't survive soft (ON+C) or hard reset (ON+A+F) (distinct from soft-power off, Right Shift+ON), unlike storing in port 2, which is flash memory (and survives soft and hard reset). Since the TI-BASIC answer seemed to use that definition I included the stack answer for completeness. – Jason Jul 9 '18 at 15:44 # APL (APLX), 5 bytes Store: ⍞⍈1 Retrieve: ⍇1 ⍞ get line from stdin ⍈1 write to next available component of file number 1 ⍇1 read the first* last component of file number 1 * Documentation says first but experimentation shows last. # bash, 10 bytes (non-competing) touch$@
ls


Unix filenames can contain any character except NUL and /, and their names can be upto 255 bytes long so this will be able to store only strings up to that length (consider that a limitation of the storage medium), and that don't contain '/' in them. That's one reason this is non-competing, another is that this assumes the directory it's run on is empty (or that extraneous output from ls is allowed). I still wanted to post this because it just seemed a cool and non-obvious way to store information.

Another on a similar vein, which wouldn't have the same length and character limitations would be:

## 35 33 bytes

mkdir -p $@ find|sed '$!d;s/..//'


This allows the / character in the string, and supports many more characters (exactly how many depends on implementation).

(-2 bytes on this thanks to @Cows quack)

• IIRC, I believe that a group at Berkeley once created a database system back in the 1990s that stored table column data as filenames (up to 255 chars). I think the rows and tables were parent directories. – David R Tribble Jul 13 '18 at 18:28
• In your 35 byte answer, you can change the second statement to s/..//. The $ is not required because all other lines are deleted so this can only apply to the last line, and the ^ can be dropped because the substitution is only applied on the first match. – Kritixi Lithos Jul 20 '18 at 8:26 • @Cowsquack Done. Thanks for explaining why the change works, too. – sundar - Reinstate Monica Jul 20 '18 at 11:59 • You need to use "$@", not $@, to avoid getting burned by whitespace, *, ?, or ~ characters. – Anders Kaseorg Jul 21 '18 at 15:46 # Python 3, 56 bytes ## Store (33 bytes) open(*'aw').write(open(0).read())  ## Retrieve (23 bytes) print(open('a').read())  Prints with a trailing newline. • why not input() instead of open(0).read() and omit end= from print? – MoxieBall Jul 6 '18 at 14:33 • @MoxieBall Not sure about why input wasn't used, but omitting end= would result in a new line being added to the end of the string (i.e., not the original string) (maybe) – user52452 Jul 6 '18 at 15:03 • @NickA It looks like a newline gets printed in the question, anyways, so I don't think that should matter... – MoxieBall Jul 6 '18 at 15:14 • Have I gone crazy or does 23+33=56 (not 54)? Also why not use input()? – Artemis Fowl Jul 6 '18 at 21:23 • @ArtemisFowl Good catch. As for input, I assume that the string to persist may contain newlines. – Jakob Jul 6 '18 at 21:32 # Japt, 46 30 bytes -16 bytes thanks to Shaggy. One of the first times I've tried using Japt. The JS eval can be fidgety sometimes. Uses the browser's window.localStorage. ## Store (16 bytes) Oxlo¯lSÈSge.P=U  ## Retrieve (14 bytes) Oxlo¯lSÈSge.P  • +1 for being the first to use something other than standard file IO I like it. – Jared K Jul 6 '18 at 4:31 • Welcome to Japt! :) – Shaggy Jul 6 '18 at 7:14 • By the way, you can bypass setItem and getItem completely with localStorage.key. Set value, retrieve value – Shaggy Jul 6 '18 at 12:04 • @Shaggy Thanks! Yours also avoids the weirder control characters. – LegionMammal978 Jul 6 '18 at 13:01 ## Haskell, 46 bytes Store (26 bytes): getContents>>=writeFile"t"  Retrieve (20 bytes): readFile"t">>=putStr  # Ruby (26 Bytes) ## Set (16 Bytes) IO.write'a',gets  ## Get (10 Bytes) IO.read'a'  # MATLAB (30 Bytes) ## Set (22 Bytes) a=input('','s');save a  Can shave off 4 bytes by changing to input(''), but this will require input to be in single quotes: 'input string' ## Get (8 Bytes) load a;a  # C (GCC), 98 bytes ## Store (46 bytes) Input is via first command line argument. main(c,v)char**v;{fputs(v[1],fopen("a","w"));}  ## Retrieve (52 bytes) c,d;r(){for(d=open("a",0);read(d,&c,1);)putchar(c);}  ## Unportability • Requires that several pointer types fit in int. ## Acknowledgments • This requires a C implementation where int can hold a pointer, for the implicit declaration of int fopen() to work. (e.g. most 32-bit systems, or use gcc -m32 if you're on x86-64 to make a 32-bit executable.) And BTW, I tried using Linux's sendfile and copy_file_range(2) system calls, but they don't work to/from a TTY. – Peter Cordes Jul 9 '18 at 7:56 • Since you're writing functions, not programs, perhaps you could justify taking the input string as a function arg allowing fputs(fopen()), and read(open(),buf,-1). (The question now allows a command-line arg as input.) – Peter Cordes Jul 9 '18 at 7:57 • The Linux 'splice' function copies from a pipe to a file (and vice-versa). If stdin/out are pipes, then it will save a function call, at the expense of more parameters. – CSM Jul 9 '18 at 21:43 # APL (Dyalog Unicode), 18 bytes Store: ⍞⎕NPUT⎕A 1 Try it online! Retrieve: ⊃⎕NGET⎕A Try it online! ⍞ get line from stdin ⎕NPUT put it in a native file called ⎕A the uppercase alphabet 1 and overwrite if the file exists ⊃ the first part (the data, the next parts are encoding and line ending type) of ⎕NGET get the native file ⎕A the uppercase alphabet # R (27 bytes) ## store (21 bytes) x=readLines('stdin')  ## load (6 bytes) cat(x)  For this to work, the first script needs to be invoked with the command line option --save, and the second one with --restore (though in interactive mode this isn’t necessary: these options are the default). This could be shortened by 7 bytes were it not for the fact that a bug in R prevents the default argument of readLine from working in non-interactive mode. In interactive mode, it is not necessary, and the solution therefore only uses 20 bytes. • I think it would be much more efficient to use q directly, with the first program being x=scan(); q("y") and the second either x or cat(x) depending on how strict we want to be about how strings are printed. By the usual code golf rules you must also count command line arguments, so add bytes for --save and --restore (which my formulation doesn't need) – JDL Jul 6 '18 at 12:56 • @JDL scan doesn’t work for arbitrary contents, and scan(w='character') is longer than readLines(). q is unnecessary (but q('y') wouldn’t work, you have to spell it yes). I thought about just using x in the second program but this would violate the requirements, as far as I understand them. – Konrad Rudolph Jul 6 '18 at 13:53 • you can use scan(w=""), you don't need to spell out the type, scan will infer it from the type of argument specified. For me, q("y") works as a save-inducing quit but perhaps that depends on your version of R, and possibly whether you are using Rstudio or not. – JDL Jul 6 '18 at 14:45 • @JDL scan: Oh, neat, the documentation doesn’t mention this! Unfortunately scan will still perform some parsing so this won’t work with all input. Anyway, scan('stdin',w='') happens to be the exact same length as readLines('stdin'). q: R 3.4.4 says “Error in q("y") : unrecognized value of 'save'”. – Konrad Rudolph Jul 6 '18 at 14:57 • Ah, it's an Rstudio thing — I tried it in Rstudio and separately at the terminal and it only worked in Rstudio. – JDL Jul 9 '18 at 12:53 # Java (JDK 10), 204 Bytes Warning: Overwrites any preferences that any java programs have stored for your username! ### Store, 94 Bytes: interface S{static void main(String[]a){java.util.prefs.Preferences.userRoot().put("",a[0]);}}  Try it online! ### Retrieve 110 Bytes: interface R{static void main(String[]a){System.out.print(java.util.prefs.Preferences.userRoot().get("",""));}}  Try it online! java S foo java R foo  This works by taking input as an arg and storing it in the user preferences backing-store provided by java.util.prefs. It overwrites the user's root node to save one byte on naming a node. If you want to test it non-deestructively, either run it from a throwaway username or change the key from "" to a node name. • Good idea! Since you're using Java 10 you can shorten these by making them lambda expressions. Also if your byte count doesn't include z you should remove it from the programs and the TIO. Consider putting a warning at the top of the submission instead to warn people. For sure the TIO should have your 94- and 110-byte solutions. – Jakob Jul 9 '18 at 13:27 • Thanks! I made your suggested edits. I'm not certain but I don't think lambda expressions can fulfill the custom IO rules for this question. – Jared K Jul 9 '18 at 15:18 • D'oh. You're right, I forgot about that. – Jakob Jul 9 '18 at 15:21 # C#, 157 Bytes Set, 74 Bytes: class P{static void Main(string[]a){System.IO.File.WriteAllLines("a",a);}}  Get, 83 Bytes: class P{static void Main(){System.Console.Write(System.IO.File.ReadAllText("a"));}}  -1 Bytes thanks to VisualMelon -2 Bytes thanks to LiefdeWen • Remove that space after "a",, and I doubt this will be beaten :) – VisualMelon Jul 9 '18 at 17:25 • You can save another byte by using WriteAllLines and the second param a – LiefdeWen Jul 9 '18 at 17:47 # Perl 5, 4826 23 bytes ### Write, 20+1(-n) bytes -3 bytes thanks to mob open f,">>f";print f  I'm actually not certain about this one points-wise, but it meets the criteria. For past entries, only the cli options were counted, so that's what I'm going with. ### Read, 0+2 bytes perl -pe "" f  • Why did you score -ne with 1 (it should have an e too), but -pe with 2? You could use -E and say instead of print. – simbabque Jul 9 '18 at 12:02 • Thank you for letting me know about -E, I wasn't familiar with that one. As for why I didn't go with -ne, it is because for that one, I'm actually running from a file. So, it would look like perl -n w.pl If this goes against PCG community standards though, I can edit my answer accordingly. – Geoffrey H. Jul 9 '18 at 14:07 • No, it's fine. We add a malus for extra command line arguments, so it's fine. – simbabque Jul 9 '18 at 14:30 • ">>","f" --> ">>f" saves 3 char – mob Jul 10 '18 at 0:27 # Attache, 23 + 16 = 39 bytes Simply writes STDIN to file A, then reads file A. store.@: $A&FileWrite!AllInput[]


retrieve.@:

Echo!FileRead!$A  ## Testing C:\Users\conorob\Programming\attache (master -> origin) λ echo testing | attache store.@ C:\Users\conorob\Programming\attache (master -> origin) λ attache retrieve.@ testing  # Lua, 5753 51 bytes Store, 27 bytes io.open("x","w"):write(...)  Retrieve, 24 bytes print(io.open"x":read())  RUBY Store (24 bytes) File.write('a', ARGV[0])  Retrieve (16 bytes) p File.read('a')  • The question asks for storing input from STDIN, not the arguments – Ferrybig Jul 6 '18 at 12:38 • I've since edited to allow IO alternates including arguments. – Jared K Jul 6 '18 at 17:59 • File.write'a',gets and p File.read'a' are a bit shorter ;) – DarkWiiPlayer Jul 7 '18 at 15:08 # C (Unix/GNU), 23+23 = 46 bytes ## Store, 2723 bytes main(){system("dd>f");}  ## Retrieve, 2723 bytes main(){system("dd<f");}  This basically wraps jofel's answer into a C program. Note: The dd commands outputs some statistics to stderr, so you will see some additional output when you naively run it in the shell. However, since the challenge only says that the stored string must be presented on stdout, not stderr, I take it that it is allowed to have additional output on stderr... Anyway, suppressing stderr output is as easy as replacing dd with cat, increasing the byte counts of the two programs by one, each. • Depending on your compiler you may also be able to remove the int return type from main. In old ANSI C style int is the default return type. – Jakob Jul 9 '18 at 19:48 • @Jakob Ah, yes, of course. I relied conciously on the implicit declaration of system() and forgot about that of main() - ouch. Thanks for pointing that out :-) – cmaster Jul 9 '18 at 22:15 # PHP, 26+1 + 21 = 48 bytes Store.php: <?fputs(fopen(s,w),$argn);


Run with echo <input> | php -nF Store.php.

Retrieve.php:

<?=fgets(fopen(s,r));


Run with php -n Retrieve.php.

# C (gcc), 77 67 + 25 = 92 bytes

Compiles with only a few warnings on my gcc.

store.c

#include<stdio.h>
main(int c,char**v){fputs(v[1],fopen("f","w"));}


Can probably golf out the include, but I couldn't figure out how. Segfaults if you don't pass it anything, but whatever.

Peter Cordes: -1

main(){system("cat f");}

• int*f=fopen should work, i.e. lie to your compiler about the pointer type. But only if you compile for a 32-bit system (i.e. one where int can hold a pointer, like gcc -m32, or just gcc on a fully 32-bit system). You can also declare main as main(int c,char**v), or maybe int**v because you're not dereferencing. – Peter Cordes Jul 9 '18 at 7:22
• The main(int c,char**v) works. I also realized I can do fputs(v[1],fopen("f","w"), although it still needs stdio for some reason. – SIGSTACKFAULT Jul 9 '18 at 14:14
• It should work if you compile a 32-bit executable. For x86-64, the compiler will truncate the int return value to 32 bits, then sign-extend that as a pointer. If the returned FILE* is in the low 32 bits, it would work, but that's not the case on x86-64 Linux. – Peter Cordes Jul 9 '18 at 19:30
• If you are on a system where all pointers are equal in size (rather likely), you can avoid the include by declaring fopen manually. Going old school with the arguments saves some bytes too: *fopen();main(c,v)int**v;{fputs(v[1],fopen("f","w"));}. – gastropner Jul 24 '18 at 17:51

# Batch - 11 Bytes

%12>f
type f


The input is received as a command-line argument and persists (with the error message created upon execution attempt, since CMD attempts to execute the parameter) in f.

# Batch - 7 Bytes (non-competitive)

'>%1
dir


There are a plethora of invalid characters in a file name, so this wouldn't work for some strings, but this essentially saves an arbitrary character to the filename given by the parameter. To read it, it just lists all files in the directory, including our string.

• Your solution appears to output on STDOUT, which is valid. STDERR is just another option, not required. The quotes around the input don't stop it from competing. The only question is whether they should be counted in your byte count. I think not, since they aren't specific to the question. They seem like standard boilerplate for Batch to take a command line arg, which isn't so different from languages that need standard command line flags. Maybe someone else with Batch knowledge will chime in. For now leave them out of the byte count. Welcome to Code Golf! :) – Jared K Jul 24 '18 at 16:41