197
\$\begingroup\$

Isn't it annoying when you find a piece of code and you don't know what language it was written in? This challenge attempts to somewhat solve this.

Challenge

You will have to write a program that when run in two different languages, will output the string:

This program wasn't written in <language program compiled/interpreted in>, it was built for <other language the program can be run in>!

  • In the output, language names should have official capitalization. eg: CJam, C++

  • Neither program should take any input from the user.

  • When run in both languages, output should be to stdout or equivalent.

  • There should be no output to stderr in either program.

  • You may use comments in either language.

  • Two different versions of the same language count as different languages.

    • If this is done, the program should output the major version number, and if running on two different minor versions, should report the minor version also.

    • You should not use prebuilt version functions (this includes variables that have already been evaluated at runtime).

Example output:

Perl and Ruby:

  • Perl: This program wasn't written in Perl, it was built for Ruby!

  • Ruby: This program wasn't written in Ruby, it was built for Perl!

Python and C:

  • Python: This program wasn't written in Python, it was built for C!

  • C: This program wasn't written in C, it was built for Python!

Python 2 and Python 3:

  • Python 2: This program wasn't written in Python 2, it was built for Python 3!

  • Python 3: This program wasn't written in Python 3, it was built for Python 2!

Python 2.4 and Python 2.7:

  • Python 2.4: This program wasn't written in Python 2.4, it was built for Python 2.7!

  • Python 2.7: This program wasn't written in Python 2.7, it was built for Python 2.4!

This is code golf so the shortest code in bytes wins.

\$\endgroup\$
9
  • 3
    \$\begingroup\$ "Two different versions of the same language count as different languages." So tricking like with C pre and past 99 comments is valid? easy ^^ \$\endgroup\$
    – Zaibis
    Sep 3, 2015 at 13:54
  • 2
    \$\begingroup\$ Added it, it feels paradoxical but fits to your rules. \$\endgroup\$
    – Zaibis
    Sep 3, 2015 at 14:48
  • 3
    \$\begingroup\$ No one's doing a Whitespace/Python polyglot? \$\endgroup\$ Sep 4, 2015 at 15:22
  • 1
    \$\begingroup\$ nevermind. Saw the 23 implementation \$\endgroup\$ Sep 4, 2015 at 15:26
  • 1
    \$\begingroup\$ Does relying on the program to be run with a certain interpreter count as input? that is, switching on argv[0]? \$\endgroup\$
    – cat
    Oct 28, 2016 at 12:10

123 Answers 123

8
\$\begingroup\$

VB6 / ES6 – 115 bytes

VB6

l="VB"
o="ES"
'';[l,o,MsgBox]=[o,l,alert]
MsgBox("This program wasn't written in "+l+"6, it was built for "+o+"6!")

ES6

l="VB"
o="ES"
'';[l,o,MsgBox]=[o,l,alert]
MsgBox("This program wasn't written in "+l+"6, it was built for "+o+"6!")
\$\endgroup\$
2
  • \$\begingroup\$ VBScript is not at version 6. The latest is 5.8. \$\endgroup\$ Mar 15, 2018 at 4:21
  • 1
    \$\begingroup\$ @peterferrie Thanks, but that's irrelevant. VB6 stands for Visual Basic 6, not VBScript 6. \$\endgroup\$
    – Toothbrush
    Mar 15, 2018 at 17:18
8
\$\begingroup\$

Whitespace and Malbolge, 1318 1055 bytes

Did I just outgolf Dennis? Yes I outgolfed Dennis. Although, it happened so that Kevin outgolfed me. Thanks for -263!

  		   			D'`rq
  			">7<Y
  		kW8Ux
   	  54-P>
   			=MLon
  			 %[k5F
   	  h}UeA
  				b?,__
  			 		)(r8Y
  		  	   Xtsl2
   	 	 Sonmf
   			,jLba
  		 f_%cE
 	  		[`Y}@
   		  ?[ZYR
   	  vVUTS
   	RQJIm
   		 	M/KDh
  			 HA)E>
 	  	 	bB$@?
   	 		>=6Z{
  				3810/
   				.R2r0
 	  		/.'&+
   		  $H('&
   	feB"!
 	  	 ~`_{z
  					  s9qvu
  			tsrk1
  		 	ohmlk
  				jc)J`
   	   &GF\a
   	 		ZY^]\
  			UyYXW
   		  9UNrR
   	QJOHM
   Fj-CH
  		   	AF?c=
  		  	   B;:9]
   		 =<|{9
   	2V0v4
 	  	 -QP0/
   		 o-&Jk
  			)"!&}
   		  C#c!x
 }|u;s
    	xwpun
   	 	 4UTpo
   				ng-kj
 	  			ihgfH
   		  %]\[`
  		     	Y^W{[
   		 Z<RvV
   	 		UT65Q
  				JnNG/
   				Ei,HG
 	  		 F?D=B
   	 	A@?8\
  				<54Xy
   	 	 x6/S3
  		210/o
   			-&Jk#
 	  	 (!~%$
   	   {Ab~w
 	  			|u;yx
   	 		qYutm
   	3kpon
   g-kji
  		 	  hgfH%
]\[`_
  ^WVzZ
   		 	   <Rv9O
	   	TMRQP
  ImGLE
 DhHGF
ED=%;
_?>=<;4z2V6/u-,+O/.'&J*j(!~}C#c!x}|u;\xqvotsl2poQPlkd*KJ`ed]\"ZY^W{UZYRWVOsSRKJOHGkKJIHA@dDCBA#">7[;{z870Tu3210).-,%$H"'&%$#"!~w=^]s9Zvo5Vlqpih.leM*u

Try it online! (Malbolge)

Try it online! (Whitespace)

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

Are solutions with more than two languages allowed? If so:

Python 3 / JavaScript / jq, 284 bytes

0//1|"\(".__len__();console={'log':lambda x:print(x.replace('JavaScript','Python 3').replace('jq','JavaScript'))}#")"|
"\(";console['log']('This program wasn\u0027t written in JavaScript, it was built for jq!');0//1#"|"This program wasn't written in jq, it was built for Python 3!")"

Highlighted for Python:

0//1|"\(".__len__();console={'log':lambda x:print(x.replace('JavaScript','Python 3').replace('jq','JavaScript'))}#")"|
"\(";console['log']('This program wasn\u0027t written in JavaScript, it was built for jq!');0//1#"|"This program wasn't written in jq, it was built for Python 3!")"

Highlighted for JavaScript:

0//1|"\(".__len__();console={'log':lambda x:print(x.replace('JavaScript','Python 3').replace('jq','JavaScript'))}#")"|
"\(";console['log']('This program wasn\u0027t written in JavaScript, it was built for jq!');0//1#"|"This program wasn't written in jq, it was built for Python 3!")"

No idea how to start explaining the jq part; just know that the string interpolation syntax in jq works as a "string inside string" of sorts: between "\(" and ")", jq is in a string inside a string, while Python and JavaScript consider them individual strings.

Using jq -n -r, python3 and node.

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

Emotinomicon/Python 2, 168 bytes

#😭!2 nohtyP rof tliub saw ti ,nocimonitomE ni nettirw t'nsaw margorp sihT😲⏪⏬⏩
print"This program wasn't written in Python 2, it was built for Emotinomicon!"

or with more languages:

Emotinomicon/Python 2/><>, 267 bytes

v=0
 #😭!2 nohtyP rof tliub saw ti ,nocimonitomE ni nettirw t'nsaw margorp sihT😲⏪⏬⏩
for _ in[0]:print"This program wasn't written in Python 2, it was built for ><>!"
"""
"
>v
v>"!nocimonitomE rof tliub saw ti ,><> ni nettirw t'nsaw margorp sihT"
>l?!;o
"""

but I'm bored so let's add another language:

Emotinomicon/Python 2/><>/Gol><>, 358 bytes

v=0
 #😭!2 nohtyP rof tliub saw ti ,nocimonitomE ni nettirw t'nsaw margorp sihT😲⏪⏬⏩
for _ in[0]:print"This program wasn't written in Python 2, it was built for ><>!"
"""
`
"
?
>v
v>"!><>loG rof tliub saw ti ,><> ni nettirw t'nsaw margorp sihT"
>l?!;o
"
>!v~~~~~"!nocimonitomE rof tliub saw ti ,><>loG ni nettirw t'nsaw margorp sihT"0q
  >l?!;o
"""
\$\endgroup\$
6
\$\begingroup\$

Perl/JavaScript ES6, 170 bytes

$a='Perl',$b='JavaScript';/1/&&($a=[$b,$b=$a].shift());$_="This program wasn't written in $a, it was built for $b!";/1/?console.log($_.replace(/\$./g,$r=>eval($r))):print

Again abusing regular expressions, but this time the fact that /1/ is truthy in JavaScript (because it's a RegExp object) and falsy in Perl (because $_ is empty) to switch the variables and run the correct print statement.

Note: This is ES6 JavaScript to work around Perl throwing a syntax error.

\$\endgroup\$
6
\$\begingroup\$

TeX / BASH - 192 bytes

echo "This program wasn't written in bash, it was built for TeX!";: "\output{\setbox0\hbox{\box255}\setbox0\vbox{This program wasn't written in \TeX, it was built for bash!}\shipout\box0}\end"

Trick is basically in the : "...." which lets bash do nothing with what comes inside the " ". TeX on the other hand just print it's own stuff onto a white paper. I know I could save 1 byte by writing "TeX" instead of "\TeX", but I wont, this looks much nicer: enter image description here

Inspired by http://pts.szit.bme.hu

Bonus:

TeX / many shells - 244 bytes

S=$(ps | grep `echo $$`$5 | awk '{ print $4$6 }');echo "This program wasn't written in $S$6, it was built for TeX!";: "\output{\setbox0\hbox{\box255}\setbox0\vbox{This program wasn't written in \TeX, it was built for shells!}\shipout\box0}\end"

This can in addition be run with dash, sh, ksh, et. al and will produce:

sheß@donald:~$ bash sh.sh
This program wasn't written in bash, it was built for TeX!
sheß@donald:~$ dash sh.sh
This program wasn't written in dash, it was built for TeX!
sheß@donald:~$ sh sh.sh
This program wasn't written in sh, it was built for TeX!
\$\endgroup\$
1
  • \$\begingroup\$ Finally:), I was already worried that no one would appreciate that \$\endgroup\$
    – sheß
    Sep 9, 2015 at 12:07
6
\$\begingroup\$

Haskell/Python 198 185 Bytes

Haskell

pass#b=b
pass##b=pass++b
p=print#putStrLn where print=p
main=p("This program wasn't written for "##(
 "Python"#"Haskell")##
 ", it was built for "##(
 "Haskell"#"Python")##
 "!")

Python

pass#b=b
pass##b=pass++b
p=print#putStrLn where print=p
main=p("This program wasn't written for "##(
 "Python"#"Haskell")##
 ", it was built for "##(
 "Haskell"#"Python")##
 "!")

Not actually sure if it works with all Pythons. Should work with python 3 at least.

If quotes in the output were valid, we could remove the third line and just use print in main (it'd print quotes around the string in haskell) - I'm assuming this is not valid here.

Explanation: The first 2 lines are no-ops in python (they just consist of pass), in Haskell they define 'select second' and 'concatenate' and concatenate operators respectively. The next line defines a 'variable' both in python and in haskell; In python it's pointing to print, in haskell it's defined as putStrLn (the where part shadows print, without it we would get type instantiation errors because of print there). The part after that is just abusing the fact that consecutive string literals in Python are concatenated like in C, in haskell we use the concatenation operator instead. We swap out "Python" and "Haskell" using our selection operators.

In python, the assignment to main is useless but valid. In Haskell, it's required because we need a main :: IO ().

\$\endgroup\$
6
\$\begingroup\$

Java/C, 418 Bytes

It might not have been a wise decision to use Java, nonetheless here's my solution:

//\u000a/*
#include <stdio.h>
#define public
#define static }
#define String int i,char*v
#define args
#define class
#define long g(){int
#define A struct{struct{int(*printf)();}out;}System={printf};f()
#define true 0
//*/
public class A{public static void main(String[]args){int c=true==(0==0)?1:0;System.out.printf("This program wasn't written in %s, it was built for %s!",c==0?"C":"Java",c==0?"Java":"C");}long f;}

Turns out Java and C are quite close. Except java is a lot more verbose and has a lot of keywords C doesn't need. And Java doesn't like the mixture of int's and booleans.

Annotated version

//\u000a/*                  /* \u000a gets replaced by a newline by javac
                               -> single line comment in C, multiline in java */
#include <stdio.h>          /* include needed, so I can use printf as function pointer */
#define public
#define static }
#define String int i,char*v /* make main declaration C compatible */
#define args
#define class
#define long g(){int        /* to remove closing bracket for `class {}` */
#define A struct { \        /* System.out.printf for C */
              struct { \
                  int (*printf)(); \
              } out; \
          } System = { printf }; \
          f()
#define true 0              /* Nothing is true, everything is permitted */
//*/                        /* single line comment in C, ends java multiline comment */
public class A {
    public static void main(String[] args) {
        int c = true == (0 == 0) ? 1 : 0; /* 1 for Java, 0 for C */
        System.out.printf("This program wasn't written in %s, it was built for %s!",
            c == 0 ? "C" : "Java",
            c == 0 ? "Java": "C");
    }
    long f; /* extra member, in java. gets redefined in C to get rid of the last } */
}

There might be some possibilites to cut off a few bytes here and there.

\$\endgroup\$
1
  • \$\begingroup\$ I think you can safely remove the v after #define String int i, char* \$\endgroup\$
    – yyny
    Dec 12, 2015 at 22:04
6
\$\begingroup\$

Perl/Tcl 171 bytes

#\
sub set{eval"\$$_[0]=\"$_[1]\""}sub puts{}
set a, "This program wasn't written in";
set b, "l, it was built for";
#\
print"$a Per$b Tcl!\n"||
puts "${a,} Tc${b,} Perl!"

No trailing semicolon or newline. This exploits Tcl comments being, well, odd!

\$\endgroup\$
6
\$\begingroup\$

Perl/PHP, 99 bytes

<?$p=erl;">;$p=HP#"
;$o=$p^erl^HP;print"This program wasn't written in P$o, it was built for P$p!";

For PHP, I assume the default interpreter settings, as they are without any ini. If you are uncertain, you may disable your local ini with -n as in php -n script.php.

\$\endgroup\$
4
  • \$\begingroup\$ On Ubuntu 15.04, perl does what's expected, but command-line php 5.6.4-4ubuntu6.2 just returns a verbatim copy of the input, even with -f or -F. Doesn't it work on command line? \$\endgroup\$ Sep 10, 2015 at 7:22
  • 1
    \$\begingroup\$ @StéphaneGourichon you will need to explicitly enable the short_open_tag in the php config file. Although it is enabled by default, all of the sample config files disable it. \$\endgroup\$
    – primo
    Sep 11, 2015 at 2:36
  • \$\begingroup\$ I'd rather not require administrator-level privilege just for this. I give up here since adding ` -d display_errors=Off` or =0 does not clean the output. php -d short_open_tag=On polyglot.php PHP Notice: Use of undefined constant erl - assumed 'erl' in polyglot.php on line 1 PHP Notice: Use of undefined constant erl - assumed 'erl' in polyglot.php on line 2 PHP Notice: Use of undefined constant HP - assumed 'HP' in polyglot.php on line 2 This program wasn't written in PHP, it was built for Perl! \$\endgroup\$ Sep 11, 2015 at 8:33
  • \$\begingroup\$ @StéphaneGourichon "I'd rather not require administrator-level privilege just for this." To be honest, I assumed most people would be running it from their own rig. short_open_tag: default value On. error_reporting: default value E_ALL & ~E_NOTICE. \$\endgroup\$
    – primo
    Sep 11, 2015 at 16:52
6
\$\begingroup\$

QBasic / Javascript, 153 134 bytes

UPDATE: Saw that the text could be de-duplicated:

a$="This program wasn't written in "
b$=", it was built for "
PRINT(a$+"JS"+b$+"QB!")
'';function PRINT(){alert(a$+"QB"+b$+"JS!");}

First post! Anyway, my code is:

PRINT ("This program wasn't written in JS, it was built for QB!")
'';function PRINT(){alert("This program wasn't written in QB, it was built for JS!");}

In QBasic, it prints the first line and doesn't execute the second line because it's believed to be a comment (thank you '). In JS, it calls the function PRINT, which is defined on the second line.

\$\endgroup\$
6
\$\begingroup\$

Ruby/Python 3, 127 122 114 109 bytes

a=["Python","Ruby"];b=(0 and 1);print("This program wasn't written in "+a[b]+", it was built for "+a[~b]+"!")

Explanation: Ruby evaluates 0 to true whereas Python evaluates it to false. The b=(0 and 1) determines whether 0 is truthy, so it represents the array index of the language it's being called from. Python had to come first because it can act oddly when the statement after the and evaluates to false. Also, that link says that it only works in older Python versions but I tried it in Python 3 and it worked fine.

Thanks kirbyfan64sos for removing 5 13 bytes!

Edit: Turns out 0 and 1 instead of 0 and 1 or 0 will also determine whether 1 is truthy in both languages.

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Nice! You can shave a 5 bytes off by changing a[(b+1)%2] to a[~b]. \$\endgroup\$ Sep 5, 2015 at 23:43
  • \$\begingroup\$ @kirbyfan64sos thanks, implemented! I never really knew about that operator before \$\endgroup\$
    – Piccolo
    Sep 6, 2015 at 17:20
  • 1
    \$\begingroup\$ It's the bitwise complement: 0 becomes -1 (which is the last element of a two-element array, 1), and 1 becomes -2 (which is the first element of a two-element array, 0). \$\endgroup\$ Sep 6, 2015 at 17:20
  • \$\begingroup\$ One more thing: is it possible to remove the spaces around the plus signs? \$\endgroup\$ Sep 6, 2015 at 17:22
  • \$\begingroup\$ @kirbyfan64sos yes! I'm kinda new to this whole code golfing thing, thanks \$\endgroup\$
    – Piccolo
    Sep 6, 2015 at 17:24
5
\$\begingroup\$

Python/Pip, 103 bytes

print(#x)O
"This program wasn't written in "#xO"Pip"Y
"Python"#xO
", it was built for "  "Pip!")
#xy.'!

GitHub repository for Pip

The main difficulty with Python and Pip is that they use completely different syntax for output (print vs O/P), for string concatenation (+ vs .), and for assignment (= vs :). At least they have the same syntax for defining strings! This is how Python interprets the program, with comments moved for clarity:

print(                             #x)O
"This program wasn't written in "  #xO"Pip"Y
"Python"                           #xO
", it was built for "  "Pip!")     
                                   #xy.'!

Literal strings in Python that are separated only by whitespace are concatenated.

Now here's how the program looks to the Pip interpreter:

p r i n t                           No-ops (all lowercase letters are variables)
(#x)                                Another no-op (# is the unary length operator)
O"This program wasn't written in "  Output without newline
#x                                  No-op
O"Pip"                              Output
Y"Python"                           The yank operator Y assigns its operand to y
#x                                  No-op
O", it was built for "              "Pip!") is a comment since it comes after two spaces
#x                                  No-op
y.'!                                Concatenate ! to the end of y and print (implicit)
\$\endgroup\$
5
\$\begingroup\$

Haskell / C - 225 219 bytes

Probably not optimized very well.

Haskell

int /* x = x -- */ printf(const char*,...); /*
main = putStrLn "This program wasn't written in C, it was built for Haskell!"
-- */ int main () { printf("This program wasn't written in Haskell, it was built for C!"); }

C

int /* x = x -- */ printf(const char*,...); /*
main = putStrLn "This program wasn't written in C, it was built for Haskell!"
-- */ int main () { printf("This program wasn't written in Haskell, it was built for C!"); }
\$\endgroup\$
4
  • \$\begingroup\$ FYI I could cut some whitespace to save bytes, but I don't feel like that'd improve the answer by much. \$\endgroup\$
    – Cubic
    Sep 7, 2015 at 5:30
  • \$\begingroup\$ Got it down to 173 \$\endgroup\$ Apr 20, 2018 at 7:08
  • \$\begingroup\$ Aren't the Haskell/C strings mixed up? That should be really easy to fix. \$\endgroup\$
    – dfeuer
    Mar 4, 2019 at 21:20
  • \$\begingroup\$ @EsolangingFruit this skips the declaration of the output function, which I wanted to include so it compiles without warnings. Could save a couple bytes by using puts instead of printf though. \$\endgroup\$
    – Cubic
    May 17, 2019 at 10:42
5
\$\begingroup\$

Ruby 2.1.5/JavaScript, 189

i
=begin
=9;n=console.log;end='';y
=end
//=~'';def n(x);puts x;end
n("This program wasn't written in "+(f=['JavaScript','Ruby'])[b='k'.match(/[^\W]/i)?0:1]+", it was built for "+f[1-b]+"!")

This does some simple polyglot manipulation to make n a function that prints to stdout. That's the only polyglot trick. The real trick is that Ruby has a bug in the Regexp matcher wherein "k" and "s" do not match /[^\W]/i due to case-folding. It's in the official documentation, too.

Anyway, to Ruby, this looks like:

i       # a pointless variable declaration
=begin
  This is a block comment
=end
//=~''; # just a pointless regex evaluation

# declare a method `n` which puts to stdout
def n(x)
  puts x
end

# call n.  b will equal 1 since this erroneously fails to match.
n("This program wasn't written in "+(f=['JavaScript','Ruby'])[b='k'.match(/[^\W]/i)?0:1]+", it was built for "+f[1-b]+"!")

And to JavaScript, it looks like:

i=begin=9;  // pointless assignment of i and begin to 9
n=console.log; // set up `n` as a function to log to stdout

// more pointless assignments....
end='';
y=end

// comments
//=~'';def n(x);puts x;end

// call n.  b will be 0 because JS does not share Ruby's bug.
n("This program wasn't written in "+(f=['JavaScript','Ruby'])[b='k'.match(/[^\W]/i)?0:1]+", it was built for "+f[1-b]+"!")
\$\endgroup\$
6
  • \$\begingroup\$ I realize that it'd be shorter to use the truthiness of 0 in both languages, but I've been looking for a way to exploit this bug for months. \$\endgroup\$ Sep 3, 2015 at 19:39
  • \$\begingroup\$ The polyglottishness was stolen outright from a younger me \$\endgroup\$ Sep 3, 2015 at 19:48
  • \$\begingroup\$ That's a great bug! Seems to be fixed in the latest Ruby, too, so you could use it to distinguish between 2.1 and 2.2. \$\endgroup\$
    – histocrat
    Sep 4, 2015 at 1:58
  • \$\begingroup\$ What version of ruby is this meant to run in? I just get undefined local variable or method 'i' for main:Object (NameError) when I try to run it on 2.2.3p173 \$\endgroup\$
    – Shelvacu
    Oct 31, 2015 at 0:44
  • \$\begingroup\$ @Shel v2.1.5. It should also work in 2.0.0 and maybe even 1.8.7 \$\endgroup\$ Nov 1, 2015 at 3:46
5
\$\begingroup\$

Haskell / Literate Haskell (195 bytes)

I hope this isn't cheaty, but I fully intended it to be cheeky!

main = putStrLn "This program wasn't written in Haskell, it was built for Literate Haskell!"
{-

> main = putStrLn "This program wasn't written in Literate Haskell, it was built for Haskell!"

-}
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Can you remove the spaces around = and putStrLn? \$\endgroup\$ Nov 19, 2017 at 3:28
5
\$\begingroup\$

Hugs 98 Haskell/GHC Haskell, 203 bytes

Edit: Please also see this version, which is more interesting, and now shorter as well!

This takes advantage of an accidental change in the strictness of foldl' in the base library that came with GHC 7.10. Said change was noted several years ago, but has not been reverted. The "version names" I've used are a bit bogus, but they mirror the ones on TIO. It would be trivial to use something different.

import Control.Exception
import Data.List
p#q=putStrLn$"This program wasn't written in Haskell"++p++", it was built for Haskell"++q++"!"
main=handle(\ErrorCall{}->""#"98")$foldl'(!)(error"")[1]
_!_="98"#""

Try it online (GHC)

Try it online (Hugs)

\$\endgroup\$
3
  • 1
    \$\begingroup\$ You can shorten (ErrorCall _) to ErrorCall{}. \$\endgroup\$ Mar 11, 2019 at 22:14
  • \$\begingroup\$ @ØrjanJohansen, heh, I made a similar suggestion to someone else recently! Thanks. \$\endgroup\$
    – dfeuer
    Mar 11, 2019 at 22:33
  • 1
    \$\begingroup\$ 201 bytes \$\endgroup\$ Mar 11, 2019 at 23:38
4
\$\begingroup\$

Selectors Level 4/Selectors Level 3, 148 chars

:has(*){--a:4;--b:3}*{--a:3;--b:4;content:"This program wasn't written in Selectors Level "var(--a)", it was built for Selectors Level "var(--b)"!"}

It works like this:

  • I assume a HTML document with a root element (<html>) and some child (<body>). Those should be generated automatically by the HTML parser, even if they aren't in the source code.
  • * will match <html>
  • I assume support of CSS Custom Properties for Cascading Variables Module Level 1. This will create the variables --a and --b.
  • In Selectors Level 3, :has(*) in an invalid selector, so it's ignored silently.
  • In Selectors Level 4, <html> matches :has(*), which has more specificity than *. This will modify the variables.
  • I assume support of CSS3 Generated and Replaced Content Module. The content property will replace the contents of <html> with the desired string, which uses var() to read the variables.

I think it should work, but I don't have any implementation to test it.

Thankfully, the name of the spec is only "Selectors Level X" instead of "CSS3 Selectors and Foo for Bar Module Level X".

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Only Opera 12 supports content for real elements. Not sure, but probably you need to use pseudoelement. What does specification sais about it? And at the moment only Firefox supports css variables. \$\endgroup\$
    – Qwertiy
    Sep 4, 2015 at 13:55
  • \$\begingroup\$ Just a little note: Selectors Level 4 does not imply support for CSS Custom Properties for Cascading Variables Module Level 1 or CSS3 Generated and Replaced Content Module. \$\endgroup\$
    – Toothbrush
    Sep 4, 2015 at 20:27
  • \$\begingroup\$ @Qwertiy But html:after is longer than * (I would have to target html explicitly to avoid displaying the string twice: for html and body) \$\endgroup\$
    – Oriol
    Sep 4, 2015 at 21:15
4
\$\begingroup\$

Brainfuck/Bash 4.3, 849 848 843 bytes

#-[--->+<]>-.[---->+++++<]>-.+.++++++++++.+[---->+<]>+++.[-->+++++++<]>.++.---.--------.+++++++++++.+++[->+++<]>++.++++++++++++.[->+++++<]>-.--[->++++<]>-.-[->+++<]>-.--[--->+<]>--.-----.[++>---<]>++.[->+++<]>-.[---->+<]>+++.--[->++++<]>-.-----.---------.+++++++++++..+++[->+++<]>.+++++++++.-[->+++++<]>-.-[--->++<]>-.+++++.-[->+++++<]>-.+[->++<]>.---[----->+<]>-.+++[->+++<]>++.++++++++.+++++.--------.-[--->+<]>--.+[->+++<]>+.++++++++.+++[----->++<]>.------------.-[--->++<]>-.+++++++++++.[---->+<]>+++.--[->++++<]>-.-[->+++<]>-.--[--->+<]>--.+[---->+<]>+++.[->+++<]>++.[--->+<]>-.------------.+++.++++++++.[---->+<]>+++.++[->+++<]>.+++++++++.+++.[-->+++++<]>+++.+[->++<]>.[-->+++<]>--.--[--->+<]>--.-----------.--[--->+<]>--.++[-->+++<]>+.------.+++++.[--->++<]>
echo -e "This program wasn't written in Bash 4.3, it was built for Brainfuck!"
\$\endgroup\$
5
  • \$\begingroup\$ This doesn't have the ! at the end. All you have to do to fix this is change the ending >- on the Brainfuck line to >-.. \$\endgroup\$
    – Kade
    Sep 3, 2015 at 13:32
  • \$\begingroup\$ @Shebang nope. That point is hidden in the bash version :) \$\endgroup\$
    – rpax
    Sep 3, 2015 at 13:37
  • \$\begingroup\$ ..what? That's not what I said. You do not print an exclamation point when executed in Brainfuck, so this answer is not valid. \$\endgroup\$
    – Kade
    Sep 3, 2015 at 13:43
  • \$\begingroup\$ The ending . you mean is located in Bash 4.3 \$\endgroup\$
    – rpax
    Sep 3, 2015 at 13:44
  • \$\begingroup\$ @Shebang you were right. Instead of adding a ., removing the last - in the first line solved the problem. I forgot about the minus sign in echo -e. Thank you! \$\endgroup\$
    – rpax
    Sep 3, 2015 at 13:58
4
\$\begingroup\$

Python/Boo, 102 bytes

v=1//2
n=("Python","Boo");print"This program wasn't written in "+n[v]+", it was built for "+n[1-v]+"!"

Explanation: Boo's syntax is strongly based on Python's, but it uses // as a C-style comment, whereas Python uses it for integer division.

\$\endgroup\$
4
\$\begingroup\$

JavaScript/JavaScript ES6, 132 130 bytes

var v=[];v[0]=v[1]=" JavaScript";v[[].fill?0:1]+=" ES6";alert("This program wasn't written in"+v[0]+", it was built for"+v[1]+"!")
\$\endgroup\$
4
  • 1
    \$\begingroup\$ You can save 2 bytes by using [].fill or [].find instead of [].values \$\endgroup\$ Sep 8, 2015 at 20:20
  • \$\begingroup\$ And I just noticed you can save another byte by using +!![].fill instead of [].fill?0:1 \$\endgroup\$ Sep 8, 2015 at 20:27
  • \$\begingroup\$ @PatrickRoberts thanks! I didn't notice fill! But, are you sure about the +!![].fill? I make a few tests on online interpreters and firefox and I'm not getting the expected results. \$\endgroup\$
    – frikinside
    Sep 9, 2015 at 7:13
  • \$\begingroup\$ Well the idea is to cast the function to a boolean then a number which is either 0 or 1 based on whether the version is ES6 or not, so that was the idea but maybe it doesn't work in practice \$\endgroup\$ Sep 9, 2015 at 11:38
4
\$\begingroup\$

Commodore 64 Basic/QBasic, 169

In order to get the capitalization right, you'll need to switch your Commodore 64 to character set 2 by pressing <SHIFT> + <C=>.

1 c$ = "QBasic": d$ = "Commodore 64 Basic"
2 if(fre(0) < 0) then e$ = c$:c$ = d$:d$ = e$
3 print "This program wasn't written in "; c$; ", it was built for "; d$; "!"

In Microsoft dialects of Basic, the "fre()" function returns the available free space. Now, QBasic can run on surprisingly low-memory IBM compatibles, so you can't reliably tell QBasic and Commodore Basic apart just by the amount of free space. However, the Commodore Basic version returns a signed 16-bit integer where the QBasic version returns a 32-bit one -- and since the Commodore 64 has more than 32767 bytes free with just a small program, while QBasic, as a real-mode program, will never see more than 1048576 bytes, "fre(0)" will always return a negative number on a C64 and a positive number under QBasic.

Commodore Basic's 80-character-per-line limit and QBasic's autoformatter interact in annoying ways here. For example, I found a neat trick involving an if-then-else statement (invalid in Commodore Basic, but an "end" statement keeps the Commodore interpreter from encountering the invalid bits) -- except that the resulting line is 86 characters long after QBasic's autoformatter gets through adding whitespace. Likewise, line 1 can't be combined with line 2: the result would be 88 characters long after autoformatting.

\$\endgroup\$
4
  • \$\begingroup\$ Why does QBasic autoformatting matter? \$\endgroup\$ Mar 7, 2016 at 0:42
  • \$\begingroup\$ @CatsAreFluffy, QBasic has a combined editor/interpreter. If you type in or load a program with what it considers improper whitespace, it will insert the whitespace for you. \$\endgroup\$
    – Mark
    Mar 7, 2016 at 19:00
  • \$\begingroup\$ So? If you paste an improperly formatted program in, it'll be autoformatted. I just don't get why the pasted-in program has to be formatted properly. If people had to care about whitespace added by the IDE, I'd have to fix every single one of my answers. (Well actually, I think 3 of them are fine, but why is ths so long) \$\endgroup\$ Mar 7, 2016 at 19:08
  • \$\begingroup\$ I'm pretty sure there's a thing called QB64 which allows disabling autoformatting. \$\endgroup\$ Apr 2, 2016 at 19:56
4
\$\begingroup\$

Java/Groovy, 190 186 184 181 bytes

class A{public static void main(String[]a){String Groovy=" Java",Java=" Groovy";System.out.print("This program wasn't written in$Java, it was built for$Groovy!".replace('$',' '));}}

Ungolfed:

class NotThatLanguage {
  public static void main(String[] args) {
    String Groovy=" Java", Java=" Groovy";
    System.out.print("This program wasn't written in$Java, it was built for$Groovy!".replace('$', ' '));
  }
}
\$\endgroup\$
4
\$\begingroup\$

Mathematica 9/Mathematica 10, 115 bytes

Print["This program wasn't written in",a=" Mathematica ",If[b=Now==Now,9,10],", it was built for",a,If[b,10,9],"!"]

A bit late to the party... In Mathematica 9, Now remains unevaluated, and therefore equals itself. In Mma 10, each evaluation has a slight time offset, causing the two Nows to be unequal.

\$\endgroup\$
2
  • \$\begingroup\$ You could replace the print function with ""<>{} with those strings as parameters to shave of a byte since Mathematica prints the evaluation implicitly. <> is shorthand for StringJoin. \$\endgroup\$
    – Pavel
    Oct 26, 2016 at 23:52
  • \$\begingroup\$ @Pavel The Mathematica REPL is not considered to be a full program. \$\endgroup\$ Oct 27, 2016 at 0:05
4
\$\begingroup\$

MATLAB / Octave, 118 116 Bytes

x=all(version-82);s={'Octave','MATLAB'};
fprintf('This code wasn''t written in %s, it was built for %s!',s{2-[x ~x]})

This works because version returns something like: 8.4.0.150421 (R2014b), in MATLAB, and 3.6.2 in Octave. version-82 will contain a zero if there is an R in the version name. all(version-82) gives true if there are only non-zero values, and false if one value is zero.

\$\endgroup\$
4
\$\begingroup\$

PowerShell 2/PowerShell 3, 144 118 Bytes

$p="PowerShell ";$a,$b=try{$d=[ordered]@{};3,2}catch{2,3}"This program wasn't written in $p$a, it was built for $p$b!"

Saved a bunch of bytes thanks to @Matt

There are probably other ways of doing this, but this is a simple one, and relatively short. The [ordered] keyword was only introduced with PowerShell v3 and later, which means that PowerShell v2 doesn't support it. A simple try/catch to set the appropriate variables, and we're off and running. (Note that the $d= is necessary to suppress setting $a to the hashtable and $b to an array when run on PowerShell 3.)

\$\endgroup\$
1
  • \$\begingroup\$ I would replace the try block with this instead $a,$b=try{$d=[Ordered]@{};3,2}catch{2,3} pretty sure that will work the same and is shorter all around \$\endgroup\$
    – Matt
    Oct 27, 2016 at 12:00
4
\$\begingroup\$

Emoji/Emojicode, 170 bytes

👴💬This program wasn't written in Emoji, it was built for Emojicode!💬➡
🏁🍇😀🔤This program wasn't written in Emojicode, it was built for Emoji!🔤🍉

Try Emoji online!
Try Emojicode online!

\$\endgroup\$
4
\$\begingroup\$

Excel / Google Sheets, 128 126 Bytes

Anonymous worksheet function that takes no input and outputs to the calling cell.

="This program wasn't written in "&IfError(M("Google Sheets, it was built for Excel"),"Excel, it was built for Google Sheets")

Or

="This program wasn't written in "&Substitute(IfError(M("Google Sheets1Excel"),"Excel1Google Sheets"),1,", it was built for ")
\$\endgroup\$
4
\$\begingroup\$

C++ (gcc) / R, 163 bytes

#include<cstdio>
#define cat(x)x
#define sprintf(a,b,c)int main(){printf(a,c,b);}
cat(sprintf("This program wasn't written in %s, it was built for %s!","R","C++"))

C++ (gcc) : Try it online!

R : Try it online!

# is the comment character in R, so using preprocessor's magic of C++ we can switch between the two languages

\$\endgroup\$
4
\$\begingroup\$

Haskell GHC/Hugs98, 199 bytes

I've already written a different program for these language variants, but I think this one is much more clever. And now, it's also shorter!

Thanks to @ASCII-only for suggesting putStr instead of putStrLn. Thanks to @ØrjanJohansen for suggesting id rather than a custom operator for a related answer, and then shedding a full 30 bytes by realizing the Num instance can be left empty.

instance Eq(a->b)where _==_=0<1
instance Show(a->b)
instance Num(a->b)
p#q=putStr$"This program wasn't written in Haskell"++p++", it was built for Haskell"++q++"!"
main|(0`id`)==1=""#"98"|0<1="98"#""

Try it online (GHC Haskell)

Try it online (Hugs98 Haskell)

Explanation

Hugs 98 used a "relaxed" interpretation of operator sections, where (x!) meant (!) x. In even vaguely recent times, GHC has only used that relaxed interpretation when a certain language extension is enabled. The rest of the time, (x!) means \y -> (!) x y. The latter (more strictly standards-compliant) interpretation can cause the type constraints on (x`id`) to be stronger. In particular, it requires id to be a function of (at least) two arguments.

Haskell has a mechanism for defaulting ambiguous types under certain narrow conditions. The defaulting mechanism is just sensitive enough to the imposed constraints that we can detect the difference in operator section interpretation.

Open questions

  • Is it possible to cut the code size down? I'm not terribly happy with the way I actually put the strings together.
  • Is it possible to use Haskell's special rules for pattern matching on numeric literals without increasing the code size? That would make it even golfier, IMO.
\$\endgroup\$
3
  • \$\begingroup\$ Wait, why not putStr \$\endgroup\$
    – ASCII-only
    Mar 11, 2019 at 9:45
  • \$\begingroup\$ @ASCII-only, fixed. \$\endgroup\$
    – dfeuer
    Mar 11, 2019 at 22:12
  • 2
    \$\begingroup\$ This is too lazy to ever evaluate a function number literal, so just instance Num(a->b) will do. \$\endgroup\$ Mar 12, 2019 at 0:20

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.