33
\$\begingroup\$

Write the smallest program that maps strings injectively to outputs and maps itself to 2020.

To be clear, your program \$p\$ must have the following properties:

  1. every possible input string \$s\$ has a well-defined output \$p(s)\$,
  2. for every pair of strings \$s\$ and \$t\$ with \$s\neq t\$, it holds that \$p(s)\neq p(t)\$, and
  3. \$p(p)=2020\$.

Be sure to explain why your submission satisfies properties 1 and 2. For property 3, the output can be a string or any type of number.

Edit 1: Programs need to be proper quine variants. Reading the source code is not allowed.

Edit 2: Note that as a consequence of property 2, it holds that \$p(s)\neq p(p)\$ for every \$s\neq p\$.

\$\endgroup\$
7
  • \$\begingroup\$ every possible input string Can we support only ASCII? \$\endgroup\$
    – Luis Mendo
    Jan 4, 2020 at 18:15
  • 1
    \$\begingroup\$ @LuisMendo - yes, provided ASCII is the alphabet of the language that your program is written in. \$\endgroup\$ Jan 4, 2020 at 18:16
  • 7
    \$\begingroup\$ Do programs need to be proper quine variants or is reading the source code allowed? \$\endgroup\$
    – FlipTack
    Jan 4, 2020 at 19:06
  • 1
    \$\begingroup\$ @FlipTack - Thanks for the clarifying question. No reading the source code. I edited the post to reflect this. \$\endgroup\$ Jan 4, 2020 at 19:37
  • 1
    \$\begingroup\$ @RobinRyder - A function is acceptable. \$\endgroup\$ Jan 4, 2020 at 19:41

13 Answers 13

54
\$\begingroup\$

awk, 4 bytes

The structure of an awk program is pattern { action }. If pattern evaluates to true, { action } is performed. If { action } is omitted, the default is to output the current input record.

Code:

2020

As 2020 always evaluates to true, the program always prints it's input, therefore satisfying properties 1. and 2. When the input is the program itself it satisfies property 3. \$p(p)=2020\$ — even \$p(p)=p\$.

Some test cases:

$ echo 2020 | awk '2020'
2020
$ echo 0 | awk '2020'
0
$ echo "" | awk '2020'

$ echo foo | awk '2020'
foo

Would've been more glorious back in the good old days:

$ echo 1 | awk '1'
1
\$\endgroup\$
4
  • 11
    \$\begingroup\$ polyglot with perl5 -p \$\endgroup\$ Jan 6, 2020 at 9:22
  • 1
    \$\begingroup\$ Nice James, thank you for sharing the same :) \$\endgroup\$ Jan 7, 2020 at 6:41
  • 2
    \$\begingroup\$ Also polyglot with Perl 6 -p. \$\endgroup\$
    – nwellnhof
    Jan 7, 2020 at 12:59
  • \$\begingroup\$ In some other stack-based languages, like Golfscript, the code 20 would suffice since it auto-concatenates the stack to print out on output. \$\endgroup\$
    – Mathgeek
    Mar 1, 2020 at 15:09
12
\$\begingroup\$

JavaScript (ES6), 23 bytes

Returns either the input string with a leading \$0\$, or \$2020\$ if the input is the program.

f=s=>s=='f='+f?2020:0+s

Try it online!


JavaScript (Node.js), 76 bytes

Generates a unique BigInt by using each byte of the input string, then applies a XOR to the result in such a way that \$f(f)=2020\$.

f=s=>(g=s=>Buffer(s).every(b=>t=t<<8n|BigInt(b),t=1n)&&t)(s)^g('f='+f)^2020n

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ The first one does not match criteria 2, as it will output the same result for different input strings \$\endgroup\$
    – Skyler
    Jan 6, 2020 at 20:09
  • 2
    \$\begingroup\$ @Skyler Please note that the input is a string and so is 0+s. If a and b are 2 distinct strings, so are 0+a and 0+b. \$\endgroup\$
    – Arnauld
    Jan 6, 2020 at 20:11
  • \$\begingroup\$ I think this doesn't satisfy the "do not read the source code" condition, right? \$\endgroup\$ Jan 7, 2020 at 9:55
  • 1
    \$\begingroup\$ @TomášZato-ReinstateMonica Last time I checked, I think Dennis' answer about that was the most upvoted, but it seems like we still don't have a clear concensus. (Also, this requirement did not exist at the time I answered the challenge.) \$\endgroup\$
    – Arnauld
    Jan 7, 2020 at 10:29
  • \$\begingroup\$ You can check the revision change on codegolf.stackexchange.com/revisions/197679/2 which was at 2020-01-04 19:36:35Z while this answer was posted on 2020-01-04 17:08:36Z - almost 2 hours and a half after this answer was posted. On that edit, the tag "quine" as added as well. \$\endgroup\$ Jan 7, 2020 at 12:08
7
\$\begingroup\$

Ruby -n, 45 bytes

Based on one of the classic Ruby quines, _="_=%p;puts _%%_";puts _%_. Prints 2020 if the input is the source, otherwise prints the Ruby representation of the input (encapsulated in quotes, various characters like " and \ are escaped, etc.)

_="_=%p;p$_==_%%_ ?2020:$_";p$_==_%_ ?2020:$_

Try it online!

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

Python 3.8 (pre-release), 81 60 59 57 56 bytes

-21 Thanks to Jo King

Outputs 2020 if the input matches the program, otherwise the input concatenated to itself 5 time (eg. abc becomes abcabcabcabcabc)

exec(a:='print(5*[i:=input(),404][i=="exec(a:=%r)"%a])')

Try it online!


Python 2, 56 bytes

Outputs 2020 if the input matches the program, otherwise the input concatenated to itself 5 time (eg. abc becomes abcabcabcabcabc)

a='i=input();print 5*[i,404][i=="a=%r;exec a"%a]';exec a

Try it online!


Python 3.8 (pre-release), 77 67 65 bytes

-10 Thanks to Jo King

Outputs 2020 if the input matches the program, otherwise the input concatenated to itself 5 time (eg. abc becomes abcabcabcabcabc)

lambda s:5*[s,404][s==(a:='lambda s:5*[s,404][s==(a:=%r)%%a]')%a]

Try it online!

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

GolfScript, 2 bytes

20

This is a refined solution to James Brown's solutions.

If the input is 20 [source code], prints 2020 - otherwise prints [string]+20, which is unique and easily reversible.

Try it online!

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

Jelly, 16 bytes

“Ṿ;⁾v`³⁽¥ŒṾ⁼?”v`

Try it online!

A full program that takes a string as its input. It outputs an unevaluated Jelly version of the input unless provided with itself, in which case it outputs 2020.

Thanks to @JonathanAllan for pointing out a flaw in my original version!

Explanation

 “Ṿ;⁾v`³⁽¥ŒṾ⁼?”v` | Evaluate as Jelly code the following, using itself as the argument:
  Ṿ               | - Unevaluate (effectively wraps string back into “”
   ;⁾v`           | - Append "v`"
       ³    ⁼?    | - If equal to the program’s argument:
        ⁽¥Œ       | - Then: 2020 (compressed integer)
           Ṿ      | - Else: Unevaluated version of the program’s original argument
\$\endgroup\$
8
  • \$\begingroup\$ Hmm, not sure it's valid without bracketing or something - TIO EDIT - how about this? \$\endgroup\$ Jan 5, 2020 at 0:42
  • \$\begingroup\$ @JonathanAllan I don’t follow. Although it will follow standard Jelly implicit printing rules, the output should still be unique for any given input. The question doesn’t seem to put any further criteria on what the output consists of. Thanks for your suggestion; while it works, I’m still not sure why I can’t just continue to use O. \$\endgroup\$ Jan 5, 2020 at 0:46
  • \$\begingroup\$ There is an s (ߤ) for which p(s) = p(p) (2020) \$\endgroup\$ Jan 5, 2020 at 0:49
  • 1
    \$\begingroup\$ Oh I see. I now also follow your comment to the question. For now, I’ll update to your version if that’s ok. Thanks! \$\endgroup\$ Jan 5, 2020 at 0:50
  • 1
    \$\begingroup\$ Was just about to suggest it! \$\endgroup\$ Jan 5, 2020 at 0:55
3
\$\begingroup\$

Raku, 47 bytes

<say "<$_>~~.EVAL"eq($!=get)??2020!!@$!>~~.EVAL

Try it online!

Outputs 2020 if the input matches the program, otherwise the input surrounded in brackets.

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

05AB1E, 28 bytes

"34çìD«QiŽ7ìëû"34çìD«QiŽ7ìëû

Try it online or verify a few more test cases.

Explanation:

"34çìD«QiŽ7ìëû"            # Push this string
               34ç         # Push 34, and convert it to a character: '"'
                  ì        # Prepend it in front of the string
                   D«      # Append a copy of the string to itself
                     Qi    # If it's equal to the (implicit) input:
                       Ž7ì #  Push compressed integer 2020
                      ë    # Else:
                       û   #  Palindromize the (implicit) input
                           # (after which the result is output implicitly)

See this 05AB1E tip of mine (section How to compress large integers?) to understand why Ž7ì is 2020.

\$\endgroup\$
4
  • \$\begingroup\$ Might work ... only problem is an empty string? \$\endgroup\$ Jan 6, 2020 at 15:17
  • 1
    \$\begingroup\$ @ExpiredData The м should be K, otherwise any input containing only characters of the input (i.e. DD) would also result in 2020. But apart from that the empty string is indeed a problem I'm not sure how to overcome. :( \$\endgroup\$ Jan 6, 2020 at 16:37
  • 2
    \$\begingroup\$ @ExpiredData the empty string is far from the only problem. Appending the code to any string doesn't change the output (example). It seems highly unlikely you can make something injective with either м or K, since those fundamentally lose information. \$\endgroup\$
    – Grimmy
    Jan 7, 2020 at 12:49
  • \$\begingroup\$ Yeah @Grimmy thanks great point \$\endgroup\$ Jan 7, 2020 at 14:32
2
\$\begingroup\$

C (gcc), 190 196 194 192 180 176 bytes

Thanks to Jo King for pointing out a bug.

Trailing newline seems accepted in some other answers, so will use that to fix a bug pointed out by NieDzejkob. (Also -12 bytes thanks to the same.)

-4 bytes thanks to @ceilingcat.

Assumes little-endian, ASCII, sizeof(int) >= 4, all the good stuff.

Outputs the input string preceded by a dollar sign, unless given its own source code, in which case it outputs 2020.

*s="*s=%c%s%1$c,u[99]={'0202'};f(int*t){puts(bcmp(u+2,t,sprintf(u+2,s,34,s))?putchar(36),t:u);}",u[99]={'0202'};f(int*t){puts(bcmp(u+2,t,sprintf(u+2,s,34,s))?putchar(36),t:u);}

Try it online!

\$\endgroup\$
9
  • \$\begingroup\$ which is a different output than the empty string \$\endgroup\$
    – user85052
    Jan 6, 2020 at 8:53
  • 1
    \$\begingroup\$ The requirement is that no two distinct inputs should have the same output. \$\endgroup\$
    – justhalf
    Jan 6, 2020 at 10:50
  • \$\begingroup\$ @JoKing Good point! (Hopefully) Corrected now. \$\endgroup\$
    – gastropner
    Jan 6, 2020 at 10:56
  • \$\begingroup\$ @NieDzejkob The number will vary between implementations no doubt. Cheers! \$\endgroup\$
    – gastropner
    Jan 6, 2020 at 17:44
  • \$\begingroup\$ @gastropner Now 2020 corresponds to the input of the old program... \$\endgroup\$
    – Maya
    Jan 6, 2020 at 18:10
1
\$\begingroup\$

Java 10, 128 bytes

s->{var t="s->{var t=%c%s%1$c;t=t.format(t,34,t);return t.equals(s)?2020:0+s;}";t=t.format(t,34,t);return t.equals(s)?2020:0+s;}

Try it online.

Explanation:

part of the explanation:

  • var t contains the unformatted source code
  • %s is used to input this String into itself with t.format(...)
  • %c, %1$c, and the 34 are used to format the double quotes
  • t.format(t,34,t) puts it all together

Challenge part of the explanation:

  • t.equals(s) checks if the input-String is equal to the source code
  • ?2020: if it is, return 2020 as result
  • :0+s: if not, return the input-String with a prepended 0 as result instead
\$\endgroup\$
1
\$\begingroup\$

Pyth, 26 23 bytes

Outputs 2020 if the input matches the program, otherwise the input concatenated to itself 2020 time (eg. ab becomes ababab...ababab)

*2020|qjN B"*2020|qjN B

Try it online!

Explanation

*2020|qjN B"*2020|qjN B
          B"*2020|qjN B : Evaluates to ("*2020|qjN B", "*2020|qjN B")
       jN               : join with '"' as seperator (will be source code)
     |q                 : True if source is equal to input else input
*2020                   : Multiply by 2020 (i.e. True -> 2020, input -> 2020 * input)

Pyth, 21 bytes

Not sure if the following solution is valid, it will only work if the year is 2020.

*.d3|qjN B"*.d3|qjN B

Try it online!

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

J, 56 bytes

".a=.}:0 :0
echo@>2020[^:(]-:'".a=.}:0 :0',LF,a&[)1!:1[3

Try it online!

A full program. Unless provided with itself prints each character on a separate line.

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

Japt, 24 bytes

OvA="¶`OvA=`+Q+A?2020:U³

Try it online!

Explanation

Outputs 2020 if the input matches the program, otherwise the input 3 times (eg. ab becomes ababab)

OvA="¶`OvA=`+Q+A?2020:U³
  A="¶`OvA=`+Q+A?2020:U³  // Set value of A to "¶`OvA=`+Q+A?2020:U³"
Ov                        // Evaluate A as japt code
      `OvA=`+Q+A          // Concatenate "OvA=", '"' and A (Q = '"')
     ¶          ?2020:U³  // If equal to input then 2020 else input concatenated to itself 3 times
\$\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.