Skip to main content

🌐 Name all canonical things 🌐

Project description

🔢 nmr: name all canonical things 🔢

Give each canonical thing a unique English name using non-repeating words from a short list of common, short English words... or use a word list of your choice.

The word list is here: https://github.com/rec/nmr/blob/main/words.txt

Canonical things include but are not limited to:

  • numbers
  • fractions
  • times, dates, time intervals
  • lat/long positions on the earth
  • IP addresses
  • UUIDs

Other unimplemented possibilities:

  • Phone numbers
  • Periodic table
  • Chemical compounds(?) (probably not worth the huge effort)
  • Pieces of music! (my original motivating example)

Shorter or simpler things should generally be represented by shorter names.

Extending this to your own domain is easy and you can either add it to this codebase or write your own code and easily plug in in.

Installs both a module named nmr and an executable called nmr.py

EXAMPLE

import nmr

assert nmr(0) == ['the']
assert nmr(2718281828) == ['the', 'race', 'tie', 'hook']

for i in range(-2, 3):
    print(i, ':', *nmr(i))

# Prints
#   -2 : to
#   -1 : of
#   0 : the
#   1 : and
#   2 : a

HOW IT WORKS

All of this involves the same trick over and over again - counting using positional notation: https://en.wikipedia.org/wiki/Positional_notation

By default nmr has 1628 different words, which you can think of as 1628 different digits.

There's a wrinkle that makes things harder: the author decided that repeating words was unaesthetic, so counting is a little trickier, but you don't have to understand how it's done.

With repeating words eliminated, 1628 is the minimum total number of words needed to be able to represent all 64-bit integers with at most six words.

Conversion runs as follows.

First you take your type, whatever it is, and figure out a way to represent it as a number in positional notation, where perhaps the digits have different values.

Suppose you're wanting to represent the time of the day, down to milliseconds.

You represent it as a four digit number: hours, minutes, seconds, milliseconds

Next, you take the positional number, and evaluate it into a "type-relative number", a number that makes sense only within this type.

For example, to represent the time 15:11:55.823, we'd evaluate the number ((((15 * 60) + 11) * 60 + 55) * 1000 + 823) to get the type relative number, but this number might mean something completely different for say, lat-long.

Now, each type also gets its own fixed "type identifier number" and that gets combined with the type-relative number to give a new number, the nmr number which is unique over all types.

Then that nmr number is encoded into a non-repeating sequence of words from the word list, which is the nmr name.


In the reverse direction, a nmr name is given, and it's converted back into an nmr number, then split into the type identifier number and type-relative number.

The type identifier number is used to look up which type is being decoded, and then the type-relative number is decoded into the positional number, and finally back into the original type.


You are guaranteed that for each original canonical thing, T, there is a unique canonical name, and that decoding that name will always reproduce exactly the same thing.

It's mathematically an injection.

On the other hand, if you start with a random name and try to decode, a data type isn't required to give any guarantees at all.

You aren't even guaranteed that the decoding will return anything - some names just won't correspond even to a known type. If a name can be decoded to a known type, that type decoder might still not be able to come up with a type. Or, if it comes up with a type, that type might have a different canonical name.

This is all good because it makes it really easy to whip up an encoder/decoder, but for the basic encoders included with the program, we can offer a better guarantee: that we can always decode any any type-relative number and return an instance of the type, even if we weren't given a canonical name.

Separately, we add a "type wrapping" feature to the main program so that unknown type identifier numbers just wrap repeated over known type identifiers - again, this will never be a canonical name.

With those features, it means you can type random names into the program, and see what sort of thing you get.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nmr-0.10.0.tar.gz (14.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nmr-0.10.0-py3-none-any.whl (21.7 kB view details)

Uploaded Python 3

File details

Details for the file nmr-0.10.0.tar.gz.

File metadata

  • Download URL: nmr-0.10.0.tar.gz
  • Upload date:
  • Size: 14.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for nmr-0.10.0.tar.gz
Algorithm Hash digest
SHA256 3c20b5a188ffe028837658b7df456d47080961fcc016b84fbffe1974ee393579
MD5 b03ca77c47abebdd88fccc83562a8c54
BLAKE2b-256 2d1305c520cbcc5b750b1262f35e4695e758b66c1044f091e96e3c75e6c43d8e

See more details on using hashes here.

File details

Details for the file nmr-0.10.0-py3-none-any.whl.

File metadata

  • Download URL: nmr-0.10.0-py3-none-any.whl
  • Upload date:
  • Size: 21.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for nmr-0.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d9f2610162156edcb38a173448f2b07d3251a3f15ab1d5474eb4887d7dcf5159
MD5 9554fc2554539d7d7b5984993c6b2208
BLAKE2b-256 436b952b6c826c888f08a77ec21244213447c232947f0b994fdbaf2d1fb98ebc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page