9
\$\begingroup\$

The Len(language,encoding) family of languages is a variety of Lenguage derivatives. To encode a program into a Len language, you replace every character with its representation in a certain encoding, then turn that into a giant integer.

Your challenge is to write a function or program that encodes your language into a Len language. However, you can make up your own encoding, and it only needs to encompass the subset of your language that is used in your program. But, you must have at least two distinct bytes in your program.

Rules

Your program must be able to take itself as input.

You can just output a number as the length of the compiled program, to avoid memory problems.

Your program must be reversible.

Scoring

Your score is the result of your program run on itself. You're trying to minimise this.

\$\endgroup\$
10
  • 3
    \$\begingroup\$ I feel like there are some restrictions missing on the encoding to stop solutions from hard-coding themselves as 1 (or hard-coding everything as 1, for that matter)--or at the least they're not spelled out quite enough \$\endgroup\$ Jun 18 '21 at 22:34
  • 3
    \$\begingroup\$ I agree with @UnrelatedString. I know that your intention was golf, but this is more of a "my encoding encodes my program as 0 and everything else in UTF-8" challenge. \$\endgroup\$
    – Makonede
    Jun 18 '21 at 22:49
  • 1
    \$\begingroup\$ Can it encode different programs as the same number? Or does it have to strictly follow the algorithm of setting a unique encoding for each symbol. \$\endgroup\$
    – AviFS
    Jun 19 '21 at 0:08
  • 5
    \$\begingroup\$ You should've required this encoding to be reversible, otherwise an obvious joke answer like Makonede's is actually valid \$\endgroup\$ Jun 19 '21 at 2:51
  • 2
    \$\begingroup\$ Do we have to encode the empty program? \$\endgroup\$
    – pxeger
    Jun 20 '21 at 6:13
8
\$\begingroup\$

05AB1E, 7845 535 34

BC

Try it online!

This converts the input from base 2 according to 05AB1E's codepage. B is mapped to 11 and C to 12. Digits larger or equal to the base are allowed and "overflow" into the next digit.
This can be inverted by iterating the digits of the output in reverse:

[D0Q#    "loop while TOS != 0"\
2‰`      "divmod 10"\
i        "if the last digit was 1:"\
 'Bˆ5-   "append ö to global array and subtract 5 from TOS"\
ë        "else:"\
 'Cˆ6-   "append T to global array and subtrac 6 from TOS"\
]¯RJ     "after the loop: reverse global array and join"\

Try it online!

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

Zsh, 40 bytes, score 0

grep -FqxfI $0&&od||od -An<I|tr -c 0-7 8

Try it online!

Encodes itself as 0, and all other programs in some horrendous octal/decimal mishmash. Takes input from a file I.

  • grep: search for a string that matches
    • F: exactly (non-regex)
    • x: the whole line
    • fI: the pattern taken from the file I
    • q: do not print the matching string; only exit with success or failure
    • $0: this source code file
  • &&od: if the match succeeds, print 0000000
  • ||: otherwise:
    • od -An<I: encode the input file in octal
    • |tr -c 0-7 8: replace all characters except 01234567s with 8s (ensures it's a valid number with no leading 0s)

Doesn't support newlines (nor null bytes).

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Wow, this is brilliant. That comment has been there for a while, but no one had actually done it! I'm going to incorporate this into my answer. \$\endgroup\$
    – AviFS
    Jun 19 '21 at 7:17
7
\$\begingroup\$

Charcoal, 11 bytes, score 96697523013522 14 bytes, score 10230313233344

⭆S⌕´S´⭆´⌕´´´ιι

Try it online! Explanation: Now uses @AviFS's approach of looking up the possible characters in a table. However, the table itself more than triples the length of the code, which leaves no room to do base conversion, so instead I just output the digits individually as base 10, but fortunately it's still slightly lower than my original score.

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

R, ~7.0689*10^69

cat(utf8ToInt(scan(,''))-29,sep='')

Try it online!

Converts the input to ASCII codepoints, subtracts 29, and concatenates all the 2-digit numbers obtained. I chose 29 because the lowest ASCII codepoint I need is 39 (for '); this ensures that all the numbers are between 10 and 98. Reversing is thus easy: split into groups of 2 digits, add 29 and convert back to characters.

Works on any string which does not include the characters !"#$%&.

A more naïve implementation would omit the -29 and use the plain ASCII codepoints; it is easy to convince oneself that this remains reversible even with some 3-digit numbers, but it leads to a score of 9.997*10^75.

\$\endgroup\$
3
  • \$\begingroup\$ This is great, but seems to be code-golfing rather than seriously competing using the challenge's scoring system. Modifying your approach like this would give a score of zero... \$\endgroup\$ Jun 20 '21 at 15:41
  • \$\begingroup\$ @DominicvanEssen I hadn't thought of such an approach (though I now see that other answers have used it since); you should post it! Although currently yours isn't reversible, since e.g. the inputs T and "" both lead to the output 55. \$\endgroup\$ Jun 20 '21 at 20:04
  • \$\begingroup\$ @DominicvanEssen I think yours is reversible with -23 instead of -29. \$\endgroup\$ Jun 20 '21 at 20:41
4
\$\begingroup\$

Dyalog APL, 2.7370885894231567 * 10^18

This is the most naive algorithm I could come up with, so I suppose it sets a baseline. Given the structure {n⊥n|⎕UCS⍵}, I wrote a script to check the lowest that n could be, and 28 is our answer.

That is, the lowest that n could be and still yield a unique codepoint for each symbol in the program, when it's unicode is reduced mod n.

The program simply takes the unicode codepoint of each symbol, mods it by 28, and then converts it to base 28. It's not very clever or optimized, I challenge you to be less lazy!

{28⊥28|⎕UCS⍵}

Try it online!

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

Vyxal, 16 bytes, score 81040998233

`\`\\v\ḟ6\β`vḟ6β

Try it online!

There may be better languages to do this, but the idea is simple.

The other answers reduce the codepoints mod n where n is the smallest number that will yield unique codepoints. But that's rarely an efficient encoding. You usually end up with lots of numbers unused. Eg. your program becomes [6,3,9,7,2] rather than [0,1,2,3,4].

This just packs every symbol used into a list, and for each symbol in the program, gets its index in the list. So you're guaranteed to get the lowest numbers you can: [0..n]. In addition, the symbols in the list are in the order they appear in the program, because we want the lower numbers to show up first. In every base, [0,1,2,3] is a much smaller number than [3,2,1,0]. Finally, I used 6 unique symbols, so I converted it to base 6.

Example execution with v6ḟ as input:

               # Implicit input                          -> "v6ḟ"
`\`\\v\ḟ6\β`   # This is just the string "`\vḟ6β" [1]    -> "v6ḟ", "`\vḟ6β"
vḟ             # Vectorized find index in list           -> [2,4,3]
6β             # Convert list to base 6                  -> 99
               # Implicit output

[1]: Unfortunately for this challenge, non-ASCII characters have an (really cool) encoding scheme in strings. So in order to have them interpreted literally, all the non-ASCII characters in the string are escaped, which adds many orders of magnitude to the score.

\$\endgroup\$
3
  • \$\begingroup\$ Wait, you so deserve to post that as your own. I don't even get it. Mind explaining in the Vyxal chat? \$\endgroup\$
    – AviFS
    Jun 19 '21 at 7:05
  • \$\begingroup\$ I just realised it's invalid because leading 0s, otherwise this would work as well \$\endgroup\$
    – emanresu A
    Jun 19 '21 at 7:06
  • \$\begingroup\$ From Charcoal's point of view the duplication to create the table is very expensive and I was only just able to achieve a lower result by skipping the base conversion completely! \$\endgroup\$
    – Neil
    Jun 19 '21 at 18:26
3
\$\begingroup\$

R, 176 bytes, score=0

'->a;b=paste0(sQuote(a),a);s=readLines(,1);`if`(s==b,cat(0),cat(utf8ToInt(s)-24,sep=""))'->a;b=paste0(sQuote(a),a);s=readLines(,1);`if`(s==b,cat(0),cat(utf8ToInt(s)-24,sep=""))

Try it online!

Despite the enormously increased byte-count, this is basically just an extension of Robin Ryder's approach, optimized for the challenge's scoring system instead of for code-golf.

We first construct a quine string of the program ('...'->a;b=paste0(sQuote(a),a)) in variable b, and then check if this is equal to the input (s=readLines(,1);`if`(s==b,...). If it is, we output zero (cat(0)): that is, we hard-code this particular progam as zero. Otherwise, we use Robin's approach to output the program's numerical value, which can never be less than 10.

Valid programs can only use characters with ASCII values 34-123: so, no newlines, and no "|}~" characters. The 'empty program' is not valid for this version (it also encodes to zero), but a slight modification can fix this, while keeping a score of zero for this challenge.

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

Jelly, 29 bytes, score 0 bytes

“Ṿ;⁾v,;⁾¥ ¤-iⱮḅL{ɗ⁼?ʋ/+1”v,¥ 

Try it online!

Returns 0 when supplied itself as an input. Otherwise looks up the supplied input in the characters “Ṿ;⁾v,;⁾¥ ¤-iⱮḅL{ɗ⁼?ʋ/+1”v,¥ and converts back from bijective base 29 before adding 1 (so that an empty input will result in 1 rather than being the same as the encoder itself).

Inspired by @pxeger’s Zsh answer so be sure to upvote that one too (implementation quite different though).

Decoder - Try It Online!

Explanation

Main link

“Ṿ…”v,¥  | Evaluate this string as a Jelly link with itself paired to the overall link’s argument (the program to encode)

Code run within eval

                   ʋ/   | Reduce using the following:
Ṿ                       | - Uneval (effectively wraps the string in “”)
 ;⁾v,;⁾¥ ¤              | - Append "v,¥ " (thus restoring the source for the encoder)
                 ⁼?     | - If equal to the original argument (the program to encode):
          -             |   - Then -1
                ɗ       |   - Else:
           iⱮ           |     - Indices of each character of program to encode in the string
             ḅ          |     - Convert from base given by:
              L{        |       - The length of the string
                     +1 | Add 1

Note the program has a trailing space because of the need to use within “” which takes a pair of characters.


Jelly, 2 bytes, score 7842

OḄ

Try it online!

A monadic link that converts to Unicode code points and unbinaries. This is a similar approach as @ovs’s 05AB1E answer so be sure to upvote that one too!

The TIO link includes a decoder in the header and generates a table of the first 32 possible programs including their decimal representation and the decoded program.

\$\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.