Write a program which can encode text to avoid reusing characters, and convert back.
Both normal and encoded forms are restricted to a particular character set: the space character with code point 32, the tilde character
~
with code point 126, and all characters between. This is 95 total characters. It's a printable subset of ASCII.
The encoded text can be up to 95 characters long. The normal text can be up to 75 characters long, because above 75 it would be impossible to uniquely encode all messages.
Encoding
There are some requirements for the encoding:
- Uses only characters from the character set described above
- Uses each character at most once
- Uniquely encodes all valid messages
Other than that, you're free to pick any variant.
Input
Input will consist of 2 items:
- A boolean: false to encode, true to decode
- A string: the message to be encoded/decoded
How you receive the input is up to you.
The boolean can be as a boolean or integer in the range [-2, 2] in your language's format. If the esoteric language doesn't have booleans or integers, use the closest analogue. I'm not doing the "or any 2 distinct values" because then you could use an encoding and decoding program as the values and evaluate them.
Output
Output should consist of only the encoded/decoded string. Leading and trailing newlines are okay.
Scoring
Your score is the length of your program, shorter is better.
I still encourage you to try harder languages even if they won't win.
Testing
Testing will generally be done with Try it Online!. For convenience, please provide a link to your program with some test input already filled in.
These are the steps to test a program:
- Pick a valid normal string.
- Encode it using the program.
- Check that the encoded form is valid.
- Decode it using the program.
- Check that the final result matches the original string.
This can be repeated with other test strings for confidence.
If you show a working case and no failing cases have been found, we will assume your program works.
Reference Implementation
I am providing a reference implementation that shows one possible method, in hopes of making this problem more approachable. I used it to generate the examples. I recommend you try the problem yourself before looking at how I did it, that way you may independently come up with a better mapping.
Examples
Since you can choose a different encoding, as well as different input/output methods, your program might not match these examples.
Empty
Input:
0Output:
(none)
Input:
1Output:
(none)
Small
Input:
0 Hello, world!
Output:
#mvcD_YnEeX5?
Input:
1 #mvcD_YnEeX5?
Output:
Hello, world!
Max Size
Input:
0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Output:
C-,y=6Js?3TOISp+975zk}.cwV|{iDjKmd[:/]$Q1~G8vAneoh #&<LYMPNZB_x;2l*r^(4E'tbU@q>a!\WHuRFg0"f%X`)
Input:
1 C-,y=6Js?3TOISp+975zk}.cwV|{iDjKmd[:/]$Q1~G8vAneoh #&<LYMPNZB_x;2l*r^(4E'tbU@q>a!\WHuRFg0"f%X`)
Output:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Extras
How did I get the 75 characters limit? I could have brute force checked it of course, but there's a slightly more mathematical method for counting the number of possible encoded messages for a given character set:
$$ F(n)=\sum_{k=0}^{n}{\frac{n!}{(n-k)!}}=e\Gamma(n+1,1)\approx en! $$
Here are the relevant bounds. There's plenty more valid encoded messages than normal messages, but still enough normal messages that you'll need a variable length encoding.
$$ F(95)\approx 2.81\times 10^{148} \\ {95}^{75}\approx 2.13\times 10^{148} \\ 95!\approx 1.03\times 10^{148} $$
The problem was inspired by a phenomenon on the Discord chat platform. In Discord, you can "react" to chat messages, which adds a little emoji underneath. You can react many times on a single chat message. Each emoji can only be added once. They remember the order they were added and display oldest to newest, left to right. You can add some non-emojis too. People sometimes write short messages in reactions, and when their message has repeat characters they're forced to get creative, usually they opt for lookalike characters.