AlpID specification

Last updated Dec 30, 2022
iter.caPages

0: Introduction

An AlpID represents a non-negative integral value. It is a binary-to-text encoding for numbers that only uses the 22 unambiguous characters of the Latin alphabet (B, I, L, and O are omitted). AlpIDs sort in the same order as the integers they represent.

In this document, all indexing is zero-indexed.

1: AlpID format

AlpIDs encode non-negative integral values as base 22 numbers written in the AlpID alphabet. The AlpID alphabet is ACDEFGHJKMNPQRSTUVWXYZ. The AlpID alphabet excludes 4 letters:

Letter Reason
B Similar to 8
I Similar to L when lowercase
L Similar to I when lowercase
O Similar to 0

The canonical form of an AlpID is all uppercase. It is valid for an AlpID to be written with lowercase letters. Implementations must reject AlpIDs that contain characters outside of the AlpID alphabet.

2: Converting integers to AlpIDs

2.1: Algorithm

This process produces the AlpID in str (which is initially empty) from a number, n.

  1. Set idx to n modulo 22.
  2. Prepend the idxth character of the AlpID alphabet to str.
  3. Set n to floor(n ÷ 22).
  4. If n is 0, stop.
  5. Go to step 2.1.1.

2.2: Example implementation

In JavaScript:

const ALPHABET = "ACDEFGHJKMNPQRSTUVWXYZ";
function toAlpId(n) {
  let str = "";
  do {
    str = ALPHABET[n % ALPHABET.length] + str;
    n = Math.floor(n / ALPHABET.length);
  } while (n !== 0)
  return str;
}
toAlpId(50) // -> DH

3: Converting AlpIDs to integers

3.1: Algorithm

This process produces the integral value of an AlpId, str, in n.

  1. Set n and idx to 0.
  2. Reverse str.
  3. Set value to the index of the character of the AlpID alphabet that corresponds to the idxth character of str (case-insensitively).
  4. Add value × (22idx) to n.
  5. If idx equals the length of str, stop.
  6. Add 1 to idx.
  7. Go to step 3.1.3.

3.2: Example implementation

const ALPHABET = "ACDEFGHJKMNPQRSTUVWXYZ";
function parseAlpId(s) {
  s = s.toUpperCase();
  const values = s.split("").reverse().map(l => ALPHABET.indexOf(l));
  if (!values.every(value => value !== -1)) throw new Error("not an AlpID");
  
  return values
    .map((value, idx) => value * (ALPHABET.length ** idx))
    .reduce((a, b) => a + b);
}
parseAlpId("FDY") // -> 2000

4: Example AlpIDs

AlpID Value
A 0
C 1
FQ 100
DCN 1000
FQDYMT 23456789

5: Resources

Send feedback on AlpID to alpid@iter.ca.