Three polyglots, two period-two quines, and one code-golf challenge

JavaScript (ES6) / Python 3, 264 + 258 = 522 bytes

Program A:

a="a=%r;b=%r;c=%r;1//2;print(c);'''\nconsole.log(b,...[a,b,c].map(uneval))//'''";b="a=%s;b=%s;c=%s;1//2;'''\nprint=_=>console.log(c)//'''\nprint(a%(a,b,c))";c="1//2;alert=print\nalert('Wrong language!')";1//2;print(c);'''
console.log(b,...[a,b,c].map(uneval))//'''

Program B:

a="a=%r;b=%r;c=%r;1//2;print(c);'''\nconsole.log(b,...[a,b,c].map(uneval))//'''";b="a=%s;b=%s;c=%s;1//2;'''\nprint=_=>console.log(c)//'''\nprint(a%(a,b,c))";c="1//2;alert=print\nalert('Wrong language!')";1//2;'''
print=_=>console.log(c)//'''
print(a%(a,b,c))

Program C:

1//2;alert=print
alert('Wrong language!')

Probably golfable...

JavaScript explanation

Program A:

// Set a, b, and c to these strings:
a="a=%r;b=%r;c=%r;1//2;print(c);'''\nconsole.log(b,...[a,b,c].map(uneval))//'''";
b="a=%s;b=%s;c=%s;1//2;'''\nprint=_=>console.log(c)//'''\nprint(a%(a,b,c))";
c="1//2;alert=print\nalert('Wrong language!')";

// Ignore this line:
1//2;print(c);'''

// Print the Python program (b), replacing the "%s"s with the raw forms of a, b, and c:
console.log(b,...[a,b,c].map(uneval))//'''

Program B:

// Set a, b, and c to these strings:
a="a=%r;b=%r;c=%r;1//2;print(c);'''\nconsole.log(b,...[a,b,c].map(uneval))//'''";
b="a=%s;b=%s;c=%s;1//2;'''\nprint=_=>console.log(c)//'''\nprint(a%(a,b,c))";
c="1//2;alert=print\nalert('Wrong language!')";

// Ignore this line:
1//2;'''

// Define a function `print` which prints `c` (the "Wrong language!" program):
print=_=>console.log(c)//'''

// Call `print`, ignoring the argument (which is NaN):
print(a%(a,b,c))

Program C:

// Ignore this line:
1//2;alert=print

// Alert "Wrong language!":
alert('Wrong language!')

Python explanation

Program A:

# Set a, b, and c to these strings:
a="a=%r;b=%r;c=%r;1//2;print(c);'''\nconsole.log(b,...[a,b,c].map(uneval))//'''";
b="a=%s;b=%s;c=%s;1//2;'''\nprint=_=>console.log(c)//'''\nprint(a%(a,b,c))";
c="1//2;alert=print\nalert('Wrong language!')";

# Print `c` (the "Wrong language!" program):
1//2;print(c);

# Ignore this part:
'''
console.log(b,...[a,b,c].map(uneval))//'''

Program B:

# Set a, b, and c to these strings:
a="a=%r;b=%r;c=%r;1//2;print(c);'''\nconsole.log(b,...[a,b,c].map(uneval))//'''";
b="a=%s;b=%s;c=%s;1//2;'''\nprint=_=>console.log(c)//'''\nprint(a%(a,b,c))";
c="1//2;alert=print\nalert('Wrong language!')";

# Ignore this part:
1//2;'''
print=_=>console.log(c)//'''

# Print the JS program (a), replacing the "%r"s with the raw forms of a, b, and c:
print(a%(a,b,c))

Program C:

# Set `alert` to the function `print`:
1//2;alert=print

# Call this function on "Wrong language!":
alert('Wrong language!')

Befunge-98 (PyFunge)/><>, 123 + 123 = 266 250 246 bytes

Program A:
"81!#.#vp00g>:#,_j+4<.=1l5v!o#!g00
g00<<<<<>0!#[f8+1!#.48*k'Wrong language!<o>[f@,kep.#!0a'00g!#o# \!gff+k,@,k*8ba$$ #o#!a"

Try it in Befunge-98!, Try it in ><>!

Program B:
"00g!#o!v5l1=.<4+j_,#:>g00pv#.#!18
g00<<<<<>0!#[f8+1!#.48*k'Wrong language!<o>[f@,kep.#!0a'00g!#o# \!gff+k,@,k*8ba$$ #o#!a"

Try it in ><>!, Try it in Befunge-98!

Program C:
"a0!#.pek,@f[>o<!egaugnal gnorW

Try it in Befunge-98! Try it in ><>!

How it Works:

The second line in both programs is identical and serves the same function for both language. When entered leftwards from the <<<<, it prints the entire second line. When entering to the right of those, print program C.

When the first line is run in the wrong language, it enters through the program C producing section. Otherwise, it prints the top line backwards with the " at the front and enters the second line producing section.

First line

Program A:
"81!#.#vp00g>:#,_j+4<.=1l5v!o#!g00

><>:
" Wrapping string literal over the first line
 81!#.  Jumps the pointer to the Program C producer

Befunge-98:
" Wrapping string literal
 81!#.  Pushes 8,0 (! inverts number, # skips over .)
      #v Skip over the exit
        p00g Pops the excess 8,0 and space and gets the " from 0,0
            >:#,_ Classic print until stack is empty
       v         j+4< Skips back to the exit and goes to the second line
Program B:
"00g!#o!v5l1=.<4+j_,#:>g00pv#.#!18

><>:
" Wrapping string literal
 00g!# Gets the " from 0,0
      o!v5l1=. Print until the stack is empty and jump to the second line

Befunge-98:

" Wrapping string literal
 00g Gets the " from 0,0
    !#o!v Skip the instruction o and go to Program C producer

Second Line:

g00<<<<<>0!#[f8+1!#.48*k'Wrong language!<o>[f@,kep.#!0a'00g!#o# $$00gff+k,@,k*9aa$$ #o#!a"

><>: Second line producer
g00<<<<< Get the " from cell 0,0
        ......      " Wrapping string literal over the stack
               #o#!a  Print newline and the stack and exit
Program C producer:
       >0!#[        Clear stack
            f8+1!#. Jump to cell 22,1
                   .....'...'   Push program C to the stack
                             00g Get " from cell 0,0
                                !#o# Print stack until empty

Befunge-98: Second line producer

g00<<<<< Get the " from cell 0,0
        ......              " Wrapping string literal
                       #o#!a  Skip over instruction o
                     $$       Pop the excess characters
                  90a Push a newline and 90
               @,k      Execute , instruction (print) 90+1 times, printing second line

Program C producer:
        >0!#[ Push 1 and skip [
             f8+1!#. Push 22, 0 and skip .
                    48*k'...' Execute ' instruction 32 times, pushing program C
                         ...'00g!#o# Push 0 and skip the instruction o
                                     \! Convert excess values to two 0s
                                       g Get " from cell 0,0
                                          ff+ Push 30
                                             k, Execute , 30+1 times, printing program C
                                               @ Exit program

Program C

"a0!#.pek,@f[>o<!egaugnal gnorW

><>:
" Wrapping string literal
 a0!#. Jump to cell 10,0
           f[ Create a new stack with only the top 15 elements
             >o< Print stack

Befunge-98:
" Wrapping string literal
 a0!#. Push 10,1
      p Pop 10,1 and excess space
       ek,@ Push 14 and execute , 14+1 times and exit the program

Python 3 + JavaScript (Rhino), 171 + 171 = 342 bytes

Program A (outputs program B in Python 3, program C in JavaScript; note trailing newline):

s="'";d='"';r=['print("s="+d+s+d+";d="+s+d+s+";r=["+s+r[1]+s+","+s+r[0]+s+"];eval(r[([11]+[0])[1]])")','print("print("+d+"Wrong language!"+d+")")'];eval(r[([11]+[0])[1]])

Program B (outputs program A in JavaScript, program C in Python; note trailing newline):

s="'";d='"';r=['print("print("+d+"Wrong language!"+d+")")','print("s="+d+s+d+";d="+s+d+s+";r=["+s+r[1]+s+","+s+r[0]+s+"];eval(r[([11]+[0])[1]])")'];eval(r[([11]+[0])[1]])

Program C (outputs "Wrong language!" in either language; also has a trailing newline, which doesn't count in the score):

print("Wrong language!")

Note that I'm using an unusual dialect of JavaScript here. People normally use browser implementations, but those have issues with output, doing it in a weird way (using alert). I'm using the Ubuntu package rhino which is an "offline" JavaScript implementation with a different set of libraries implemented to a typical browser (it's intended as an embeddable scripting language); this is notable in that it provides a print statement in the same style as, for example, Python 3.

This is a "true polyglot" in the sense that both languages are running the same calculations, in the same order, giving them the same meaning. They both have the same AST (and it's fairly trivial to create a Python 3 + JavaScript polyglot quine via reducing this program). There's no code that's specific to one language, which helps me bring the length way down. Incidentally, you have to use Python 3 so that you can use semicolons to separate statements (if you used newlines you'd have to escape the newlines).

The program starts by defining strings s and d which hold a single quote and double quote respectively. This makes it possible to output quotes without having to mention them later in the source code, avoiding issues with escaping (which frequently seem to be a problem with quines; the main reason I answer so many quine problems in Underload is that its strings nest).

The heart of the program is the array r which holds the main body of the two programs used by the challenge; one of the programs (the one that comes first in program A, and second in program B) is an almost-quine that simply outputs the original program via concatenating together pieces (taken mostly from r itself, with a few string literals), and the other prints program C. In order to make the program not a true quine (which would make it impossible to detect that we were running in the wrong language), the elements of r are printed in reverse order; r[0] in program A is r[1] in program B, and vice versa.

Finally, all that's necessary is to evaluate the correct element of r. This is accomplished using the expression ([11]+[0])[1] that produces a different value in Python 3 and in JavaScript. Both languages parse it identically, but they have different ideas of what addition does to lists:

  • When Python 3 adds [11] to [0], it gets [11, 0] (concatenating the lists), and then taking the second element of the list ([1]) gives us the integer 0.

  • When JavaScript adds [11] to [0], it gets "110" (concatenating the string representations of the lists), and then taking the second character of the string ([1]) gives us the string "1", which JavaScript is quite happy to use as an index into a list.

Therefore, Python 3 runs the first element of r in both programs (producing the almost-a-quine when running program A, and printing program C when running program B); JavaScript runs the second element, and thus treats program A and program B the opposite way around.

Incidentally, if you run program A in Ruby, it will print program B except without a trailing newline. If you run program B in Ruby, it will print program C except without a trailing newline. In other words, this solution very nearly works with a different set of languages, swapping Python 3 for Ruby (the only reason I don't just delete the newline from program B to get a score of 341 is that the newline inconsistency in program C would disqualify the submission).

(I was working on a "true polyglot" like this for a different reason, which I've now posted as a challenge, and realised that the techniques could be adapted to this one as well.)