19
\$\begingroup\$

Introduction

A quine is a program that outputs its own source code. For example, a well-known Python quine is _='_=%r;print(end=_%%_)';print(end=_%_). Running it outputs _='_=%r;print(end=_%%_)';print(end=_%_), therefore it is a valid quine. An error quine is similar to a regular quine, however it must output to STDERR. In Python (for example), this could be achieved by replacing both instances of print in the above code with exit. A polyglot is a program that is valid in multiple languages.

Challenge

Write two full programs in two programming languages of your choice. The first one should be a quine, and the second an error quine. When concatenated (in any order, you can pick), it should form a Hello, World! program in a third programming language.

Example

Say you have a language A* in which a valid quine is 123, and another language B* where abc is an error quine. Then, 123abc (or abc123) should be a valid Hello, World! program in language C*. If this is the case, your answer should look similar to the following:


A, B, C, score 3

A, 3 bytes - Quine

123

Try it online!

B, 3 bytes - Error quine

abc

Try it online!

C, 6 bytes - Hello, World!

123abc

Try it online!

Explanation (optional)

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus sem mi, dignissim a odio vehicula, tincidunt ultrices tellus. Etiam luctus scelerisque urna, ac sodales nisl rhoncus at. Cras ac accumsan velit. Integer eget mi nec diam suscipit pretium a ac massa. Praesent at enim nec nisl molestie aliquet nec sed lorem. Duis iaculis condimentum dui at ullamcorper. Fusce molestie iaculis dolor. Cras vel metus dictum, aliquam quam sit amet, gravida tortor. Praesent maximus quam porttitor, vulputate magna eu, rhoncus nunc. Sed accumsan dui ut sapien semper finibus. Nulla eget dictum justo.


Scoring

Your score is the arithmetic mean of the lengths of the two quines (i.e. half the length of the Hello, World! program).

Rules

  • All three programming languages used must be different.
  • The Hello, World! program should output exactly Hello, World!. A trailing newline is allowed.
  • Standard loopholes are forbidden, except for storing information in the file name; if done so in either one of the quines, it will add <length of file name> bytes to the length of both that program and the Hello, World! program, therefore adding half of <length of file name> to your score. If done in the Hello, World! program, it adds the same amount to your score and bytecount for it, but not for either one of your quines. Note that, if you're not doing this, the file name will be assumed to be .code.tio even if not running on TIO.
  • The regular quine must output to STDOUT and the error quine must output to STDERR. If STDOUT and STDERR do not exist in your language(s), use the closest equivalent(s). However, the Hello, World! program may output using any of the standard I/O methods. Also, the quine and Hello, World! programs may output anything to STDERR, and the error quine may output anything to STDOUT.
  • If possible, please link to an online interpreter (e.g. TIO) to run your program on.
  • Please explain your answer. This is not necessary, but it makes it easier for others to understand.
  • Neither one of the quines may output a trailing newline unless that newline also occurs in the source code.
  • Languages newer than the question are allowed. This means you could create your own language where a is a quine, b is an error quine, and ab is Hello, World!, and post an answer in that language with score 1, but expect many downvotes.
  • Non-programming languages are allowed. A non-programming language is a language which doesn't satisfy both of these conditions:
    • Able to take two integers as input and print their sum
    • Able to take one integer as input and print a truthy value if it is prime, and a falsy value if it is not
  • Different versions of the same language may be used. For example, your quine could be in Python 2 and your Hello, World! program in Python 3.
  • This is , so shortest code in bytes wins!

*Fun fact: these are all actual languages!

\$\endgroup\$
6
  • 6
    \$\begingroup\$ "neither one of the quines may output with a trailing newline" - what if the program ends with a trailing newline? \$\endgroup\$
    – pxeger
    Jan 29, 2021 at 7:59
  • 2
    \$\begingroup\$ @KevinCruijssen Maybe the fact that outputting to stderr is different from outputting to stdout should make the error quine more interestin ? Taking advantage of the error printing makes it a fundamentally different challenge, not yet-another-quine. For example, this Rust error quine is much more original than a regular quine that just has to find a way to output to a different stream ^^. (if that is what you meant) \$\endgroup\$ Jan 29, 2021 at 9:47
  • 2
    \$\begingroup\$ @AnimaLibera Yeah, I realized that later on as well. Error quines are completely different than regular quines. The regular quines should be proper quines (so simply using A in Charcoal or PHP which output A isn't allowed), but the error quines is basically finding a program and error message that match exactly. I've deleted both my comments, since they both don't make much sense knowing this now. \$\endgroup\$ Jan 29, 2021 at 9:51
  • 3
    \$\begingroup\$ Why take the arithmetic mean, when the sum of the lengths ranks the answers just the same? \$\endgroup\$ Jan 29, 2021 at 17:37
  • \$\begingroup\$ @pxeger then yes, it must. \$\endgroup\$
    – Makonede
    Jan 29, 2021 at 18:08

8 Answers 8

24
+100
\$\begingroup\$

C, Bash, C++, score 174.5 175

C, 301 bytes - Quine

#include<stdio.h>
int main(){
#ifdef __cplusplus
printf("Hello, World!"
#else
char*c="#include<stdio.h>%cint main(){%c#ifdef __cplusplus%cprintf(%cHello, World!%c%c#else%cchar*c=%c%s%c;printf(c,10,10,10,34,34,10,10,34,c,34,10,10%c#endif%c);}//";printf(c,10,10,10,34,34,10,10,34,c,34,10,10
#endif
);}//

Try it online!

Bash, 48 49 bytes - Error quine

.code.tio: line 1: .code.tio:: command not found

Try it online! (the trailing newline was added, see comments)

C++, 349 350 bytes - Hello, World!

#include<stdio.h>
int main(){
#ifdef __cplusplus
printf("Hello, World!"
#else
char*c="#include<stdio.h>%cint main(){%c#ifdef __cplusplus%cprintf(%cHello, World!%c%c#else%cchar*c=%c%s%c;printf(c,10,10,10,34,34,10,10,34,c,34,10,10%c#endif%c);}//";printf(c,10,10,10,34,34,10,10,34,c,34,10,10
#endif
);}//.code.tio: line 1: .code.tio:: command not found

Try it online!


Explainations and notes

The C quine is inspired by this C quine (the short version), and contains C++ code for the Hello, World!.

The Bash error quine works due to the TIO implementation, but given that error messages are generally implementation defined, it might be hard to print them in some standard way (other than directly outputting to stderr, which is just like a regular quine... how unoriginal would that be). The submitted Bash program may be an invalid Bash program, but it is still a valid error quine in Bash. (Edit: note the trailing newline that is now legal to output.)

The C++ Hello, World! doesn't output a trailing newline, but the challenge doesn't require it. After the preprocessor preprocessing, the only code source left is the main function with a simple printf call.

What was used in this answer are similarities between C and C++, very useful for polyglots (C is not entirely contained by C++, but it is contained enough) (for example: the usage of the C standard library is almost the same in these two languages which allows for a single #include directive, the main function definition is also similar enough to factorize the beginning and end out of the preprocessor-picked variations). The preprocessor and the __cplusplus macro are almost necessary at this point as they allow the C and C++ interpreters (or compilers, whatever) to pick only a specific subset of the program. The trailing line comment // ensures that the concatenation with a TIO Bash error doesn't upsets the C++ parser as it will completely ignore it.

I didn't find a way to to golf it even further. An other approach or a different set of languages are probably to be considered. For example, maybe using Argh! or INTERCAL for the error quine (or any other language in which error output is part of the language specification (these languages are rare, even among esolangs)). It might also be more interesting to use an other strategy than this """polyglot""" that makes each language ignore the code designed for the other languages instead of actually running most of the code.

\$\endgroup\$
13
  • 3
    \$\begingroup\$ Welcome to the site - it's pretty rare to see a first answer on a challenge like this! It's hard to tell on TIO but I think your error quine actually outputs a trailing newline, as you can see by comparing with this. (Maybe a TIO quirk, not sure.) \$\endgroup\$
    – Dingus
    Jan 29, 2021 at 12:34
  • 2
    \$\begingroup\$ @Dingus Oh yes, you are right >< I have no idea how to output a real error with no trailing newline then. I think it is impossible except if there is a bug in an implementation's error printing. How frustrating haha ^^' Edit: Oh unless we consider that trailing newlines in the program don't count of course! And thank you ^^. \$\endgroup\$ Jan 29, 2021 at 13:23
  • 2
    \$\begingroup\$ Nice one! You definitely won't win this challenge, but if this were a popularity-contest, you definitely would. +1 \$\endgroup\$
    – Makonede
    Jan 29, 2021 at 18:20
  • 2
    \$\begingroup\$ You can save some space by using POSIX positional arguments for printf to reduce the doubled printf parameters. \$\endgroup\$
    – EasyasPi
    Jan 31, 2021 at 2:26
  • 3
    \$\begingroup\$ @Makonede It was not aimed to someone in particular, just a trend I noticed, and it actually makes sense: I barely even look at answers in languages I don't understand, and wouldn't see the subtleties involved \$\endgroup\$
    – Kaddath
    Feb 1, 2021 at 17:42
10
\$\begingroup\$

MathGolf, gnuplot, Underload, score: 33.5

MathGolf, 9 bytes (Quine)

ÿ'ÿ\_'ÿ\_

Try it online.

gnuplot, 58 bytes (Error quine)


(Hello, World!)S
^
".code.tio", line 2: invalid command


With one leading and two trailing newlines.

Try it online.

Underload, 67 bytes (Hello, World!)

ÿ'ÿ\_'ÿ\_
(Hello, World!)S
^
".code.tio", line 2: invalid command


With two trailing newlines.

Try it online.

Explanation:

MathGolf:

ÿ          # Push a string of four characters: 
 'ÿ\_      #  "'ÿ\_"
     'ÿ    # Push character "ÿ"
       \   # Swap the top two values on the stack
        _  # Duplicate the top value on the stack
           # (after which the entire stack joined together is output implicitly)

gnuplot:

I've never used gnuplot before, but I simply tried random languages on TIO that contains (Hello, World!)S for the Underload program, and result in an error quine at the same time, of which gnuplot was one of the few, and the shortest I could find.

It will ignore the leading newline, and then complain about the (Hello, World!)S being invalid on line 2. Everything after that is fortunately enough ignored.

Underload:

Underload will simply print everything between (...)S, which is the intended Hello, World! in this case. It does give an error due to the rest of the program, but we can ignore STDERR and only look at the STDOUT, which is allowed by default.

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

Y, nameless language, Deadfish~, 4.5

Y, 3 bytes

Uwp

Try it online: Copy-paste the code from above (or type it manually), and click on the 'timeout run' button.

nameless language, 6 bytes

[[0]]

With trailing newline.

Try it online.

Deadfish~, 9 bytes

[[0]]
Uwp

Try it online.

Explanation:

Y:

U    # Begin scanning, ignoring any links, and record as string once another `U` is
     # encountered, while starting the string itself with a leading "U"
 wp  # "wp"
U    # Wraps around to the start of the program again, finishing the string "Uwp"
 w   # No-op
  p  # Print the stack

I'm pretty sure Y is the language with the shortest proper quine available, of just 2 bytes with Up.

nameless language:

nameless language is a brainfuck derivative using 0s and 1s in 4-bit parts for the builtins. It will also debug the pointers to STDERR by default, which starts with [[0]] for empty programs.

Deadfish~:

Basically every character we used in the Deadfish~ program is a no-op, except for the w, which is the builtin to print Hello, World! to STDOUT.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Does Deadfish~ qualify as a programming language? \$\endgroup\$
    – xigoi
    Jan 29, 2021 at 23:30
  • 1
    \$\begingroup\$ @xigoi Given that this is in part a Kolmogorov complexity challenge (especially the Hello World part), I’m not sure it needs to be \$\endgroup\$ Jan 30, 2021 at 0:44
  • 4
    \$\begingroup\$ @xigoi Answering in non-programming languages is allowed. (There's been an attitude shift here - see WheatWizard's comment on this question for more background.) \$\endgroup\$
    – Dingus
    Jan 30, 2021 at 0:47
  • 1
    \$\begingroup\$ Oh, that's cool! \$\endgroup\$
    – xigoi
    Jan 30, 2021 at 8:45
8
\$\begingroup\$

V (vim), ><>, Help, WarDoq!, score 16

V, 6 bytes (Quine)

H2aH2a

Try it online!

H      # move cursor to first non-blank character (effectively no-op)
 2a    # twice append
   H2a # literal characters

><>, 26 bytes (Error quine)

something smells fishy...

Try it online!

Note the trailing newline. Quoting from Esolangs:

Although there are multiple reasons an error may occur, there is only one error message: something smells fishy...


Help, WarDoq!, 32 bytes (Hello, World!)

H2aH2asomething smells fishy...

Try it online! Link is to an interpreter in CJam identical to the reference implementation described at Esolangs. The code (without the trailing newline, due to technical limitations) can also be run from the CJam interpreter linked at Esolangs, but it unhelpfully combines STDOUT and STDERR into one output field.

H                               # print 'Hello, World!'
 2                              # ignored
  a                             # throws an error: attempts to read two integers from STDIN and XOR them
   H2asomething smells fishy... # (not executed)
\$\endgroup\$
0
5
\$\begingroup\$

Ruby, ><>, Stax, score = 48 43

Ruby, 60 bytes (quine)

"Hello, World!"
puts <<2*2,2
"Hello, World!"
puts <<2*2,2
2

Try it online!

><>, 26 bytes (error quine)

something smells fishy...

Try it online!

Stax, 86 bytes (hello world)

"Hello, World!"
puts <<2*2,2
"Hello, World!"
puts <<2*2,2
2
something smells fishy...

Try it online!

-5 score thanks to Dingus

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

Objective-C++/NASM/ARM Assembler, score 114.5 115.5

Objective-C++ (clang) -fmodules, quine, 188 187 bytes

@import std;int main(){auto s="@import std;int main(){auto s=%c%s%1$c;printf(s,34,s,R%1$c(%3$s)%1$c,10);}%4$c";printf(s,34,s,R"(
.macro instruction x;.print"Hello, World!";.endm@)",10);}

Includes trailing newline.

I would post a link but unfortunately modules appear to be borked on both TIO and Wandbox.

When Travis decides to wake up, I will link a non-interactive demo.

You will see why I need Objective-C++ in a moment.

NASM, error quine, 42 44 bytes

t.:1: error: parser: instruction expected

Just your standard NASM error quine.

Requires the program to be named t.

The length depends on the filename, but nasm will only properly quine if the filename contains a dot and the first character isn't a dot.

Try it online!

ARM Assembler (clang), Hello World, 230 231 bytes

Uses the .print GAS directive.

@import std;int main(){auto s="@import std;int main(){auto s=%c%s%1$c;printf(s,34,s,R%1$c(%3$s)%1$c,10);}%4$c";printf(s,34,s,R"(
.macro instruction x;.print"Hello, World!";.endm@)",10);}
t.:1: error: parser: instruction expected

Try it online!

Explanation

First, let's ungolf the Obj-C++ quine and remove the actual quine part to show what is going on:

@import std;
int main()
{
    auto fmt = "...";
    printf(fmt, '"', fmt, R"(...)", '\n');
}

So the ObjC++ quine is a fairly standard C++ quine, although it uses the Objective-C @import extension and a raw string literal. Other than that, there really isn't that much to explain.

You may ask, "why are you using @import? If you have modules, you can just do import".

The answer is that, in ARM assembly, @ is a comment. And that is the magic (and literally the only reason we are using ObjC++).

So first, we make the ARM assembler completely ignore the first line while also @importing printf.

I'd love to just use ObjC so I can have my implicit int, but .print requires a quoted string. I don't see any way to do this without raw string literals. 😭

As for the assembly thing, I decided to use code from BOTH the NASM quine and the Obj-C++ quine, which I believe was the intended meaning of having the programs concatenated.

I could save a lot of bytes by just commenting out the NASM code though (it would go down to a score of 96, but I prefer this more creative solution.

For the assembler, I define a macro instruction:

.macro instruction x
    .print "Hello, World!"
.endm

Then, when I append the NASM quine, it is parsed as a bunch of labels followed by instruction expected:

.t:
1:
error:
parser:
        instruction  expected

which calls the instruction macro I just defined, executing the compile-time .print "Hello, World!" statement.


For the reference, here is the more boring one which comments out the NASM line.

Objective-C++/NASM/ARM Assembler, boring version, score 96

Objective-C++ (clang) -fmodules, quine, 149 bytes

Note: newline is no longer necessary.

@import std;int main(){auto s="@import std;int main(){auto s=%c%s%1$c;printf(s,34,s,R%1$c(%3$s)%1$c);}";printf(s,34,s,R"(
.print"Hello, World!"@)");}

NASM, error quine, 44 bytes

t.:1: error: parser: instruction expected

Just like before, needs the filename to be t..

ARM Assembler (clang), Hello World, 192 bytes

@import std;int main(){auto s="@import std;int main(){auto s=%c%s%1$c;printf(s,34,s,R%1$c(%3$s)%1$c);}";printf(s,34,s,R"(
.print"Hello, World!"@)");}t.:1: error: parser: instruction expected

Try it online!

This version removes the trailing newline and just comments out the NASM error. The .print is directly run instead of requiring the macro.

However, the ARM program will still do the same thing without the NASM program. Therefore, I am (at least personally) going by the higher score because I feel it is more in the spirit of the challenge and not an ugly hack.

\$\endgroup\$
5
  • 3
    \$\begingroup\$ Original set of languages ^^. Also, note that your error quine may output a trailing newline (which is forbidden by the question), as we all did the first time we used a real error to output to stderr haha (see this comment to see why this may be). \$\endgroup\$ Jan 31, 2021 at 1:08
  • 1
    \$\begingroup\$ Thanks for pointing out the newline! \$\endgroup\$
    – EasyasPi
    Jan 31, 2021 at 1:12
  • \$\begingroup\$ You reminded me, I almost forgot to point out what happens if you store extra information in the filename. I have updated the rules and submitted an edit adding one point. \$\endgroup\$
    – Makonede
    Jan 31, 2021 at 2:42
  • 1
    \$\begingroup\$ Oooooh okay, I was confused there like "huh? Can this person count?". I'll accept your edit. \$\endgroup\$
    – EasyasPi
    Jan 31, 2021 at 2:43
  • 2
    \$\begingroup\$ Thanks! Also, I really like the idea of using ObjC++'s @import to make a quine and simultaneously comment out some assembly. On an unrelated note, you're penultimate in terms of golfage, but second in terms of creativity. +1 \$\endgroup\$
    – Makonede
    Jan 31, 2021 at 2:47
2
\$\begingroup\$

Perl 5, PHP, Perl 4 Score 84

Perl 5, 75 bytes (Quine)

eval($s='printf(-1**2+1?"Hello, World!":"eval(\$s=%c%s%c);#",39,$s,39);');#

Try it online!

PHP, 93 bytes (Error Quine)

PHP Parse error:  syntax error, unexpected 'Parse' (T_STRING) in Command line code on line 1

Try it online!

Perl 4, 168 bytes (Hello World)

eval($s='printf(-1**2+1?"Hello, World!":"eval(\$s=%c%s%c);#",39,$s,39);');#PHP Parse error:  syntax error, unexpected 'Parse' (T_STRING) in Command line code on line 1

Try it online!

EXPLANATION:

EDIT: Due to OP's decision about PHP errors I had to resort to more traditional tricks, sorry. Welcome to the classical comment!

  • the difference between the quine and HelloWorld is that in Perl 4 the minus operator takes precedence over exponentiation (-1**2+1 will be 2 and then truthy), while the contrary in Perl 5 (-1**2+1 will be 0 and then falsy)

  • The error quine is nothing special, notice the trailing newline

  • Nothing more for the third, uses a comment

\$\endgroup\$
3
  • \$\begingroup\$ First of all, the <?php at the start of your code makes it an invalid error quine. With PHP -r, however, it is possible, as it no longer requires, or even permits, the opening/closing tags. Second of all, I mentioned specifically that the error quine must output to STDERR. Third of all, you can't replace die with trigger_error without any other changes; the program then outputs PHP Notice: eval($s='trigger_error("eval(\$s=".chr(39).$s.chr(39).");");'); in Command line code(1) : eval()'d code on line 1 with a trailing newline. Please edit this answer to fix this or I will flag it. \$\endgroup\$
    – Makonede
    Jan 30, 2021 at 19:02
  • \$\begingroup\$ Also, do note that for some reason you have to use Bash by itself to run PHP with -r, so just type php -r `cat` in Bash on TIO and input the code via STDIN. \$\endgroup\$
    – Makonede
    Jan 30, 2021 at 19:04
  • 1
    \$\begingroup\$ @Makonede adapted my answer accordingly. Notice that no need for Bash in TIO, like in PHP command-line the code has to be passed in the command after the -r (the code is here just for the count, it can be removed, what is typed in the code part is ignored in -r) \$\endgroup\$
    – Kaddath
    Feb 1, 2021 at 19:00
1
\$\begingroup\$

Python 3, ><>, Befunge-93, score 54

Python 3, 82 bytes - Quine

"!dlroW ,olleH">':#,_@';_='"!dlroW ,olleH">\':#,_@\';_=%r;print(_%%_)';print(_%_)

Try it online!

"!dlroW ,olleH">':#,_@';_='"!dlroW ,olleH">\':#,_@\';_=%r;print(_%%_)';print(_%_)  # full program
"!dlroW ,olleH">':#,_@';                                                           # singleton comparison statement (effectively NOP)
                        _=                                                         # set variable _ to...
                          '"!dlroW ,olleH">\':#,_@\';_=%r;print(_%%_)';            # literal
                                                                       print(_     # output _ with a trailing newline...
                                                                              %    # with the %r replaced by...
                                                                               _   # _'s value...
                                                                                   # including quotes...
                                                                              %    # and the %% replaced by %
                                                                                )  # end function call

><>, 26 bytes - Error quine

something smells fishy...

Try it online!

s...  # trimmed program
s     # invalid command, causes fatal error "something smells fishy...\n"
 ...  # unreachable code

Befunge-93, 108 bytes - Hello, World!

"!dlroW ,olleH">':#,_@';_='"!dlroW ,olleH">\':#,_@\';_=%r;print(_%%_)';print(_%_)
something smells fishy...

Try it online!

"!dlroW ,olleH">':#,_@...  # trimmed program
"                          # push charcodes of...
 !dlroW ,olleH             # literal...
"                          # separately onto stack
              "            # end literal
               >           # move right
                '          # NOP (unrecognized command)
                 :         # duplicate top of stack when going right, NOP when going left
                  #        # skip over next command in current direction
                   ,       # output top of stack as a character when going left, NOP when going right
                    _      # pop top of stack, go left if nonzero
                     @     # terminate
                      ...  # unreachable code
\$\endgroup\$

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.