26
\$\begingroup\$

Task

Write a polyglot in two languages that when run, outputs the name of the language it is run in. Additionally, this program must also output the other language's name if the source code is reversed

Example:

Program ABC in language foo outputs foo. ABC in language bar outputs bar. CBA in language foo outputs bar, and CBA in language bar outputs foo.

This is code-golf, so the shortest code wins

\$\endgroup\$
2
  • \$\begingroup\$ Does anyone see how to use Haskell in an answer? \$\endgroup\$
    – Simd
    Feb 13 at 7:29
  • \$\begingroup\$ Please add a comment here if anyone had an implementation of txeT before this question posted. :) \$\endgroup\$
    – tsh
    Feb 23 at 8:11

14 Answers 14

16
\$\begingroup\$

JavaScript, HTML, 68 bytes

HTML JavaScript
Normal
<!---->HTML<!--!<tpircSavaJ>--
alert`JavaScript`//`LMTH`trela
<!--!<
<!---->HTML<!--!<tpircSavaJ>--
alert`JavaScript`//`LMTH`trela
<!--!<
Reversed
<!--!<
alert`HTML`//`tpircSavaJ`trela
-->JavaScript<!--!<LMTH>----!<
<!--!<
alert`HTML`//`tpircSavaJ`trela
-->JavaScript<!--!<LMTH>----!<

JavaScript is a strange language that support 5 kinds of comment and 5 kinds of link breaks.

Comment:

  • Multi line comment /* ... */ Ref
  • Single line comment // ... Ref
  • Hashbang comment #! ... Ref
    • Must at the beginning of source code
    • Some script host support an extra BOM in front of hashbang
  • Single line HTML open comment <!-- ... Ref
  • Single line HTML close comment --> ... Ref

Line breaks: Ref

  • <LF>
  • <CR>
  • <LS>
  • <PS>
  • <CR> <LF>
\$\endgroup\$
14
\$\begingroup\$

Python + ><>, 49 bytes

#o<"><>"
print("python")#)"><>"(tnirp
"nohtyp"<o#

Try it:

\$\endgroup\$
12
\$\begingroup\$

Java and Whitespace, 175 bytes

v->"Java"//"ecapsetihW">-vSSTTN
SSTTTN
SSTTSTN
SSSTSTSN
SSSTTSTN
SSTTN
SSSTTTSN
SSSTTN
SSSTSN
SSTTTTTN
N
SSN
SSSTTSSTTSN
TSSSTN
SSN
SN
N
N
N
SN
SSN
TSSSTN
SSSSSTTSSSN
SSN
N
STTSTTSSN
TSSSN
STTSTSSSN
TSSS

Above, the spaces, tabs, and newlines are indicated with S; T; and N respectively for readability only. The TIO-links below contain the actual spaces/tabs/newlines.

Explanation:

In Java:

v->                        // Method with empty unused parameter & String return-type
   "Java"                  //  Return "Java"
         //"ecapsetihW">-v //  No-op comment
                           //  No-op spaces/tabs/newlines

In Java reversed:

                           // No-op spaces/tabs/newlines
v->                        // Method with empty unused parameter & String return-type
   "Whitespace"            //  Return "Whitespace"
               //"avaJ">-v //  No-op comment

In Whitespace:

v->"Java"//"ecapsetihW">-v // No-ops
SSTTN                      // Push -1 (e)
SSTTTN                     // Push -3 (c)
SSTTSTN                    // Push -5 (a)
SSSTSTSN                   // Push 10 (p)
SSSTTSTN                   // Push 13 (s)
SSTTN                      // Push -1 (e)
SSSTTTSN                   // Push 14 (t)
SSSTTN                     // Push 3 (i)
SSSTSN                     // Push 2 (h)
SSTTTTTN                   // Push -15 (W)
NSSN                       // Create Label LOOP
 SSSTTSSTTSN               //  Push 102
 TSSS                      //  Add the top two integers together
                           //  (which will implicitly stop the program with an error if
                           //  there is just a single value on the stack)
 TNSS                      //  Print the top as character to STDOUT
 NSNN                      //  Jump to Label LOOP
NNSNSSNTSSSTNSSSSSTTSSSNSSNNSTTSTTSSNTSSSNSTTSTSSSNTSSS
                           // No-op whitespaces

In Whitespace reversed:

SSSTN                      // Push 1 (a)
SSSTSTTSN                  // Push 22 (v)
SSSTN                      // Push 1 (a)
SSTTSTTSN                  // Push -22 (J)
NSSN                       // Create Label LOOP
 SSSTTSSSSSN               //  Push 96
 TSSS                      //  Add the top two integers together
                           //  (which will implicitly stop the program with an error if
                           //  there is just a single value on the stack)
 TNSS                      //  Print the top as character to STDOUT
 NSNN                      //  Jump to Label LOOP
NNSNSSNTSSSTNSTTSSTTSSSNSSNNTTTTTSSNSTSSSNTTSSSNSTTTSSSNTTSSNTSTTSSSNSTSTSSSNTSTTSSNTTTSSNTTSS
                           // No-op whitespaces
v->"Whitespace"//"avaJ">-v // No-ops

The constants 102 and 96 are generated by this Java program based on this Whitespace tip of mine.

\$\endgroup\$
11
\$\begingroup\$

05AB1E and Y, 15 bytes

"Y"gxg"E1BA50"R

Explanation:

In 05AB1E:

"Y"              # Push string "Y"
                 #  STACK: "Y"
   g             # Pop and push its length
                 #  STACK: 1
    x            # Double it (without popping)
                 #  STACK: 1,2
     g           # Pop and push its length
                 #  STACK: 1,1
      "E1BA50"   # Push string "E1BA50"
                 #  STACK: 1,1,"E1BA50"
              R  # Reverse it
                 #  STACK: 1,1,"05AB1E"
                 # (after which the top of the stack is output implicitly)

In 05AB1E reversed:

R                # Reverse (without input, it'll push an empty string)
                 #  STACK: ""
 "05AB1E"        # Push string "05AB1E"
                 #  STACK: "","05AB1E"
         g       # Pop and push its length
                 #  STACK: "",6
          x      # Double it (without popping)
                 #  STACK: "",6,12
           g     # Pop and push its length
                 #  STACK: "",6,2
            "Y"  # Push string "Y"
                 #  STACK: "",6,2,"Y"
                 # (after which the top of the stack is output implicitly)

In Y:

"Y"              # Push string "Y"
   g             # Pop and print it
    x            # Stop the program
     g"E1BA50"R  # No-ops

In Y reversed:

R                # No-op character
 "05AB1E"        # Push string "05AB1E"
         g       # Pop and print it
          x      # Stop the program
           g"Y"  # No-ops
\$\endgroup\$
1
  • 1
    \$\begingroup\$ There's a minor mistake in the explanation for the 05AB1E reverse program. When the program is reversed, the string literal reads 05AB1E, not E1BA50. \$\endgroup\$
    – noodle man
    Nov 22 at 0:45
9
\$\begingroup\$

Python + Javascript(Node.js) 150 bytes

Uses the differences between javascript objects and python dicts to change code passed to eval in both languages. Uses both quoting styles with escaping to evaluate different code when reversed

"'\",)]'0'[}')'\nohtyP'\(gol.elosnoc':0,')'\tpircsavaJ'\(tnirp':'0'{(lave,'",eval({"0":"print(\"Python\")",0:"console.log(\"Javascript\")"}["0"]),'\"'

Python normal

Javascript normal

Python reversed

Javascript reversed

\$\endgroup\$
3
  • 3
    \$\begingroup\$ 96 bytes if you use SpiderMonkey: Try it online! \$\endgroup\$
    – Neil
    Feb 6 at 21:56
  • 1
    \$\begingroup\$ @Neil Can you reverse the quotey \$\endgroup\$
    – l4m2
    Feb 10 at 2:58
  • \$\begingroup\$ @l4m2 Nice, and you can do it in the reversed program too for 92! "'\",)]0[}'nohtyP':'0','tpircsavaJ':0{(tnirp,'",print({0:"Python","0":"Javascript"}[0]),'\"' \$\endgroup\$
    – Neil
    Feb 10 at 8:36
8
\$\begingroup\$

C/C++, 119 bytes

#include<stdio.h>//
int main(){puts(sizeof!0-1?"C":"C++");}//};)"++C+0\C0"+0!foezis(stup{)(niam tni
//>h.oidts<edulcni#

Try it online!

Reference

Old: C/C++, 167 bytes

#include<stdio.h>//
int main(){puts("C"//
#ifdef __cplusplus//
"++"//
#endif//
);}//};)
//fidne#
//"++"
//sulpsulpc__ fednfi#
//"C"(stup{)(niam tni
//>h.oidts<edulcni#

Try it online!

Not that elegant due to #ifdef but resolving it also save bytes done

\$\endgroup\$
7
\$\begingroup\$

PHP Perl 4 or 5, 45 43 41 bytes

print-true?php:perl;#;php:lrep?eurt-tnirp

Try it online PHP

Try it online Perl

A simple take at it, I assumed it was not mandatory to specify the Perl version as it is not a polyglot between different versions of perl (though I could do one). Works in Perl 4 or 5

Takes advantage of the fact that PHP converts true to 1 for numerical operations while Perl 4/5 ignores it

EDIT: saved 2 bytes by removing 1, -true is enough (with swaped languages names)

EDIT 2: thanks to Neil for saving another 2 bytes removing the spaces

\$\endgroup\$
2
  • \$\begingroup\$ Now that you no longer have the 1, do you still need the spaces? \$\endgroup\$
    – Neil
    Feb 7 at 22:26
  • \$\begingroup\$ @Neil good catch, I don't indeed, thanks \$\endgroup\$
    – Kaddath
    Feb 8 at 8:08
6
\$\begingroup\$

C and Python, 163 119 bytes

p=0//1;print("Python")#//#
#define p;main(){puts("C");}//#
p
#//};)"nohtyP"(stup{)(niam;p enifed#
#//#)"C"(tnirp;1//0=p

Try it online!


warning-less & C99 compliant version, 235 bytes

#include<stdio.h>//#
#define p int main(void){puts("C");}//#
#if 0//fidne#
print("Python");p=0//1#//#
#endif//0 fi#
p
#if 0//fidne#
#//#1//0=p;)"C"(tnirp
#endif//0 fi#
#//};)"nohtyP"(stup{)diov(niam tni p enifed#
#//>h.oidts<edulcni#

Try it online!

Turns out, since C99, main() does implicitly return 0 which indicates successful termination. A single # (with optional whitespaces and/or comments after it) followed by a new line is also allowed; The standard calls it "Null directive".

\$\endgroup\$
2
  • \$\begingroup\$ Is it possible to make a version without C warnings? \$\endgroup\$
    – Simd
    Feb 13 at 7:27
  • 1
    \$\begingroup\$ @Simd Yes. You have to add an #include <stdio.h> for puts() and the int type specifier for main(). Since it's C, the empty parameter list must also be (void), and you must explicitly return 0 (or EXIT_SUCCESS by also #including <stdlib.h>. Some compilers might not accept #), #//, )#. I had a version that (ab)used the #line directive and some extra Python boilerplate to workaround this. \$\endgroup\$
    – pan
    Feb 14 at 13:34
2
\$\begingroup\$

Python 3.8 (pre-release) + JavaScript (Node.js), 95 bytes

1//print("Python")#1//)"nohtyP"(gol.elosnoc
console.log("JavaScript")//1#)"tpircSavaJ"(tnirp//1

Try it online! (Python)

1//print("Python")#1//)"nohtyP"(gol.elosnoc
console.log("JavaScript")//1#)"tpircSavaJ"(tnirp//1

Try it online! (JavaScript)

The python programs error after printing

\$\endgroup\$
2
\$\begingroup\$

dc and Fission, 35 bytes

[dc]P[;"cd"R"Fission";][[P]noissiF[

Try it online! dc in dc.

Try it online! Fission in Fission.

Try it online! Fission in dc reversed.

Try it online! dc in Fission reversed.

Explanations

dc → dc

[dc]P[;"cd"R"Fission";][[P]noissiF[
[dc]                                   push the string "dc"
    P                                  print without newline
     [;"cd"R"Fission";]                push the string (psuedo comment)
                       [               push the rest of the program as string (ditto)

Fission → Fission

[dc]P[;"cd"R"Fission";][[P]noissiF[
           R                           start an atom going right
            "Fission"                  print "Fission" and set the atom's mass to 7
                     ;                 destroy the atom

dc reversed → Fission

[Fission]P[[];"noissiF"R"dc";[P]cd[
[       ]                              push the string "Fission"
         P                             print without newline
          [                            push the rest of the program as string (psuedo comment)
                                       note that dc's [strings] nest
                                       and also doesn't complain with an unterminated string

Fission reversed → dc

[Fission]P[[];"noissiF"R"dc";[P]cd[
                       R               start an atom going right
                        "dc"           print "dc" and set the atom's mass to 2
                            ;          destroy the atom
\$\endgroup\$
2
\$\begingroup\$

Minecraft Function and C, 243 bytes

#include <stdio.h>//a fednu#
#define w int main(){printf("C");}//a fednu#
w
#undef a//>h.oidts< edulcni#
#undef a//};)"noitcnuF tfarceniM"(ftnirp{)(niam tni w enifed#
#if 0//fidne#
tellraw @a "Minecraft Function"#
#"C" a@ warllet
#endif//0 fi#

The C code is hidden behind preprocessor directives, which are interpreted as comments in the Minecraft function. The Minecraft code is hidden with #if 0 and #endif which is completely skipped by the compiler.

The code is written symmetrically with appropriate comments to comment out the reversed version. #undef a// (a comment in Minecraft and a no-op in C) is used to hide the reversed code.

The w, which is interpreted in C as int main(){printf("C");}, is also a valid Minecraft command. It has the wrong number of arguments, which causes a silent error, but the rest of the function still runs.

Try It Online:

(Minecraft Function not available on TIO)

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

Python, JavaScript (Node.js), 107 bytes

00000000: 2321 2f2f e280 a863 6f6e 736f 6c65 2e6c  #!//...console.l
00000010: 6f67 2822 4a61 7661 5363 7269 7074 2229  og("JavaScript")
00000020: 2f2f 2922 6e6f 6874 7950 2228 676f 6c2e  //)"nohtyP"(gol.
00000030: 656c 6f73 6e6f 63e2 80a8 3b60 230a 7072  elosnoc...;`#.pr
00000040: 696e 7428 2250 7974 686f 6e22 2923 2922  int("Python")#)"
00000050: 7470 6972 6353 6176 614a 2228 746e 6972  tpircSavaJ"(tnir
00000060: 700a 2360 e280 a82f 2f21 23              p.#`...//!#

No TIO link available...

All you need is comment out whatever you don't want...

\$\endgroup\$
5
  • \$\begingroup\$ on my machine the reversed javascript doesn't run \$\endgroup\$
    – emirps
    Feb 7 at 13:31
  • \$\begingroup\$ @emirps I reversed the program using python -c 'open("2.js","w",encoding="utf-8").write(open("1.js",encoding="utf-8").read()[::-1])'. And execute it using node 2.js. Let me know any errors you will get after execute these commands. \$\endgroup\$
    – tsh
    Feb 8 at 1:50
  • \$\begingroup\$ @emirps and the node version is v12.22.9 I'm using. As this program does not use any non-standard node features, it should work for any node version newer than 12.22.9. \$\endgroup\$
    – tsh
    Feb 8 at 1:59
  • \$\begingroup\$ Note that those periods in the ASCII preview are not really periods. You may need to use a command like cat tsh_poly.xxd | xxd -r > tsh_poly.pyjs to create the file for testing. \$\endgroup\$
    – M Virts
    Feb 8 at 20:08
  • 1
    \$\begingroup\$ @MVirts your command is about how to create 1.js described in above command \$\endgroup\$
    – tsh
    Feb 9 at 1:35
1
\$\begingroup\$

Vyxal + 05AB1E, 39 bytes

"‛₴ŀ,Q,`E1BA50``"i0"laxyV"}"05AB1E"0i0`

Vyxal code

Vyxal code reversed

05AB1E code

05AB1E code reversed

\$\endgroup\$
0
\$\begingroup\$

Clip and Fission, 18 bytes

"Clip";"noissiF"L+

Try it online in Fission!

Try it online in Fission reversed!

No online link for Clip.

In Clip, most things after the first entity and its parameters recursively don't matter. (Some operators also wait for input, but not in this case.) Strings takes no parameters. L is an empty list. + is for concatenation.

In Fission, L emits an atom to the left and ; destroys the atom. Strings in double quotes on the path of the atom are printed. It wraps around on the edges like most 2D languages.

GolfScript and Fission, 25 bytes

"GolfScript"K}K"noissiF"L

Try it online in GolfScript!

Try it online in Fission!

Try it online in GolfScript reversed!

Try it online in Fission reversed!

In GolfScript, K is a no-op and } is a super comment.

In Fission, K works like ; but also does something else that doesn't matter. Using ; here would break GolfScript.

\$\endgroup\$

Your Answer

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

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