# Encode a Lenguage

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.

# Scoring

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

• 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 Jun 18, 2021 at 22:34
• 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. Jun 18, 2021 at 22:49
• 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. Jun 19, 2021 at 0:08
• You should've required this encoding to be reversible, otherwise an obvious joke answer like Makonede's is actually valid Jun 19, 2021 at 2:51
• Do we have to encode the empty program? Jun 20, 2021 at 6:13

# 05AB1E, 7845535 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!

# 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).

• 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. Jun 19, 2021 at 7:17

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

⭆Ｓ⌕´Ｓ´⭆´⌕´´´ιι


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.

# 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.

• 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... Jun 20, 2021 at 15:41
• @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. Jun 20, 2021 at 20:04
• @DominicvanEssen I think yours is reversible with -23 instead of -29. Jun 20, 2021 at 20:41

# 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!

# 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.

• Wait, you so deserve to post that as your own. I don't even get it. Mind explaining in the Vyxal chat? Jun 19, 2021 at 7:05
• I just realised it's invalid because leading 0s, otherwise this would work as well Jun 19, 2021 at 7:06
• 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!
– Neil
Jun 19, 2021 at 18:26

# 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.

# 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

“Ṿ…”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


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.