Lipogram "quine"

26

1

Task

  1. Take a single Unicode character as input.
  2. Output a program in the same language that also obeys this specification, but which does not contain the input character.
  3. If your program is run with input a, and then the output program is then run with input b, then the program it outputs is ALLOWED to contain character a. However, b is still not allowed to appear in this program. In other words, only the input into the most recent incarnation of the program is forbidden to appear.
  4. Regardless of what the title may say, standard quine rules apply.

Shortest program wins. Program must be at least one byte long.

Example

If the program is ABCD. (# is an comment)

> slangi "ABCD"
A
EBCD          # "FBCD" "JGGJ" "UGDKJGDJK" are all OK
> slangi "EBCD"
C
ABGD          # "EBGD" "UIHDAIUTD" are all OK
> slangi "ABGD"
B
AFCD
> slangi "AFCD"
Z
ABCD

Where slangi is an interpreter for a fictitious language.

Akangka

Posted 2016-01-03T05:03:01.723

Reputation: 1 859

Wouldn't this challenge less verbose languages? Several use words for instruction names, so it would be very difficult and/or impossible to avoid characters such as e. – LegionMammal978 – 2016-01-03T11:52:29.560

2It's very difficult to write in English without e, yet Gadsby does it. – Akangka – 2016-01-03T12:36:48.907

I'm assuming no quine functions? – Mama Fun Roll – 2016-01-04T05:11:36.783

Answers

24

CJam, 45 41 38 35 bytes

{`"OX$_?"+_l&{{H)+`}/"\He,}":)}&}_~

If the input character is none of the characters "$&)+,/:?HOX\_`el{}, this program prints the following, slightly modified version of itself. Try it online!

{`"OX$_?"+_l&{{H)+`}/"\He,}":)}&}OX$_?

Otherwise, the program prints the following, obfuscated version of the modification. Try it online!

''r'4'a'j'6'q'Q'4'='q'~'8'''Z';'='r''A'4'n'Z'w'>''4'L';''8''a'j'6'q'Q]If-~

Note that some of the characters are unprintable. Try it online!

How it works

{`"OX$_?"+_l&{{H)+`}/"\He,}":)}&}_~

{                               }    Define a code block.
                                 _~  Push a copy and execute the copy.
 `                                   Push a string representation of the block.
  "OX$_?"                            Push that string.
         +_                          Concatenate and push a copy.
           l&                        Intersect the copy with the input.
             {                }&     If the intersection is non-empty:
              {    }/                  For each character of the concat. strings:
               H)                        Push 18.
                 +                       Add it to the character.
                  `                      Inspect; turn 'c into "'c".
                     "He,}"            Push that string.
                           :)          Increment each char. Pushes "If-~"

In the first possible output program, we avoid using ~ to be able to use it in the other program. Therefore, instead of _~, the modified program ends with OX$_?, which works as follows.

O        Push "" (falsy).
 X$      Push a copy of the code block.
   _     Push yet another copy.
    ?    Ternary if; since "" is falsy, execute the second copy.

Finally, in the remaining output program,

''r'4'a'j'6'q'Q'4'='q'~'8'''Z';'='r''A'4'n'Z'w'>''4'L';''8''a'j'6'q'Q]

wraps all those characters in an array, therefore pushing the following string.

"'4aj6qQ4=q~8'Z;=r'104nZw>'4L;'8'j6qQ"

If- subtracts 18 from each character code, pushing the string

"{`\"OX$_?\"+_l&{{H)+`}/\"\He,}\":)}&}OX$_?"

which ~ the evaluates.

Dennis

Posted 2016-01-03T05:03:01.723

Reputation: 196 637

18

JavaScript (ES6), 356 340 327 308 303 263

Now using Function`...``` for the second program:

f=(b=y=>[for(x of`f=${f};f()`)x.charCodeAt().toString(y).toUpperCase()])=>alert([`eval('\\${b(8).join('\\')}')`,`eval(String.fromCharCode(${b(10).map(x=>'+9-8'.repeat(x))}))`,'Function`\\x'+b(16).join('\\x')+'```'][1+"0e1v2a3l4(5'6'7)\\".indexOf(prompt())%2]);f()

The function packs itself into one of three possible programs:

  1. The first program calls eval on a string literal containing the function's code with each character escaped as an octal value.

    eval('\146\165...')
  2. The second program redirects the browser to a javascript: URL containing the function's code with each character URL encoded. This is the only way I could think to evaluate code without using parentheses. It also escapes the letters in 'eval'.

    window["\x6coc\x61tion"]["hr\x65f"]="j\x61\x76\x61script:%66%75..."
  3. The last program is painfully long. It builds the function's code by adding one (+9-8) at a time to get each character code. This is to avoid using the octal digits.

    eval(String.fromCharCode(+9-8+9-8+9-8+9-8...))

The correct program is indexed by searching a carefully constructed string for the input character:

[`program_1`,`program_3`,`program_2`][1+"0e1v2a3l4(5'6'7)\\".indexOf(prompt())%2]

Here's an ungolfed, untested version. It might not work because of newlines in the source.

function f() {
    // convert source code of current function to bytes
    var bytes = Array.map(f + 'f()', x => x.charCodeAt());

    // pack this function's code in one of three possible programs,
    // depending on the input
    var input = prompt();

    // PROGRAM 1 - only contains characters: eval(')01234567\
    // eval('\146\165...')
    var source = "eval('\\" + bytes.map(x => x.toString(8)).join('\\') + "')";

    // PROGRAM 2 - doesn't contain characters: eval('')
    // window["\x6coc\x61tion"]["hr\x65f"]="j\x61\x76\x61script:%66%75..."
    // -> window["location"]["href"] = "javascript:..."
    if ("eval(')".includes(input)) {
        source = 'window["\\x6coc\\x61tion"]["hr\\x65f"]="j\\x61\\x76\\x61script:%';
        source += bytes.map(x => x.toString(16).toUpperCase()).join('%') + '"';
    }

    // PROGRAM 3 - doesn't contain characters: 01234567\
    // eval(String.fromCharCode(+9-8+9-8+9-8+9-8...))
    if ('01234567\\'.includes(input)) {
        source = "eval(String.fromCharCode(";
        source += bytes.map(x => '+9-8'.repeat(x)).join(',') + '))';
    }

    console.log(source);
}
f()

grc

Posted 2016-01-03T05:03:01.723

Reputation: 18 565

function f(){ ... };f() can be (f=_=>{ ... })(). Here's an example: http://www.es6fiddle.net/iiz2nq0l/ – Ismael Miguel – 2016-01-03T21:48:15.970

Even better: f=(_=prompt())=>...;f(). Input is stored as _. – Mama Fun Roll – 2016-01-03T23:29:41.070

Also, no need for console.log, function output is fine. – Mama Fun Roll – 2016-01-03T23:29:58.643

Won't using Function`[code]`.call``; work for you, instead of redirecting? Here is a working example: http://www.es6fiddle.net/ij023v49/ (See? No evil()! Erm, I mean eval()...)

– Ismael Miguel – 2016-01-04T14:23:18.517

Well, you have learned something today. Just be aware that the this object will be that empty template string. It relies on the Function constructor, which allows you to create a function, instead of running eval(). The function will have the code contained within the first parameter. I use it a lot to get the real window, using Function('return this')(). Since you can't use (), I've abused a little of ES6's kindness to try to spit an usable function that you can run without (). For that, you need the .call() method, which calls the function with a new this object. – Ismael Miguel – 2016-01-04T15:32:15.017

@IsmaelMiguel can you use:

Function`return 1```
 – Dom Hastings  – 2016-01-05T09:31:29.723

@DomHastings You can use that, but it won't execute. The .call`` is to make sure that it is called. Without it, you could do A=Function`return 1`,A, with no byte savings. – Ismael Miguel – 2016-01-05T11:00:17.033

@IsmaelMiguel but it does call the function (as if with an empty param)? Apologies if I missed the need to use call, but if you aren't using this in the code that shouldn't matter right? I mostly wanted to share because I thought that three backticks in a row would be a syntax error and was surprised when they didn't! I did also wonder if using template string eval would be shorter too, but since you can't return anything from it probably not... – Dom Hastings – 2016-01-05T11:09:46.320

@DomHastings Now I see what you did there! That is magnificent! That is way cooler than my code! That is really quite a nice saving! The reason why I went this way is because on the 2nd function, you can't use any of the chars eval('). grc found a way to execute code by redirecting to a javascript: url. Since the Function prototype doesnt contain any of the forbiden chars, I though he could use that to run his code. But you... You smashed it! Well done! Really good idea! I am surprised that it works as well! – Ismael Miguel – 2016-01-05T13:46:02.213

Thanks. I've improved it, but It's a shame you can't use octal encoding inside string templates... – grc – 2016-01-05T14:30:22.893