Quote-Safe Quines

17

1

Your task is simple: write a program (or function) that takes no input and outputs (or returns) its source code. The catch is that when the program is wrapped in "quotes" (Unicode character 34), it should again output its (now quoted) source code.

Standard rules for quines apply. This is , so the shortest program (in bytes) wins.

Esolanging Fruit

Posted 2017-01-27T05:03:17.950

Reputation: 13 542

8@ATaco think creatively. The code in quotes normally isn't executed, but when the entire program is surrounded with quotes those sections are executed. – Pavel – 2017-01-27T05:11:16.650

1Hmm, Good point. – ATaco – 2017-01-27T05:12:04.793

This might work with BF on implementations that support !... – Esolanging Fruit – 2017-01-27T05:22:21.023

1Must you use "? Some languages support two or three quote characters. – Neil – 2017-01-27T08:48:27.293

must the output include the quotes the second time through? – Golden Ratio – 2017-01-27T09:29:21.320

In my answer, I provided a 1 byte solution. But, I am unsure if it is considered cheating. By definition it satisfies everything I have read about Quines and what is asked in this question, but for some reason I do not feel right about it.

– tkellehe – 2017-01-27T16:05:06.823

1

@tkellehe Meta: What counts as a proper quine? As far as I understand your 1-byte quine, it violates the code/data requirement formulated in the highest voted post.

– Laikoni – 2017-01-27T16:20:52.170

@Laikoni, thank you! That makes more sense. I knew it didn't feel right:) – tkellehe – 2017-01-27T16:26:48.333

How does this challenge work in a language that works as follows: the program is written in a character set which contains quotes, and the interpreter detects it as such; however, if you add quotes around the program (in that character set), the interpreter treats the octets that make up those quotes as a character set selection directive, and reinterprets the whole file in a character set that doesn't contain quotes? – None – 2017-01-28T00:07:38.890

@ais523 If the unquoted quine was written in character set A, then prepending and appending bits representing quotes in character set A to the program should produce the desired behavior, even if the interpreter interprets it with a different character set. – Esolanging Fruit – 2017-01-28T06:09:27.533

Answers

4

Noodel, 9 7 bytes

This version works the same way as the other, just that I forgot that Noodel has a way to run a block of code once and I made the language...

Ḷ1ḥ-Ð1ḥ@€

ḷḥ-Ðḥ@ḅ

Try it:)


How it Works

ḷḥ-Ðḥ@ḅ # Single statement that builds itself as a string.
ḷ       # Loop the following block of code unconditionally.
 ḥ-     # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack.
   Ð    # Push the stack as an array to stdout (since is an array it is done by reference).
    ḥ@  # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack.
      ḅ # Break out of the given loop. (The stack is now ["ḷ", "ḥ-Ðḥ@ḅ"]).

        # The top of the stack is popped off and displayed which modifies the array to produce {["ḷ"], "ḥ-Ðḥ@ḅ"} in stdout.

Quote-Safety

Placing the " character before and after the program works because Noodel has a set of of characters dedicated to what I call printables. These are immediately parsed as string literals when placed by themselves and allow for easily printing something to the screen. So unlike most languages, Noodel sees the normal ASCII set that is considered print worthy as direct string literals (except for space and line feed) therein quoting the code is merely seen as pushing on strings.

"ḷḥ-Ðḥ@ḅ"

"         # Pushes on the string literal "\"" onto the stack.

 ḷḥ-Ðḥ@ḅ  # Same execution as before, simply builds the Quine for this loop.
 ḷ        # Loop the following block of code unconditionally.
  ḥ-      # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack.
    Ð     # Push the stack as an array to stdout (since is an array it is done by reference).
     ḥ@   # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack.
       ḅ  # Break out of the given loop. (The stack is now ["\"", "ḷ", "ḥ-Ðḥ@ḅ"]).

        " # Pushes on the string literal "\"" onto the stack.

          # The top of the stack is popped off and displayed which modifies the array to produce {["\"", "ḷ", "ḥ-Ðḥ@ḅ"], "\""} in stdout.

"Try it:)"


Snippets

<div id="noodel" code='ḷḥ-Ðḥ@ḅ' input="" cols="10" rows="1"></div>
<script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>

<div id="noodel" code='"ḷḥ-Ðḥ@ḅ"' input="" cols="10" rows="1"></div>
<script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>

tkellehe

Posted 2017-01-27T05:03:17.950

Reputation: 605

I don't think using e is valid. The question doesn't ask for the character encoded as the byte 34, but for the Unicode character 34. No matter which encoding you use, there is only one: " – Dennis – 2017-01-27T16:39:32.643

@Dennis, I am guessing what you are saying is the reference to the Unicode character 34 was just to ensure the everyone was using the same "? (Sorry, just trying to make sure I understand what you are saying) Also, should I remove all of the text in the answer referring to using e? – tkellehe – 2017-01-27T16:46:29.563

1Yes, there are thousands of encodings, but only one Unicode character set. Since " works, I'd just remove the discussion and simply use ". – Dennis – 2017-01-27T17:14:35.720

11

Python 2 3, 181 152 130 124 122 bytes

""" """>" "or exec("oct=0");p='"""" """>" "or exec("oct=0");p=%r;a=oct==0;print(p[a:~a]%%p)#".';a=oct==0;print(p[a:~a]%p)#

Try it online! The TIO comes with a header and footer that automatically test the validity of the quine. You can clear them to just run the quine.

This code works by using the triple-quoted strings in Python. """ """ is equal to ' ' and """" """ is equal to '" '.

The code does use exec, but not for the "non-quiney" way of executing data as code, just for setting a variable from inside an expression. The exec is properly encoded in the data, too.

The first statement compares the string, possibly with a quote prepended, to " ", and sets the variable oct accordingly. (The variable could've been any short builtin.)

The rest of the code then implements the traditional Python quine using %r string formatting, with some additional code that strips the extra quotes if oct is unchanged.

An alternative version using the "cheaty" exec comes in at 126 bytes with less repeated code:

""" """>" "and exec("oct=0");s='"""" """>" "and exec("oct=0");s=%r;p=%r;exec(p)#".';p='a=oct!=0;print(s[a:~a]%(s,p))';exec(p)#

Try it online!

PurkkaKoodari

Posted 2017-01-27T05:03:17.950

Reputation: 16 699

7

V, 27, 23 bytes

éPñi"éP241"qpá"lxx|xÿ

Try it online!

Since this contains some unprintable characters, here is a readable version:

éPñi"éP<C-v>241<esc>"qpá"lxx|xÿ

and here is a hexdump:

00000000: e950 f169 22e9 5016 3234 311b 2271 70e1  .P.i".P.241."qp.
00000010: 226c 7878 7c78 ff                        "lxx|x.

So the very first thing we need to do is to determine if the first character is a quote. éP inserts a 'P' character, but "éP is a NOOP. After that, we run a slight modification on the standard extendable quine, which is:

ñi<C-v>241<esc>"qpÿ

We're going to do it slightly differently though. First off we need to insert the starting "éP" text. So we do

ñ                        " Start recording into register 'q'
 i                       " Enter insert mode
  "éP<C-v>241<esc>       " Enter the following text: '"éPñ'
                  "qp    " Paste the text in register 'q'
                     á"  " Append a '"'

Here is where the branching happens. The text currently in the buffer is

"éPñi"éP<C-v>241<esc>"qpá"P
Cursor is here ----------^

Unless we wrapped it in quotes, in that case the 'P' would never have been inserted, and the buffer is:

"éPñi"éP<C-v>241<esc>"qpá"
Cursor is here ----------^

Since we are still recording, we can do whatever we want here, and it will get added to the buffer when the "qp happens. So from here it's pretty easy to conditionally delete the quotes:

l           " Move one character to the right. If there is no character to the right, 
            " then this is effectively a "break" statement, stopping playback of the recording
 xx         " Delete two characters (the '"P')
   |        " Move to the first character on this line
    x       " Delete one character
     ÿ      " End the program

James

Posted 2017-01-27T05:03:17.950

Reputation: 54 537

7

StandardML, 182 176 108 bytes

";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))

Unquoted version: Try it on codingground.
Quoted version: Try it on codingground.

Note that the output looks something like this

> val it = "{some string}" : string
> val it = "{some string}" : string
{output to stdout}> val it = fn : string -> unit

because the code is interpreted declaration by declaration (each ; ends a declaration) and shows the value and type of each declaration.


Background

In SML there is a quine of the form <code>"<code in quotes>":

str(chr 34);(fn x=>print(x^it^x^it))"str(chr 34);(fn x=>print(x^it^x^it))" 

and one in the form "<code in quotes>"<code>:

";str(chr 34)^it;print(it^it)";str(chr 34)^it;print(it^it)

Both rely on the fact that the <code>-part contains no quotes and can thus be quoted with out the need for escaping anything, the " needed to output the quine are given by str(chr 34).

They also heavily rely on the implicit identifier it which is used when no explicit identifier is given in a declaration.

In the first quine str(chr 34); binds it to the string containing ", fn x=> starts an anonymous function taking one argument x, then concatenates x^it^x^it and prints the resulting string. This anonymous function is directly applied to a string containing the program code, so the concatenation x^it^x^it yields <code>"<code>".

The second quine starts with just the program code as string ";str(chr 34)^it;print(it^it)"; which is bound to it. Then str(chr 34)^it; concatenates a quote to the start of the string and as again no explicit identifier is given, the resulting string "<code> is bound to it. Finally print(it^it) concatenates the string with itself yielding "<code>"<code> which is then printed.


Explanation

Edit: No longer up to date with the 108-byte version, however one might understand it too after reading this explanation.

The quote-safe quine combines both of the above approaches and is itself of the form "<code>"<code>. Putting this in again in quotes yields ""<code>"<code>", so we get an empty string and then a quine of the other form.

That means the program is either given its own source in the form "<code> by the identifier it, or it is just " and we are given our own source <code> as argument and must thus be a function which handles such an argument.

(if size it>1then(print(it^it);fn _=>())else fn x=>print(it^it^x^it^x^it))

To identify in which case we are, we check whether the size of it is larger than 1. If not then it is " and we are in the second case, so the else-part returns an anonymous function fn x=>print(it^it^x^it^x^it) which is then called because its followed by source as string. Note the leading it^it^ which is needed for the empty string at the start of the of the program.

If size it is larger than 1 we are in the then-part and just perform print(it^it), right? Not quite, because I neglected to tell you that SML is strongly typed which means that a conditional if <cond> then <exp_1> else <exp_2> must always have the same type which again means that the expressions <exp_1> and <exp_2> need to have the same type. We already know the type of the else part: An anonymous function which takes a string and then calls print has type string -> <return type of print>, and print has type string -> unit (unit is in some way similar to void in other languages), so the resulting type is again string -> unit.

So if the then part was just print(it^it) which has type unit, we would get a type mismatch error. So how about fn _=>print(it^it)? (_ is a wildcard for an argument that is not used) This anonymous function on its own has type 'a -> unit where 'a stands for an arbitrary type, so in the context of our conditional which enforces a string -> unit type this would work. (The type variable 'a gets instantiated with type string.) However, in this case we would not print anything as the anonymous function is never called! Remember, when we go in the then-part the overall code is "<code>"<code>, so the <code>-part evaluates to a function but, as nothing comes after it, its not called.

Instead we use a sequentialisation which has the form (<exp_1>; ...; <exp_n>) where <exp_1> to <exp_n-1> may have arbitrary types and the type of <exp_n> provides the type of the whole sequentialisation. From a functional point of view the values of <exp_1> to <exp_n-1> are simply discarded, however SML also supports imperative constructs so the expressions may have side effects. In short, we take (print(it^it);print) as the then-part, thus printing first and then returning the function print which has the correct type.

Laikoni

Posted 2017-01-27T05:03:17.950

Reputation: 23 676

3

JavaScript (ES6), 239 237 bytes

Set=``;eval(";a='Set=``;eval(~;a=1;S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);~)';S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);")

Take care to try each version in a fresh environment (e.g., a new browser tab)

There has got to be at least one way to simplify this...

ETHproductions

Posted 2017-01-27T05:03:17.950

Reputation: 47 880

1I suppose you could use an array for the replaces like so: [x="replace"]. Might break things though, I'm not very experienced with quines... – Luke – 2017-01-27T17:17:02.983