Jelly has compressed string literals, using the “...»
delimiters. The way these work is by interpreting the ...
as a base-250 integer, \$n\$, then repeatedly divmod-ing this integer until it reaches \$0 \newcommand{\d}[2]{ \left( \left\lfloor \frac {#1} {#2} \right\rfloor, #1 \text{ mod } #2 \right) }\$, building up the decompressed version as it goes by indexing into dictionaries and printable ASCII.
Jelly has 2 dictionaries, "short" and "long". "Short" contains \$20453\$ words of 5 letters or shorter. "Long" contains \$227845\$ words with 6 or more letters.
As the exact method is rather complicated, I'll work through how \$n\$ is decompressed:
- First, we divmod \$n\$ by \$3\$: \$n, m = \d n 3\$. We then call \$m\$ the mode.
- If the mode is \$0\$:
- Divmod \$n\$ by \$96\$, yielding \$n, c = \d n {96}\$
- Add the \$c\$th character in the printable ASCII range (
~
) to the decompressed string. If \$c\$ is \$95\$ yield a newline instead of 0x7F
- If the mode is \$1\$:
- If \$n\$ is even, use the "long" dictionary and replace \$n\$ with \$\frac n 2\$
- If \$n\$ is odd, use the "short" dictionary and replace \$n\$ with \$\frac {n-1} 2\$
- Then, take the length \$l\$ of the dictionary (\$20453\$ for "short", \$227845\$ for "long"), calculate \$n, i = \d n l\$ and retrieve the \$i\$th element of the dictionary, the word
- If the decompressed string is not empty, prepend a space to the word. Finally, append the word to the decompressed string
- If the mode is \$2\$:
- Calculate a flag \$f\$ as \$n, f = \d n 3\$ and update \$n\$
- If \$n\$ is even, use the "long" dictionary and replace \$n\$ with \$\frac n 2\$
- If \$n\$ is odd, use the "short" dictionary and replace \$n\$ with \$\frac {n-1} 2\$
- Then, take the length \$l\$ of the dictionary (\$20453\$ for "short", \$227845\$ for "long"), calculate \$n, i = \d n l\$ and retrieve the \$i\$th element of the dictionary, the word
- If the flag doesn't equal \$1\$, swap the case of the first character of the word
- If the flag doesn't equal \$0\$ and the decompressed string is not empty or the flag equals \$0\$ and the decompressed string is empty, prepend a space to the word
- Finally, append the word to the decompressed string
- If \$n\$ is non-zero, go to the first step with the new value of \$n\$
We can work through an example, using \$n = 46886323035539\$:
First, we divmod by \$3\$: \$n = 15628774345179, m = 2\$.
As the mode is \$2\$, we calculate \$n\$ and \$f\$ as \$n = 5209591448393, f = 0\$. \$n\$ is odd, so we're using the "short" dictionary and \$n\$ becomes \$2604795724196\$.
Calculate the index and the updated value of \$n = \left\lfloor \frac {2604795724196} {20453} \right\rfloor = 127355191\$ and \$i = 2673\$. The \$2673\$th word in the "short" dictionary is
Caird
, so we call that our word.As \$f \ne 1\$, we swap the case of the first character of the word:
caird
. However, \$f = 0\$ and the decompressed string is empty, so we don't prepend a space. Finally, we appendcaird
to the (empty) decompressed string, yieldingd = 'caird'
As \$n = 127355191\$, which is non-zero, we go to the first step again
Now,
d = 'caird'
and \$n = 127355191\$. Divmod by \$3\$ to get \$n = 42451730, m = 1\$.As the mode is \$1\$ and \$n\$ is even, we're going to use the "long" dictionary this time around and \$n\$ becomes \$21225865\$
We calculate the index into the dictionary as \$n = \left\lfloor \frac {21225865} {227845} \right\rfloor = 93\$ and \$i = 36280\$. The \$36280\$th element of the "long" dictionary is
coinhering
, so we set that as our word.As
d
is non-empty, we prepend a space to our word, then append it tod
:d = 'caird coinhering'
As \$n = 93\$, which is non-zero, we go to the first step again
Now,
d = 'caird coinhering'
and \$n = 93\$. Divmod by \$3\$ to get \$n = 31, m = 0\$As the mode is \$0\$, we calculate \$n\$ and \$c\$ as \$n = 0, c = 31\$. The \$31\$st ASCII character (alternatively, the character with ordinal \$63\$) is
?
We add
?
to the end ofd
, resulting ind = 'caird coinhering?'
and \$n = 0\$As \$n = 0\$, we are done, and we return
caird coinhering?
as our decompressed string
Alternatively, here is a version of the sss
function adjusted slightly.
Task
You are to take a positive integer \$n\$ as input and output the decompressed string that \$n\$ maps to. You may also take the two dictionaries ("short" and "long") as input if you wish. The dictionaries can be found on TIO or in the Jelly repo
You will never be given an input \$n\$ outside the native bounds of integers in your language, but your program must theoretically work for arbitrarily large integers
This is code-golf, so the shortest code in bytes wins
Test cases
n out
1 Aachen
2 aachen
3 !
47 Aah
218 aaronical
250 Abdul
745 abdominoplasties
7180 auto
8106 . aahs
364038195 Q unconfine
396478210 SoddyAberration
592528345 insulting abature
4060289999 Shool< aalborg
6079656777 CcircuityAachen
2402785962 njX abac
1192732966 flongAllel
69526673848 Kansu4Abderian
7240502929952 Eyehook% arval
7300618740196341 g noninterchangeableu mahwa
98944394632073037 /;streetwards Harz aachen
8092569718755799474 epos sporran@ Apriorism
11508828911594644653 /,e Waterbirdanelasticities
11209288138354511564 eale Thuya&decokes (note the leading space)
11683582443091721078 Saveable! duly babbliest (note the leading space)
13365392696538596641 tambourinists}Battu0abaca
Additionally, make sure your program works for \$n = 8609941742042387534416\$:
this
has
newlines
and also for \$n = 16505187\$:
a
b
And the outputs for \$1 \le n \le 100\$ (one per line): Try it online!