14
\$\begingroup\$

Create a program that can be run in 4 different languages such that:

  • One language prints "Hello World!"
  • One language outputs its own source code
  • One language outputs 99 bottles of beer on the wall, that is:
    99 bottles of beer on the wall
    99 bottles of beer
    Take one down, pass it around
    98 bottles of beer on the wall
    
    98 bottles of beer on the wall
    98 bottles of beer
    Take one down...
    
    <the pattern continues for a while>
    
    ...pass it around
    1 bottle of beer on the wall
    
    1 bottle of beer on the wall
    1 bottle of beer
    Take one down, pass it around
    No more bottles of beer on the wall
    
  • One language takes a nonnegative integer as an input and outputs that integer + 1

Rules and Scoring

  • This is code golf, so shortest code wins. Score in character count rather than byte count for this challenge so that golfing languages that use specialized codepages are not disadvantaged by their UTF-8 representations.
  • Standard rules and loopholes apply
  • Each language may optionally output a trailing newline for its designated output
  • Each language may use any I/O convention that is convenient to that language. The convention does not need to be consistent across all four languages; for instance, one uses stdout, another uses the return value, one writes to a file, and the last one spawns an alert containing the text.
  • Golfing languages that have the option to use specialized codepages must use a standard encoding; they may not take advantage of a byte being interpreted as a different character in another encoding.
  • Hello World may optionally include a comma after "Hello", thus Hello, World! is a valid output.
  • Standard quine rules apply and the only superfluous output allowed is a trailing newline.
    • Text, or any other "language" where all programs are quines, is not a valid language for the quine.
  • 99 Bottles of Beer requires:
    • A blank line between each verse
    • No blank lines within any verse
    • The singular/plural distinction of 'bottle' vs 'bottles'
    • no more instead of 0 on the last line
    • Each line may have any amount of trailing whitespace (or none at all)
  • The incrementing program must support all input integers that can be incremented natively by its language.
    • For languages which support unsigned integers, the largest unsigned integer should be used
    • For languages which represent all numbers as floating point numbers, this would require supporting all input numbers up to \$2^{53}-1\$.
    • For languages which natively support arbitrary-sized integers, all positive integers must be supported.

Format the header of your answer like this:

# <language for H, <language for Q>, <language for 9>, <language for +>, n characters
\$\endgroup\$
7
  • 4
    \$\begingroup\$ Even if you score in byte count, golfing languages with code pages still get to score their code in characters! \$\endgroup\$ – null Aug 12 '20 at 3:40
  • \$\begingroup\$ Regarding "standard encoding": the usual definition of "polyglot" is that there must be a file that can be run in the interpreters without any encoding change, and the score is the byte count of that file. (also it's the least ambiguous definition.) \$\endgroup\$ – user202729 Aug 12 '20 at 9:14
  • 1
    \$\begingroup\$ FWIW, I don't think the + in HQ9+ inputs or outputs anything. \$\endgroup\$ – user253751 Aug 12 '20 at 19:58
  • 1
    \$\begingroup\$ @user That is correct, however this challenge is only inspired by HQ9+, not an implementation of the language. \$\endgroup\$ – Beefster Aug 12 '20 at 20:03
  • 2
    \$\begingroup\$ The header format can be golfed to # <language for H>, <language for Q>, <language for 9>, <language for +>, n characters. \$\endgroup\$ – Bubbler Aug 13 '20 at 2:41
8
\$\begingroup\$

Ruby, ><>, HQ9+, Befunge-93, 62 characters

#9&1+.@.10[0[fr'
puts"\u0048ello World!"#.1*57;!?lo r]r}:*3da'

"Hello World!" (Ruby)

Relevant part of code:

puts"\u0048ello World!"

quine (><>)

After colliding with the # mirror, both lines are read as string literals and printed with a newline between.

99 bottles of beer on the wall (HQ9+)

Code contains no H or Q, and exactly one 9, so the lyrics of the song are printed once.

+1 program (Befunge-93)

After jumping over 9 due to the # trampoline, a simple +1 program is run &1+.@

\$\endgroup\$
1
  • 3
    \$\begingroup\$ Argh! You beat me to the punch! (Oh, and HQ9+ is not a valid language.) \$\endgroup\$ – null Aug 13 '20 at 2:39
6
\$\begingroup\$

Python 2, Perl 5, JavaScript (Node.js), Ruby, 524 characters

0//1;q=0;print"Hello, World!";'''/.__id__;puts STDIN.read.succ;%q[=;$_=q{print q@0//1;q=0;print"Hello, World!";'@.qq@''/.__id__;puts STDIN.read.succ;%q[=;\$_=q{$_};eval;q[\n@.q@for(x=99,z=(a=' on the wall\n')=>`${x||'No more'} bottle${1-x?'s':''} of beer`+a;x;)console.log(z()+z(n='\n')+'Take one down and pass it around\n'+(x--,z()))//]#]#'@.q@''@};eval;q[
for(x=99,z=(a=' on the wall\n')=>`${x||'No more'} bottle${1-x?'s':''} of beer`+a;x;)console.log(z()+z(n='\n')+'Take one down and pass it around\n'+(x--,z()))//]#]#'''

Hello, World!, Python 2

Pretty straightforward, this performs integer division in void context, then sets q to 0, prints Hello, World! and the rest of the program is contained in a ''' quoted multi-line string. With long, unprocessed, strings removed:

0//1;q=0;print"Hello, World!";'''...'''

Try it online!

Quine, Perl 5

Probably the most complicated, but not overly. It's a pretty standard $_="...";eval quine template, but we have to include the preceding code for other languages too. The 0//1 performs integer division in a void context and then q=...= is a single-quoted string delimited by = in a void context. Then the quine is built into $_ using an @-delimited string. I switched from using $< in Ruby for STDOUT to avoid having to keep switching in and out of quotes more, although I ended up having to do that for Python 2's ''' anyway, which needed to be broken up to avoid being triggered. Once $_ is built, eval is called and the rest of the program is contained in q[...] (a [...] delimited, single-quoted string). Here's a simplified version:

0//1;q=...=;$_=q{print q@...'@.qq@''...=;\$_=q{$_};eval;q[\n@.q@...'@.q@''@};eval;q[...]...

Try it online! Verification.

99 bottles of beer, JavaScript (Node.js)

JavaScript is relatively easy to have in other code as // comments out the rest of the line, so 0//1 is just 0 in void context, followed by a comment and the string closing delimiters of the other three languages are avoided using // too.

I borrowed the main code from here for this, amending as necessary as using \n instead of a literal newline was slightly easier for the quine contents.

0//...
for(x=99,z=(a=' on the wall\n')=>`${x||'No more'} bottle${1-x?'s':''} of beer`+a;x;)console.log(z()+z(n='\n')+'Take one down and pass it around\n'+(x--,z()))//...

Try it online!

Accumulator, Ruby

This uses a technique I've used in quite a few polyglots with Ruby in the past. The 0//.../.__id__ construct is parsed as 0 dividede by the __id__ property of the /.../ regex (__id__ is chosen as it's a short property that returns a number to avoid a type mismatch error). Then STDIN.read.succ returns the next string that succeeds it, so 9 results in 10, etc. The rest of the code is wrapped in %q[...] effectively hiding it.

0//.../.__id__;puts STDIN.read.succ;%q[...]#...

Try it online!


Python 2, Perl 5, HQ9+, Ruby, 181 characters

Using HQ9+ for the 99 Bottles implementation, reduces code size considerably:

0//1;q=9;print chr(72)+'ello, World!'#/.__id__;puts STDIN.read.succ;#=;$_=q{print"0//1;q=@{[1^8]};print chr(72)+'ello, World!'#/.__id__;puts STDIN.read.succ;#=;\$_=q{$_};eval"};eval

Hello, World!, Python 2

Try it online!

Quine, Perl 5

Try it online! Verification.

99 bottles of beer, HQ9+

Since the code only contains 9 from HQ9 (and + doesn't cause any output) it's all that's executed. My main worry with this is finding an interpreter that complies with the requirements, which might make this invalid perhaps.

9

Accumulator, Ruby

Try it online!

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Very nice! You can shave 16 bytes off the Ruby by replacing STDIN.read with gets and __id__ with hash. \$\endgroup\$ – Dingus Aug 13 '20 at 23:24
  • \$\begingroup\$ Ahhh, nice. Didn't think of hash!. gets` makes so much more sense too... Thank you! \$\endgroup\$ – Dom Hastings Aug 14 '20 at 7:10
4
\$\begingroup\$

Help, WarDoq!, Befunge-98 (FBBI), HQ9+, SOGL, 15 characters

I←9La@,+1!',kf"

I already feel bad for writing this. At least the quine is not in PHP.

Explanation

Help, WarDoq!

Ignores the first 3 characters, L prints Hello World! and a tries to read 2 integers (and exits with an error).

Befunge

Mostly stolen from this. I bounces unless redefined by a fingerprint, so it can be used instead of the starting <.

HQ9+

I used the interpreter http://web.archive.org/web/20060714044320/http://www.safalra.com/programming/interpreters/hq9plus/. Its output is very similar to the lyrics in the question, but, unfortunately, it's not exactly the same. When I found it, I assumed that there is at least one HQ9+ interpreter that outputs the correct lyrics. However, finding it is left as an exercise to the reader. and since the challenge is inspired by HQ9+, how can HQ9+ be wrong?

SOGL

Implicit input, then I increments and exits (with implicit output).

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

Trigger, Ruby, Fortran (GFortran), COW, 371 370 characters

!t='HHHeeelll lllooom   WWWooorrrlllddd!!!MoO  qOOM
character*40::w=" on the wall",f="(a,/,a,/,a)",n,b
do i=99,1,-1
write(n,"(i2)")i
j=3
if(i<10)j=2
k=7
if(i<2)k=6
b=adjustl(n(:j))//"bottles"(:k)//" of beer"//w
if(i<99)print f,b
print f,b,b(:j+k+9),"Take one down, pass it around"
enddo
print"(a)","No more bottles"//b(9:)
end!';eval$s=%q($><<"!t='#{t}';eval$s=%q(#$s)")

What an unholy combination this is!

Hello World!, Trigger

The idea to use Trigger came from some of the answers to this question. The main advantage is that it's relatively easy to embed within other garbage. The interpreter effectively sees

!t='HHHeeelll lllooom   WWWooorrrlllddd!!!MoO  q
q($><<"!t='#{t}';eval$s=%q(#$s)")

Try it online!

The functional part is HHHeeelll lllooo WWWooorrrlllddd!!!: triple letters are printed once. (The space between the two lll groups is needed for proper parsing.) The q (two leading spaces) at the end of the first line is essential to avoid double letters later in the full code (such as those in bottles and beer) that would otherwise create conditional jumps with hard-to-predict consequences. (Indeed, without q the code appears to enter an infinite loop.) This possibility is headed off by jumping forward to the next q, which happens to be in the last line of the full program. As far as the outside world is concerned, the remainder of the program is no-ops.

Quine, Ruby

The full program is really just a straightforward extension of the Ruby quine

eval s=%q(puts"eval s=%q(#{s})")

with two modifications: (i) the global variable $s saves a byte on the string interpolation and (ii) $><< is used instead of puts to avoid a trailing newline. The rest of the program defines a string variable t, which contains all the functional code for the other three parts of the polyglot. The exclamation mark (negation) in !t at the top of the program is effectively a no-op (though a warning is emitted to STDERR).

Try it online! or verify quinehood (thanks to @DomHastings for the idea)

99 Bottles of Beer, Fortran

This part of the code accounts for 74% of the total character count. Fortran's string manipulation capabilities are truly horrendous, but it's one of the few languages I'm proficient enough in to golf 99 Bottles from scratch.

As ! is the comment character in Fortran, the compiler sees

character*40::w=" on the wall",f="(a,/,a,/,a)",n,b
do i=99,1,-1
write(n,"(i2)")i
j=3
if(i<10)j=2
k=7
if(i<2)k=6
b=adjustl(n(:j))//"bottles"(:k)//" of beer"//w
if(i<99)print f,b
print f,b,b(:j+k+9),"Take one down, pass it around"
enddo
print"(a)","No more bottles"//b(9:)
end

Try it online!

Except for the first and last verses, each iteration of the loop actually prints the last line of the previous verse followed by the first three lines of the current verse.

Increment, COW

As COW completely ignores all non-instructions, all that the interpreter sees is

oomMoOOOM

Try it online!

This is a simple sequence of three operations: read an integer from STDIN (oom), increment it (MoO), and print to STDOUT (OOM). TIO's COW interpreter uses signed 32-bit integers so the largest input for which the output is correct is \$2^{31}-2\$.

\$\endgroup\$
3
\$\begingroup\$

Hello++, H🌍, 99, brainf***, 5 characters

#H,+.

"Hello World" in Hello++

According to the language spec:

Hello++ will print out "Hello World" whenever it encounters 'h' or 'H'. It ignores all other characters silently.

So it prints out "Hello World" when it encounters that H and ignores everything else.


Quine in H🌍

The only needed characters in H🌍 are "h", "w", and "q". All incorrect programs become quines.


99 bottles of beer in 99

All valid programs in 99 print the lyrics to the song we all love. For a program to be valid, it just needs to start each line with a #


+ in brainf***

All the characters before ,+. are ignored, and those last three read a number, increment it, and print, respectively.


I'm not sure if this is valid, but if it isn't, just let me know and I'll remove it.

\$\endgroup\$
8
  • 1
    \$\begingroup\$ Does this work for 3 bytes? (I changed brainfuck to V for +) \$\endgroup\$ – the default. Aug 16 '20 at 4:06
  • \$\begingroup\$ @mypronounismonicareinstate Cool! How does that work? (I couldn't find anything on the V wiki) \$\endgroup\$ – user Aug 16 '20 at 23:45
  • 1
    \$\begingroup\$ I haven't used any V-specific commands, my proposed golf is basically pure vim (but encoded in bytes rather than keystrokes). # finds the previous occurrence of the number (and doesn't find anything, as it is the only thing in the buffer), H moves to the first line on the screen (since the line with the number is the only line, this also does nothing), and the SOH byte is equivalent to a Ctrl+A keypress which increments the number (incrementing and decrementing are the only built-in vim math commands I know about). \$\endgroup\$ – the default. Aug 17 '20 at 3:03
  • 2
    \$\begingroup\$ The Gol><> comment was wrong: the lowercase h in it would break the H🌍 part. \$\endgroup\$ – the default. Aug 17 '20 at 3:06
  • 1
    \$\begingroup\$ We have a winner. \$\endgroup\$ – null Aug 30 '20 at 4:32
2
\$\begingroup\$

brainf***, Java, Groovy, Whitespace, 1461 bytes

A tad long, but I'm sure it can be golfed further

class   Q{//++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.>[
public static void main(String[]a){
    
Character   c=10;char   Q=34;char   w=32;char   t=9;String  x="classzz$Q{//++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.>[#publiczstaticzvoidzmain(String[]a){#%#Character%c=10;char%Q=34;char%w=32;char%t=9;String%x=WXW;if(x.contains(WW+Q)){StringzC=WW+c;for(Integerzi=100;--i>0;)z%#%System.out.println(String.join(WW+w,WW+i,i<2?WbottleW:WbottlesW,WofW,WbeerW,WonW,WtheW,WwallW,C.concat(WW+i),i==1?WbottleW:WbottlesW,WofW,WbeerW,C.concat(WTakeW),WoneW,Wdown,W,WpasszitzaroundW,C.concat(i==1?WNozmoreW:WW+(i-1)),i==2?WbottleW:WbottlesW,WofW,WbeerW,WonW,WtheW,WwallW,C));%}#z%else###System.out.println(x.replace((char)122,w).replace((char)35,c).replace((char)87,Q).replace((char)37,t).replace((char)36,w).replace(c.toString(88),x));}}//]";if(x.contains(""+Q)){String C=""+c;for(Integer i=100;--i>0;)    
    System.out.println(String.join(""+w,""+i,i<2?"bottle":"bottles","of","beer","on","the","wall",C.concat(""+i),i==1?"bottle":"bottles","of","beer",C.concat("Take"),"one","down,","pass it around",C.concat(i==1?"No more":""+(i-1)),i==2?"bottle":"bottles","of","beer","on","the","wall",C));   }
    else


System.out.println(x.replace((char)122,w).replace((char)35,c).replace((char)87,Q).replace((char)37,t).replace((char)36,w).replace(c.toString(88),x));}}//]

brainf*** code (ignoring other characters):

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

>[[]++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.>[[].++-->...+,+,<,,,,,,.+,,,,.,,,,,.+-,,,,,,,...,.,.,.,.,..,].++-->...+,+,<,,,,,,.+,,,,.,,,,,.+-,,,,,,,...,.,.,.,.,..,]

Try it in brainf*** online!

Edit: Originally, this didn't work because while testing, I used the wrong version of my code. It's fixed now, but even longer than it was before.

The first line prints "Hello world!", and the second line basically just makes sure the rest of the code never runs by moving to a cell that's 0 and wrapping everything inside square brackets.


Whitespace code (ignoring other characters):

[S] [S] [S] [LF]
[S] [S] [S] [LF]
[T] [LF]
[T] [T] [T] [T] [T] [S] [S] [S] [T] [LF]
[T] [S] [S] [S] [T] [LF]
[S] [T] [LF]
[LF]
[LF]

Explanation:

[S][S][S][L]     ----   push 0
[S][S][S][L]     ----   push 0
[T][L][T][T]     ----   read a number and put it at address 0 in the heap (0 because the top of the stack is 0)
[T][T][T]        ----   retrieve the number at address 0 in the heap
[S][S][S][T][L]  ----   push 1
[T][S][S][S]     ----   add
[T][L][S][T]     ----   print the number at the top of the stack
[L][L][L]        ----   exit the program

Try it in Whitespace online!


Try it in Java online!


Try it in Groovy online!

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

Python 2, Python 3, HQ9+, Python 2 -O, 84 bytes

s="print(8/9and's=%r;exec(s)'%s or __debug__*'\\x48ello World!'or-~input())";exec(s)

Try H online!
Try Q online!
Try + online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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