Home > Back-end >  Map a PIN to and from an array of strings
Map a PIN to and from an array of strings

Time:09-23

I’m working on a treasure hunt/escape room type game, where players have to solve 4 real-world puzzles which all give them a word. When they’ve completed all the puzzles, they should head to a tiny webapp where they can enter the words they found: the app then converts these words into a final secret -- in this case, the 4-digit code to a padlock with a treasure.

Now, it would be easy if the list of valid words were static, but it’s an interactive system where the puzzles’ output change constantly between players. I’m trying to think of a simple algorithm so we can encode and decode PINs into and from arrays of words, so that they can be changed across games, and only people setting the code know the PIN and then change the answers of each game.

These are the constraints:

  • the app does not need to know if a code is right or wrong. It only has an encode feature (here’s a padlock code, give me 4 words) and a decode feature (here’s 4 words, give me a matching padlock code). So players can enter any words and just receive a code in return, but there’s no guarantee that it’s the right one.
  • ideally the order of words does not matter (given the input “green grass legend party” outputs the same PIN as “grass green party legend”), but this sounds like it could complicate things a lot, so I’m happy to make it so codes need to be entered in a certain order
  • this is for a game, there’s no need to be cryptographically secure here
  • I do have an array of secret words already, so essentially just need to find an array of 4 numbers from a base number that will always come out the same.

For example

Encode:
Input: 8370, output [“danger”, “writer”, “negative”, “origin”]   
Input: 8375, output [“crab”, “junior”, “spider”, “pillar”]
Input: 2455, output [“party”, “fish”, “cookie”, “cactus”]


Decode:
Input: [“danger”, “writer”, “negative”, “origin”], output 8370
Input: [“writer”, “danger”, “negative”, “origin”], output 8370
Input: [“party”, “fish”, “cookie”, “cactus”], output 2455
Input [“pillar”, “crab”, “spider”, “junior”], output: 8375

I’m not necessarily looking for a full solution to this problem, but I’d really like pointers on where to look -- algorithms, libraries, existing work. Keywords to find an app that already does that, or an existing algorithm, led me nowhere. I’ve tried a few options (looping through an array of words by adding the PIN as an index) but always get stuck on how to decode it.

CodePudding user response:

Since your numeral code is made of four digits, there are only 10,000 possibilities. You can download an English dictionary and randomly generate 10,000 combinations of four words corresponding to the 10,000 possible numeral codes. Then create two Python dictionaries, one mapping a numeral code to an English phrase, and the other one mapping an English phrase to a numeral code. Note that since a Python dictionary's key has to be of an immutable type, you can not define lists of words as keys. You will have to use some other structure, like frozenset or a custom class, but this is mostly a technicality. If you want the encoding-decoding process to be order-agnostic, this is not a problem. Just order the four words passed to the decoding method lexicographically and define another dictionary which maps an English phrase given in lexicographic order to the desired English phrase (same words, potentially different order).

  • Related