Session-Saving Quine

12

Inspired by this question.

Create a program that prompts the user to store some data, and when the program is quitting, spit out the program itself, except the session data changed.

The user then open the newly generated program, and can recall the data from the previous program.

Commands

  • KEY VALUE: sets session variable KEY to VALUE
  • *: clear all data
  • ! KEY: delete KEY
  • ? KEY: query KEY (if not exist: print nothing and move on)
  • otherwise, quit the program

Neither key or value cannot contain any spaces. The newly generated program's filename must identify the version of the program, you can use dates or counters.

Example interaction:

 name test                    store name = test
                              data is now { name: test }
 0 1                          data is now { name: test, 0: 1 }
 ? name                       output: test
 ! 0                          delete 0
                              data is now { name: test }
 hello good world             data is now { name: test, hello: good }
                              the extra word "world" is ignored
 egiwiwegiuwe                 the "otherwise" case: quit program

The user opens the newly generated program

 ? name                       output: test
 name retest                  data is now { name: retest }
 *                            clear
                              data is now { }

Sample implementation: https://gist.github.com/1128876

Rules

  • You do not need to preserve comments or insignificant whitespaces in the quined program: just preserve the functionality and the data
  • You cannot use any external storage.
  • No cheating quines, like any other quine problems.
  • Shortest code wins.

Ming-Tang

Posted 2011-08-06T01:20:12.520

Reputation: 5 383

This reminds me of the time that I wrote a view in SQL Server that acted just like a table by using INSERT/UPDATE/DELETE triggers and storing the data in the view itself as SELECT 1 AS ID, NAME AS BLAH UNION... – mellamokb – 2011-08-06T05:10:11.493

What's considered a cheating quine? – Casey Chu – 2011-08-08T07:58:36.097

Casey, reading own source code, usually. – Joey – 2011-08-08T08:21:40.047

Ah. My JS solution comes close to doing that, whoops. Oh well, since the spec isn't that clear about that, I'll leave it up at the risk of being downvoted. – Casey Chu – 2011-08-08T08:29:51.350

Answers

1

Ruby 1.9, 159 156

This program generates files named "1", "2", "3" and so on.

b={}
I=1
eval T="loop{c,d=gets.split
c==?*?b={}:d ?c==?!?b.delete(d):c==???puts(b[d]):b[c]=d :break}
open(I.to_s,?w){|f|f<<'b=%p
I=%d
eval T=%p'%[b,I+1,T]}"

Lowjacker

Posted 2011-08-06T01:20:12.520

Reputation: 4 466

1

D (419 chars)

enum c=q{string[string] m;import std.stdio;import std.array;void main(){foreach(string s;lines(stdin)){auto a=s.split;if(!a.length)goto e;switch(a[0]){case "*":m.clear;break;case "!":m.remove(a[1]);break;case "?":writeln(m.get(a[1],""));break;default:if(a.length<2){goto e;}m[a[0]]=a[1];}stdout.flush;}e:write("static this(){");foreach(i,v;m)writef("m[`%s`]=`%s`;",i,v);write("}enum c=q{",c,"};mixin(c);");}};mixin(c);

formatted:

enum c=q{
    string[string] m;
    import std.stdio;
    import std.array;
    void main(){
        foreach(string s;lines(stdin)){
            auto a=s.split;
            if(!a.length)goto e;
            switch(a[0]){
                case "*":m.clear;break;
                case "!":m.remove(a[1]);break;
                case "?":writeln(m.get(a[1],""));break;
                default:if(a.length<2){goto e;}m[a[0]]=a[1];
            }
            stdout.flush;
        }
        e:write("static this(){");
        foreach(i,v;m)writef("m[`%s`]=`%s`;",i,v);
        write("}enum c=q{",c,"};mixin(c);");
    }
};mixin(c);

variant of my D quine

the * command relies on m.clear; to work correctly which it doesn't in dmd 2.52 (bug in the compiler)

the need for stdout.flush; depends whether auto flush is enabled (it isn't on my machine)

ratchet freak

Posted 2011-08-06T01:20:12.520

Reputation: 1 334

1

JavaScript, 245

(function(o,N){while(a=prompt()){a=a.split(' ')
b=a[0]
c=a[1]
if(b=='*')o={}
else if(b=='?'){if(o[c]!=N)alert(o[c])}
else if(b=='!')delete o[a[1]]
else if(c!=N)o[b]=c
else break}alert('('+arguments.callee+')('+JSON.stringify(o)+')')}({}))

Casey Chu

Posted 2011-08-06T01:20:12.520

Reputation: 1 661