18
\$\begingroup\$

In my time on PPCG, I've noticed that quine problems and polyglot problems are quite popular. Also, meta-solutions to problems, that is, scripts which generate a program which is the solution to a problem, tend to get a lot of positive feedback from the community. Therefore, I have created this challenge, which implements these three ideas.

Your task then, reader and enthusiast, is to create as short as possible a script which can run in two languages A and B to generate quines for A and B. When your program is run in language A, it should generate a program that is a quine in language B but not in language A and vice versa. The languages A and B can be different version of the same language, provided you keep in mind that the generated quines should only work in one of the versions.

Keep in mind that the standard loopholes should be considered closed and only proper quines are allowed.

Good luck, fewest characters wins!

\$\endgroup\$
6
  • 1
    \$\begingroup\$ A quine is basically a meta-meta-meta-meta-meta-meta-meta-etc. program anyways :) \$\endgroup\$ Commented Nov 8, 2016 at 4:50
  • \$\begingroup\$ How to count bytes if the two languages use different character encodings? You should probably score in characters rather than bytes \$\endgroup\$
    – Luis Mendo
    Commented Nov 8, 2016 at 8:13
  • 1
    \$\begingroup\$ If I run the quine in language A to generate a quine for language B, should that be runnable in A? \$\endgroup\$
    – corvus_192
    Commented Nov 8, 2016 at 8:33
  • 2
    \$\begingroup\$ @LuisMendo When writing a polyglot for languages with different encodings, I'd assume that they both receive the same byte stream (not different encodings of the same characters). \$\endgroup\$ Commented Nov 8, 2016 at 14:11
  • 1
    \$\begingroup\$ @Pavel I actually wrote a similar challenge here, but it got closed as a duplicate. \$\endgroup\$
    – Oliver Ni
    Commented Nov 11, 2016 at 4:22

9 Answers 9

8
\$\begingroup\$

CJam / Fission, 22 bytes

"'!+OR'")5-"{'_'~}_~";

Try it in CJam. Try it in Fission.

In CJam, this prints the standard Fission quine:

'!+OR"

Try the Fission quine.

In Fission, this prints a "-less variant of the standard CJam quine:

{'_'~}_~

Try the CJam quine.

This also works for 22 bytes (printing the same quines):

"& *NQ!":)R"{'_'~}_~";

Explanation

In CJam:

"'!+OR'"    e# Push this string.
)           e# Pull off the last character.
5-          e# Subtract 5, turning ' into ".
"{'_'~}_~"  e# Push this string.
;           e# And discard it again.

So at the end of the program, the stack contains the string "'!+OR" and the character ", both of which are implicitly printed.

In Fission, program flow starts at the R with a right-going atom. '" just changes the atoms mass, ), 5 and - are ignored for various reasons. Then the atom enters print mode at the " and prints {'_'~}_~. ; destroys the atom and terminates the program.

\$\endgroup\$
2
  • 4
    \$\begingroup\$ +1 for emoticon {'_'~} \$\endgroup\$
    – betseg
    Commented Nov 8, 2016 at 14:26
  • 5
    \$\begingroup\$ destroys the atom I'd rather not be anywhere near when that happens \$\endgroup\$
    – Luis Mendo
    Commented Nov 8, 2016 at 16:20
6
\$\begingroup\$

Clojure / Common Lisp, 274 bytes

(defmacro t []"((fn [s] (print (list s (list (quote quote) s)))) (quote (fn [s] (print (list s (list (quote quote) s))))))")(if '()(print(let[s clojure.string/replace](.toUpperCase(s(s(s(s(s(t)"fn""lambda")"[s]""(s)")"(quote ""'")"e)""e")")))))""))))"))))(eval '(princ(t))))

Some spaces added for readability

(defmacro t []"((fn [s] (print (list s (list (quote quote) s))))
     (quote (fn [s] (print (list s (list (quote quote) s))))))")
(if '()(print(let[s clojure.string/replace](.toUpperCase
    (s(s(s(s(s(t)"fn""lambda")"[s]""(s)")"(quote ""'")"e)""e")")))))""))))"))))
    (eval '(princ(t))))

Basically defines a macro which returns a quine in Clojure. Clojure requires parameters for macro definition provided as vector ([]) whereas Common Lisp (thankfully) just ignores it. After that we differ 2 languages by evaluating '() which equals to nil and thus falsey in Common Lisp and is true in Clojure. Then we do string manipulations using Clojure which Common Lisp doesn't even try to evaluate as it goes in another if branch. Clojure on the other hand tries to check if another branch is at least correct before executing so had to use eval there to both be correct in Clojure and output correct string in Common Lisp.

Note: just returning two different string might probably be shorter but then it won't be different to a polyglot challenges about outputing different strings in different languages. ¯\_(ツ)_/¯

Clojure original source run: https://ideone.com/SiQhPf

Common Lisp original source run: https://ideone.com/huLcty

Clojure output : ((LAMBDA (S) (PRINT (LIST S (LIST 'QUOTE S)))) '(LAMBDA (S) (PRINT (LIST S (LIST 'QUOTE S)))))

Common Lisp output : ((fn [s] (print (list s (list (quote quote) s)))) (quote (fn [s] (print (list s (list (quote quote) s))))))

Clojure output run in Common Lisp: https://ideone.com/T1DF7H

Vice versa: https://ideone.com/Fezayq

\$\endgroup\$
5
+50
\$\begingroup\$

CJam 0.6.6 dev / GolfScript, 15 14 12 bytes

"0$p"0$~a:n;

Thanks to @jimmy23013 for golfing off 2 bytes!

Rest to be updated.

Verification

Since the submission involves significant whitespace, it's best to compare hexdumps.

$ xxd -g 1 mpquine
0000000: 22 60 30 24 7e 22 30 24 7e 4e 4d 3a 6e 3b        "`0$~"0$~NM:n;
$
$ cjam mpquine | tee quine.gs | xxd -g 1
0000000: 22 60 30 24 7e 22 60 30 24 7e 0a                 "`0$~"`0$~.
$ golfscript quine.gs | xxd -g 1
0000000: 22 60 30 24 7e 22 60 30 24 7e 0a                 "`0$~"`0$~.
$ cjam quine.gs | xxd -g 1
0000000: 22 60 30 24 7e 22 60 30 24 7e                    "`0$~"`0$~
$
$ golfscript mpquine | tee quine.cjam | xxd -g 1
0000000: 22 60 30 24 7e 22 60 30 24 7e                    "`0$~"`0$~
$ cjam quine.cjam | xxd -g 1
0000000: 22 60 30 24 7e 22 60 30 24 7e                    "`0$~"`0$~
$ golfscript quine.cjam | xxd -g 1
0000000: 22 60 30 24 7e 22 60 30 24 7e 0a                 "`0$~"`0$~.

CJam

CJam prints "`0$~"0$~ and a trailing linefeed. Try it online!

The generated program prints "`0$~"0$~ with the trailing linefeed in GolfScript (Try it online!), but without the linefeed in CJam (Try it online!).

How the metaquine works

"`0$~"         e# Push that string on the stack.
      0$~      e# Push a copy and evaluate it:
               e#   `     Inspect the string, pushing "\"`0$~\"".
               e#    0$   Push a copy.
               e#      ~  Evaluate, pushing "`0$~".
               e# Both "\"`0$~\"" and "`0$~" are now on the stack.
         NM    e# Push "\n" and "".
           :n; e# Map print over the elements of "" (none) and pop the result.
               e# "\"`0$~\"", "`0$~", and "\n" are now on the stack, and the
               e# characters they represent will be printed implicitly.

How the quine works

"`0$~"          # Push that string on the stack.
      0$~       # As in CJam.
         <LF>   # Does nothing.
                # "\"`0$~\"" and "`0$~" are now on the stack, and the characters
                # they represent will be printed implicitly, plus a linefeed.

Unlike GolfScript, CJam doesn't print a trailing linefeed by default, so this is not a quine in CJam.

GolfScript

GolfScript prints "`0$~"0$~, without trailing whitespace. Try it online!

The generated program prints "`0$~"0$~ without trailing whitespace in CJam (Try it online!), but GolfScript appends a linefeed (Try it online!).

How the metaquine works

"`0$~"0$~       # As in CJam.
         NM     # Unrecognized token. Does nothing.
           :n   # Store the top of the stack – "`0$~" – in the variable n. n holds
                # "\n" by default. When the program finishes, the interpreter
                # prints n implicitly, usually resulting in a trailing linefeed.
                # By redefining n, it will print "0$~" instead.
             ;  # Pop the string from the stack so it won't be printed twice.

How the quine works

"`0$~"0$~      e# Works as in GolfScript.

Unlike CJam, GolfScript will append a linefeed to the contents of the stack, so this is not a quine in GolfScript.

\$\endgroup\$
4
  • \$\begingroup\$ Just curious, in a broad sense, what's the difference between CJam and GolfScript, and why does your code work? \$\endgroup\$
    – Pavel
    Commented Nov 8, 2016 at 20:54
  • \$\begingroup\$ CJam was heavily inspired by GolfScript and is mostly backwards compatible. One big difference is that GolfScript, by default, appends a linefeed to the output, while CJam doesn't, which is what I'm exploiting here. I'll add a detailed explanation asap. \$\endgroup\$
    – Dennis
    Commented Nov 8, 2016 at 20:56
  • 1
    \$\begingroup\$ "0$p"0$~a:n;. \$\endgroup\$
    – jimmy23013
    Commented Nov 10, 2016 at 18:34
  • \$\begingroup\$ @jimmy23013 Nice, thank you! I had toyed with a:n, but using p didn't occur to me. \$\endgroup\$
    – Dennis
    Commented Nov 10, 2016 at 18:37
4
\$\begingroup\$

Jelly / GolfScript, 18 16 bytes

0000000: 3a 6e 22 ff cc cc 22 7d 7f fe 22 3a 6e 60 ff 3b  :n"..."}..":n`.;

Verification

Testing all involved programs with the exact byte streams can only be done locally.

$ LANG=en_US # Latin-1. Jelly doesn't care about the exact encoding,
$            # as longs as it's not UTF-8.
$
$ xxd -g 1 mpquine
0000000: 3a 6e 22 ff cc cc 22 7d 7f fe 22 3a 6e 60 ff 3b  :n"..."}..":n`.;
$
$ jelly f mpquine | tee quine.gs | xxd -g 1
0000000: 22 3a 6e 60 22 3a 6e 60                          ":n`":n`
$ golfscript quine.gs | xxd -g 1
0000000: 22 3a 6e 60 22 3a 6e 60                          ":n`":n`
$ jelly f quine.gs 2> /dev/null | xxd -g 1
$
$ golfscript mpquine | tee quine.jelly | xxd -g 1
0000000: ff cc cc                                         ...
$ jelly f quine.jelly | xxd -g 1
0000000: ff cc cc                                         ...
$ golfscript quine.jelly | xxd -g 1
0000000: 0a

Jelly

With Jelly's code page, the program looks as follows.

:n"”ṘṘ"}
“":n`”;

This prints (Try it online!)

":n`":n`

which is a quine in GolfScript (Try it online!), but a parser error in Jelly (Try it online!).

GolfScript

In Latin-1, the program looks as follows, with an unprintable DEL character between } and þ.

:n"ÿÌÌ"} þ":n`ÿ;

This prints (Try it online!)

ÿÌÌ

or, visualized with Jelly's code page,

”ṘṘ

which is a quine in Jelly (Try it online!), but only prints a linefeed in GolfScript (Try it online!).

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Good old ”ṘṘ, thus ØV should be gone, right? \$\endgroup\$ Commented Nov 13, 2016 at 11:37
3
\$\begingroup\$

JavaScript / C 278 bytes

At a staggering 278 bytes:

//\
console.log('int main(){char*A="int main(){char*A=%c%s%c;printf(A,34,A,34);}";printf(A,34,A,34);}');/*
int main(){puts("A='A=;B=String.fromCharCode(39);console.log(A.slice(0,2)+B+A+B+A.slice(2));';B=String.fromCharCode(39);console.log(A.slice(0,2)+B+A+B+A.slice(2));");}//*/

The C quine:

int main(){char*A="int main(){char*A=%c%s%c;printf(A,34,A,34);}";printf(A,34,A,34);}

The JavaScript quine:

A='A=;B=String.fromCharCode(39);console.log(A.slice(0,2)+B+A+B+A.slice(2));';B=String.fromCharCode(39);console.log(A.slice(0,2)+B+A+B+A.slice(2));

\$\endgroup\$
1
  • \$\begingroup\$ Holy mother of quines... \$\endgroup\$
    – MD XF
    Commented May 26, 2017 at 4:20
3
\$\begingroup\$

Befunge / Fission, 35 bytes

"$TQ-#'">,#-:#2_@;"+1_@#`+66:,g0:"L

Try it in Befunge | Try it in Fission

In Befunge this produces the Fission quine:

'!+OR"

In Fission this produces the Befunge quine:

:0g,:66+`#@_1+
\$\endgroup\$
1
\$\begingroup\$

Python / Retina, 70 65 64 66 bytes

I used the same strategy I used in my previous Python / Retina polyglot.

#
print"\nS`((.+))"*2+"\n\n"
#?
#_='_=%r;%_\n';_
#?;
#;print _%
#

Try in Python | Try in Retina

# is a comment in Python, so it simply prints the Retina quine in Python. In Retina, the first stage (2 lines) does nothing, because no # will be found in the input. The next stage replaces nothing with the basis of the Python quine. The third stage replaces each semicolon with the #print _% piece. The last stage removes all #'s.


Quine in Retina:


S`((.+))
S`((.+))


Quine in Python:

_='_=%r;print _%%_\n';print _%_

The quines used may be seen in this challenge. The Retina quine is an error in Python, and the Python quine has no output in Retina.

\$\endgroup\$
2
  • \$\begingroup\$ Can you add an explanation to your answer for how the metaquine works? \$\endgroup\$
    – Pavel
    Commented Nov 10, 2016 at 23:59
  • \$\begingroup\$ @Pavel Added it. \$\endgroup\$
    – mbomb007
    Commented Nov 11, 2016 at 3:58
1
\$\begingroup\$

Python 3 / Python 2, 62 bytes

_='_=%r;print(_%%_['+'~'*-~int(-1/2)+'int(-1/2):])';print(_%_)

Try it in Python 2, Python 3.

Based on the Python quine here. The distinguishing factor between the two versions is what they do with int(-1/2): in Python 2, / is integer division (rounding down), with a result of -1; in Python 3, / is floating point division (-0.5), which int truncates to 0.

We build a string _ in three parts. '_=%r;print(_%%_[' and 'int(-1/2):])' are always the same. The interesting part is '~'*-~int(-1/2):

  • In Python 2, -~int(-1/2) is 0, and the tilde is not added to the string;
  • In Python 3, -~int(-1/2) is 1, and the tilde is added to the string.

Thus, Python 2 outputs the Python 3 quine

_='_=%r;print(_%%_[int(-1/2):])';print(_%_[int(-1/2):])

and Python 3 outputs the Python 2 quine

_='_=%r;print(_%%_[~int(-1/2):])';print(_%_[~int(-1/2):])

In each version, the expression inside [ :] evaluates to 0, which makes the slice include the entire string, whereas in the wrong language it evaluates to -1, which makes the slice include only the last character, truncating the output so it's not a full quine.

\$\endgroup\$
1
\$\begingroup\$

Brain-Flak, brainfuck 4617 4009 bytes

((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()()()())))()())[()()])))()()())[()()])))())[()])[()()()()])))))))))))))))))))))))))))))))))))))))))))()()())()())[()()()()])()()())[()()])()())[()()()()])()()()))()()())[()()])[()()()()])))))))))))))))))))()())))()()())[()()()()])()()()()())[()()]))()())[()()()])()())[()()])))()()())[()()])))())[()()])[()()()])))))))))))))))))))))))))))))))))))))))))))()()()())[()()()])()()()())[()()])[()()()]))()()()())[()()()])()()()())[()()])[()()()])()()()())[()()()])()()()())[()()])[()()()]))))))))))))))()()()())[()()()])()()()())[()()])[()()()]))()()()())[()()()])()()()())[()()])[()()()])))))))))))))))))))))))))))))()()()())[()()()])()()()())[()()])[()()()]))()()()())[()()()])()()()()()))))))[()()()])[()])()()))))()()){({}<>)<>}<>([]){({}[()]<(({}[()]<((((((()()()){}())){}{}){}())<>)>)<>){({}[()]<({}()())>){({}[()]<({}())>){({}[()]<({}((()()()){}()){})>){({}[()]<({}()())>){({}[()]<({}(((()()()){}()){}){}())>){(<{}({}()())>)}}}}}}{}([]<({}<{({}<>)<>}<>>)>){({}[()]<({}<>)<>>)}{}{({}[()]<(({}))>)}{}(((({})(((()()())){}{}){}())))<>>)}{}{<>({}<>)}{+++++++>>>+>>>+++++++>>>++++++++>>>+++>>>++++>>>++>>>+++>>>++++>>>++++++++>>>+++>>>++++>>>+>>>+++++>>>++++++>>>++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+>>>+>>>+>>>+>>>+>>>+>>>+>>>+>>>++>>>+>>>++>>>+>>>++>>>+>>>++>>>+>>>++>>>++>>>+++++++>>>++++++++>>>++>>>+++++++>>>++++++++>>>++>>>+++++++>>>++++++++>>>++>>>+++>>>++++>>>++>>>++>>>+>>>++>>>++>>>++>>>++++>>>++>>>+++>>>++++>>>++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+++++++>>>++++++++>>>+>>>++>>>++>>>++++>>>++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+++++++>>>++++++++>>>+>>>+>>>+>>>+>>>++>>>+>>>++>>>+>>>++>>>++>>>++>>>+++++++>>>++++++++>>>+++++++>>>++++++++>>>++>>>+++++++>>>++++++++>>>+>>>++>>>++>>>++++>>>++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+++++++>>>++++++++>>>+>>>++>>>+>>>++>>>++>>>++++>>>++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+++++++>>>++++++++>>>+>>>+>>>+>>>+>>>++>>>+>>>++>>>+>>>++>>>++>>>+++++++>>>++++++++>>>+>>>++>>>++>>>+++++++>>>++++++++>>>++>>>+++++++>>>++++++++>>>+>>>++>>>++>>>++++>>>++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+++++++>>>++++++++>>>+>>>++>>>+>>>++>>>++>>>++++>>>++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+++++++>>>++++++++>>>+>>>+>>>+>>>+>>>++>>>+>>>++>>>+>>>++>>>+>>>++>>>+>>>++>>>++>>>++>>>+++++++>>>++++++++>>>+++++++>>>++++++++>>>++>>>+++++++>>>++++++++>>>++>>>++++>>>++>>>+++++++>>>+>>>+++>>>+++++++>>>++++++++>>>+>>>+++++++>>>++++++++>>>+>>>++>>>+>>>++>>>++>>>++++>>>++>>>++++++++>>>++++++++>>>++++++++>>>++++++++>>>++++++++>>>++++++++>>>++++++++>>>+++++++>>>++++++++>>>+>>>+++++>>>++++++>>>+++>>>+>>>+++++++>>>++++++++>>>+++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++>>>++++>>>++>>>+++>>>++++>>>++++++++>>>+++>>>++++>>>++++>>>++>>>++++>>>++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+++++++>>>++++++++>>>+++>>>++++>>>++>>>+++>>>++++>>>++++>>>++>>>++++++++>>>+++++++>>>++++++++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>+++>>>+>>>+>>>+>>>+++++++>>>++++++++>>>+++++>>>+>>>++>>>++++++>>>++>>>+>>>++>>>++>>>++>>>++++>>>++>>>++++++++>>>+++++++>>>++++++++>>>+++>>>++++>>>++++>>>++>>>++++++++>>>+++++++>>>++++++++>>>+++>>>++++>>>+++++++>>>+>>>+++++++>>>++++++++>>>+++>>>++++>>>++>>>+++>>>++++>>>++++++++>>>+++>>>++++>>><<<[<<<]>>>[>++++++++++++++++++++++++++++++++++++++++.<[->.+.->+<<]>+.[-]>>]<[<<<]>>>[<++++++++++++++++++++++++++++++++++++++++>-[<+>-[<+++++++++++++++++++>-[<++>-[<+++++++++++++++++++++++++++++>-[<++>-[<++++++++++++++++++++++++++++++>-[<++>-]]]]]]]<.>>>>]}{}

Try it online!

Try it online!

Explanation is on its way I am still golfing this

\$\endgroup\$
2
  • \$\begingroup\$ This generates a brainfuck quine in brainfuck, and a Brain-Flak quine in Brain-Flak. It should generate a brainfuck quine when run in Brain-Flak and a Brain-Flak quine when run in brainfuck. \$\endgroup\$
    – Pavel
    Commented Jan 27, 2017 at 1:10
  • \$\begingroup\$ I will do it again. I am sorry I just have a hard time following the As and Bs \$\endgroup\$
    – Wheat Wizard
    Commented Jan 27, 2017 at 1:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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