26
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – LegionMammal978 Jan 3 '16 at 11:52
  • 2
    \$\begingroup\$ It's very difficult to write in English without e, yet Gadsby does it. \$\endgroup\$ – Akangka Jan 3 '16 at 12:36
  • \$\begingroup\$ I'm assuming no quine functions? \$\endgroup\$ – Mama Fun Roll Jan 4 '16 at 5:11
24
\$\begingroup\$

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.

\$\endgroup\$
18
\$\begingroup\$

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()
\$\endgroup\$
  • \$\begingroup\$ function f(){ ... };f() can be (f=_=>{ ... })(). Here's an example: es6fiddle.net/iiz2nq0l \$\endgroup\$ – Ismael Miguel Jan 3 '16 at 21:48
  • \$\begingroup\$ Even better: f=(_=prompt())=>...;f(). Input is stored as _. \$\endgroup\$ – Mama Fun Roll Jan 3 '16 at 23:29
  • \$\begingroup\$ Also, no need for console.log, function output is fine. \$\endgroup\$ – Mama Fun Roll Jan 3 '16 at 23:29
  • \$\begingroup\$ Won't using Function`[code]`.call``; work for you, instead of redirecting? Here is a working example: es6fiddle.net/ij023v49 (See? No evil()! Erm, I mean eval()...) \$\endgroup\$ – Ismael Miguel Jan 4 '16 at 14:23
  • \$\begingroup\$ 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. \$\endgroup\$ – Ismael Miguel Jan 4 '16 at 15:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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