37. C++ (gcc), 776 bytes
# 1"16" 2//v\(;@#/;n4"14"
#/*`3 auaaZ<>16/"<"6/b.q@")(22)S# ␉␉␉␉
#yy␉;36!@
# ␉
#=␉>
#[#yy#yy0l0mx01k1k0l0ix0jx0h0h1d111P0eU0bx0b0o1d0b0e0e00x1d0i0fx0g0n0n11x0o0n0cx0c0o0f0c0gx0g0f0h0j0j0i0001k10mx0m0l11111100(^_)
#`<`␉|
print((eval("1\x2f2")and( 9 )or(13 ))-(0and 4)^1<<(65)>>(62))or'(\{(\{})(\{}[()])}\{}\{}\{})'#46(8+9+9+9+9+=!)#1|=/=1/24=x=9[<$+@+-@@@@=>+<@@@=>+<?#>+.--.]/
__DATA__=1#//
#.\."12"*␉
""""#//
=begin␉//
#*/
#include<iostream>␉
int main() /*/
#()"`#"\'*/{std::cout<<37;}/*'"`"
$'main'␉//
#-3o4o#$$$
<>3N.<>␉//
#xx
#x%~~~+␉+~*ttt*.x
#xx
=end #//
"""#"#//
#0]#echo 21#/(\[FAC,1<-#2FAC,1SUB#1<-#52FAC,1SUB#2<-#32FACLEGEREEX,1PLEASEGIVEUPPLEASE) ap
#_~nJ|#o51\
#0␛dggi2␛`␉|1|6$//''25 >>>>>#>27.say# =#print(17)#^_^_7LEintndus({})!<>+]/*///Z222999/3!@"26
␉
is a literal tab, ␛
a literal ESC character; Stack Exchange would mangle the program otherwise. I recommend copying the program from the "input" box of the TIO link below, if you want to work on it.
Rundown
This program prints 37 in C++, 36 in Labyrinth, 35 in INTERCAL, 34 in Rail, 33 in Incident, 32 in Whirl, 31 in Modular SNUSP, 30 in Whitespace, 29 in Trigger, 28 in Brain-Flak, 27 in Perl 6, 26 in 05AB1E, 25 in Pip, 24 in Thutu, 23 in Hexagony, 22 in Underload, 21 in Nim, 20 in Prelude, 19 in Reng, 18 in Cardinal, 17 in Julia, 16 in Pyth, 15 in Haystack, 14 in Turtlèd, 13 in Ruby, 12 in Fission, 11 in Befunge-98, 10 in Befunge-93, 9 in Perl 5, 8 in Retina, 7 in Japt, 6 in SMBF, 5 in Python 2, 4 in ><>, 3 in Minkolang, 2 in V/Vim, and 1 in Python 3.
Verification
Most of the languages are tested by the test driver shown above. You can test Reng here and Modular SNUSP here; they output 19 and 31 respectively, as required.
I added another format to the test driver output that escapes double quotes as well as make line feed replacements. This is so I can feed the single line string to a c(gcc) program I wrapped around the function created by @feersum here. Hopefully others can make use of it as is.
Here's the Incident token program. Ideally I'd like to deliminate the tokens since they are a bit hard to read, indicate the "center" token, and include it in the test driver. But I don't really know how to do anything other than make various programs print sequential integers, so this is as far as I've gotten.
I've attempted to solve the obvious Incident problems, like tokens after the beginning and end jump tokens and anything that looked extraneous, but I haven't balanced the tokens to put 0o
at the center. I'm not really sure what the logic is exactly to determine the center. I'm hoping @ais523 will help there. This string near the end 7LEintndus({})!<>+
would all be tokens if not for this 4th inclusion in the code. These can all be removed (and replaced with a .
for Hexagony alignment) in order to adjust the center token.
I'm going to be updating this post off and on over the next day or two to walk through the code, (assuming Incident can be verified/fixed without going over the byte count). But it's super late now, and I mostly wanted to get this out there before I had to solve another Labyrinth like problem. :P
Explanation
##How the C++ code works.
I think most people are familiar enough with C++, so I won’t go into too much detail. Block comments come in the form of /* comment */
. Line comments come in the form of //comment
. The actual code utilized by C++ to produce the answer is int main() {std::cout<<37;}
. And the library that’s used to interface with STDOUT is referenced by this statement #include<iostream>
.
/*Comments Abuse*/
For me, the story of C++ goes back to my Brain-Flak answer.
After finally finding #28, I set out to study some other polyglots posted in PPGC and all that studying led me to a few easy answers (most of these are still available to be found if anyone else is so inclined). But more importantly, I came to a conclusion about polyglots in general: large polyglots tend to fall into one of two broad categories: #
comment abuse or /*
comment abuse.
This is not a fact or restriction in anyway, but of a personal mental framework that guided my next several answers.
From here I reasoned that if this was to become the world’s largest polyglot, which I presume it to be currently, it would be best if it could leverage comment abuse from both comment families. So I set out to find a way incorporate a /*
comment language and pushed towards the C family due mostly to a personal familiarity.
C++ Initial Test
My initial thought process for this was to use C# mostly because of my familiarity and the first hurdle for C# was getting the polyglot into a state where it could accept a line that didn’t start with #
without otherwise being treated as code by the scripting languages. The Rail answer, along with several byte inflating answers that lead up to it, solved this piece.
Next came the problem of how to initiate the first /*
comment block. I knew the line would have to start the line with a #
to remain invisible to Perl, Ruby and Python, but whatever came before the /*
would be read by C#. I attempted a C# #region
tag at first, but that turned out to be too ridged for the 2D languages. Enter C++.
C++ has several preprocessor directives that all start with #
, which give a lot of options for the 2D languages to traverse. But it turned out that all of them were incompatible with at least one language, and being in a C++ exposed code space, I had limited workarounds. Out of frustration and desperation, I stumbled into the fact that C++ would simply accept just a single #
before the comment block. Okay, whatever, that’s workable. So I moved forward with the presumption that #/*
could work as the first three characters in the polyglot.
The second piece of basic verification was to ensure that the actual print statement could live happily with the other codes. I knew from the Brain-Flak answer that Japt didn’t like un-escaped {
’s and that was needed for C++ to say int main() {std::cout<<37;}
and C++ wouldn’t allow Japt’s escape character in the middle of its code. This time I was lucky enough to find that if I dropped out of Japt’s literal string just for this statement, Japt would still happily produce the same result.
Meanwhile, Brain-Flak didn’t like the {}
either, but I was again lucky to find that C++ was ok with a #
between its int main()
and {std::cout<<37;}
statements, allowing the curly braces to be commented out of Brain-Flak’s perspective.
So, with the main problems of C++ proven to be theoretically solvable, I began the arduous process of resolving all the errors I’d introduced.
2D Landscape
The hardest part of this answer was by far the reconfiguration of the top two lines of the polyglot. And the most significant problem was the *
. Underload will not allow a *
prior to a (
. It considers this as math operation on an empty stack, which it feels is an error. So the polyglot required a (
prior to the /*
but C++ couldn’t allow this. So the solution was to us a C++ line comment //
on the first line to hide a (
and then start the second line with a #/*
.
Next, Befunge really didn’t like the idea of a /
without something being divided but after studying the existing Begunge answer of 16/"<"6/b.q@
I stumbled on the idea of a number and a string smashed together ahead of the //
. It worked and I have no idea why C++ is ok with this but it accepts # 1"16" 2
as it’s opening statement. I’m not going to question it, but I do know that the spaces are required for it to work.
##Line One
Japt turned out to be rather space sensitive and didn’t really want to enter into its backtick based string on the top line, so it and Pip’s backtick got moved to the second line, forcing a lot of linguistic gymnastics on line 1.
- Pip didn’t like most of line 1, so a second space was placed after the first
#
to indicate a comment. - The
(
for Underload had to be escaped out of Japt with a preceding\
. #
is a jump terminator in Turtlèd so it was required, but Pyth considers this a error terminating loop, so Pyth needed a divide by null/
after the#
- I’m not sure what the
@
in the first line is doing anymore, but Pyth and Japt seem to like it’s presence better than not, although@
is not a meaningful character according to Pyth’s documentation. - And it looks like the first
;
can be removed at this point without consequence, so I’m not sure what was being solved there anymore, although I suspect it was Pyth related. But it looks like future solutions can save a byte by omitting that one. - <>< and Turtlèd both basically work the same as before with <>< reflecting on the first
#
and wrapping to the end of line one. And Turtlèd jumps with#
like I mentioned and ends with the"14"
string which it prints.
##2D routing
With these issues resolved, the next phase was routing the 2D languages. Previously the initial v
was ignored by the Befunges due to the preceding #
, but sent Haystack and Minkolang down. Now, the initial space attempts to send Minkolang along the 3rd dimension, which its documentation refers to as the time dimension.
Quick aside on Minolang’s 3rd dimension: to me it’s something of a misnomer to call this a time dimension it really seems more spacial than temporal to me. I didn’t really get it until I found this link that illustrates the concept, and it seems more like the multiple layers of a 3D chess board. My belief is that this is how 3D languages generally operate. But as this was a new concept to me, I thought I’d throw this info out for others.
So Minkolang’s multiple layers are delimited by lines ending in $$$
which I threw onto the end of the Rail code here: #-3o4o#$$$
. Now, Minkolang hits the space and falls to first >
in <>3N.<> ␉//
and proceeds to the right outputting 3. #>
couldn’t be allowed to start this line because it would attempt to terminate a Perl6 comment block, so <
is used instead of #
to balance for SMBF and Brain-Flak. However, this is a Brain-Flak stack swap procedure, so a second set of <>
is used after Minkolang Terminates in order to swap back to Brain-Flak’s correct answer.
Labrynth similarly bumps up against the space but it causes Labrynth to moves down in column 1. It then turns down line 2 where it travels down to the 3
hits another wall, causing it to turn south again and hit a ;
which causes the 3 to get popped. Then the program continues to the right where 36 gets stored and printed, before finally finding a @
exit. This path is longer than it needs to be, but I found that Prelude would output a nul byte before it’s normal 20 output if the !
was any further to the left than it is now, regardless of the line it appears. So I made it more correct, because I had the space to do so.
Next, Haystack’s routing got changed because /
now comes prior to v
on line 1 and reflects its path up like Reng. Fortunately, Reng cohabitates rather peacefully. The one hitch was that Haystack’s needle |
was a reflector in Reng, so a Reng uses a Befunge like jump (#
) over the needle to conclude Reng correctly.
The Befunges continue along line 1 until the v
and get directed down and then to the right on the second line to conclude with the same code used before. My sense is that this piece can be golfed down a bit now that fewer languages are attempting to meaningfully traverse the code, but I didn’t need any more walls to bang my head against, so I left it as is.
Finally, Cardinal’s starting point is %
which had not particular need to be lumped in to the already dense top two lines. So I moved it down to Python’s string. Its multiple code paths are also now bounded by x
’s, which ends the movement of its pointer.
Line 2 &3
The only significant change here is that all of the :
got golfed out for one reason or another. Maybe Prelude’s (
needs or maybe it was simple byte count problems – probably both. The other thing is that trigger’s jump code got moved back and rebranded as auaaZ
. I had space to fill to meet Befunge’s code path and this seemed best. Also the <
following this piece is to balance SMBF’s following >
. Finially, the lone ”
near the end of the second line are to maintain 05AB1E’s string. Also, yy
on line 3 are just filler characters for Labyrinth.
The Big String Esolangs
With the top two lines resolved, it was time to start digging into the fuller-parsing esolangs, and Pip turned out to have a problem. If you remember we dealt with the curly braces in {std::cout<<37;}
by dropping out of the Japt string to let Japt treat this as code. Well, Pip is using the same string syntax and didn’t like this line as code and Pip has very similar string declaration options as Japt. Both use a single '
to declare a one character string, both use the same escape declaration of \
and both will accept "
as string identifiers. So it was difficult to make Pip believe this was a string without making Japt believe the same.
It turned out that Japt did have one exploitable difference though - #
takes the ascii value of the next character. So, #"`
will terminate the Japt/pip string, then tell Japt to take the asci value of "
, while telling Pip to start a new string. The "
probably could have been a backtick instead, and probably would have been better, but my line of thinking was to use a different string identifier on the inside as another point of string manipulation. So here’s another place where you could save a few bytes down the road.
Next, I had to initiate the Japt string after the curly braces while allowing Pip to remain in a string. I did this with '"`
that's a single quote, double quote, and a backtick. For Japt the '
is not in a string and is therefore an indicator to take the next character as a single char string. Pip sees the '
as part of the string and terminates its string with the "
. And finally, `
is indicates to both Pip and Japt that another string is beginning which continues throughout the polyglot until the last line where both languages complete happily.
Now, both Japt and Pip worked at this point, but 05AB1E failed because of the use of "
caused some error inducing code exposure. Fortunately this one was easy enough to solve by putting another set of "
around the whole thing, leaving the set of string manipulations as "`#"\\'*/{std::cout<<37;}/*'"`"
.
Finally, with the line now looking like this,int main() #/*"`#"\'*/{std::cout<<37;}/*'"`"
which Underload had a problem with. The consecutive *
’s, were another syntax error so I threw a ()
in the middle of the *
’s to appease it.
The Fragile Esolangs
The big hurdle now was White Space. I won’t go into a ton of detail here because most of the Whitespace solution is built into the explanations already given, and I just glossed over the instances where whitespace forced a few decisions. I’m looking at you Labyrinth. The big change though, is that the actual code to output Whitespace’s answer is on line 2-4 instead of 1-3. This is largely due to Japt’s code exposure in line 1.
Thutu originally had problems with what had been this line: int main() #/*()"`#"\'*/{std::cout<<37;}/*'"`"
. So, I threw in a linefeed just before the first #
to hide all the problems behind a comment indicator and then spammed out a bunch of trailing /
’s everywhere else that was code exposed.
At this point I aligned Hexagony and found new problem. The code at the very beginning, which started life as # 1"16" 1
made the +
in /+23!@
no longer clear the stack. So, I just removed the +
is and found it now output 123. This was easy enough to fix by changing the opening gambit to # 1"16" 2
and golfing the Hexagony piece down to /3!@
.
Whirl had some changes, but it was mostly a matter of making sure the right number of leading 1s appeared before the Whirl-Incident line. Incident though had one token that was particularly difficult. I had exactly 3 copies of /*
and */
.
I initially wanted to just throw *//*
any old place in the code to create a 4th copy of each, but Underload saw consecutive *
’s again, which was a no go. Ultimately I threw a /
on the end of this line int main() /*
to make it end in /*/
, thinking that I’d make the tokens overlap, but I only succeeded in creating 4 copies of one of the two tokens. Right, right. That’s how that works. Oh well, I’ll just throw a similar /
in the final */
to make a 4th there. After this, I replaced a bunch of hexagony no-ops with a 4th copy of several incident tokens in this string on the final line 7LEintndus({})!<>+
.
Conclusion
Ok, that's all the detail I have for this massive refactor. I promise not to have so much to write about next time. I actually have no idea if C++ is a good or bad choice for this polyglot, but my sense it opens some options. Hopefully this leads to good things.
Happy coding.