# Re: Factor

Factor: the language, the theory, and the practice.

## Proquint

Tuesday, February 7, 2023

A few days ago, Ciprian Dorin Craciun wrote a binary to text encoding blog post about the “state of the art and missed opportunities” in various encoding schemes. In that post, I was introduced to the Proquint encoding which stands for “PRO-nouncable QUINT-uplets”.

In the Factor programming language, we have enjoyed implementing many encoding/decoding methods including: base16, base24, base32, base32hex, base32-crockford, base36, base58, base62, base64, base85, base91, uu, and many others. I thought it would be fun to add a quick implementation of Proquint.

Like other encodings, it makes use of an alphabet – grouped as consonants and vowels:

``````CONSTANT: consonant "bdfghjklmnprstvz"

CONSTANT: vowel "aiou"
``````

Numbers are grouped into 5-character blocks representing a 16-bit number, with alternating consonants representing 4 bits and vowels representing 2 bits:

``````: >quint16 ( m -- str )
5 [
even? [
[ -4 shift ] [ 4 bits consonant nth ] bi
] [
[ -2 shift ] [ 2 bits vowel nth ] bi
] if
] "" map-integers-as reverse nip ;
``````

Encoding a 32-bit number is made by joining two 16-bit blocks:

``````: >quint32 ( m -- str )
[ -16 shift ] keep [ 16 bits >quint16 ] bi@ "-" glue ;
``````

Decoding numbers looks up each consonant or vowel, skipping separators:

``````: quint> ( str -- m )
0 [
dup \$[ consonant alphabet-inverse ] nth [
nip [ 4 shift ] [ + ] bi*
] [
dup \$[ vowel alphabet-inverse ] nth [
nip [ 2 shift ] [ + ] bi*
] [
CHAR: - assert=
] if*
] if*
] reduce ;
``````

We can use this to make a random password that might be more memorable – but perhaps more secure if using more random-bits:

``````: quint-password ( -- quint )
32 random-bits >quint32 ;
``````

And we could use our ip-parser vocabulary to make IPv4 addresses more memorable:

``````: ipv4>quint ( ipv4 -- str )
ipv4-aton >quint32 ;

: quint>ipv4 ( str -- ipv4 )
quint> ipv4-ntoa ;
``````

You can see how this might work by building a test suite to show roundtrips work:

``````{ t } [
{
{ "63.118.7.35"     "gutuk-bisog" }
{ "140.98.193.141"  "mudof-sakat" }
{ "64.255.6.200"    "haguz-biram" }
{ "128.30.52.45"    "mabiv-gibot" }
{ "147.67.119.2"    "natag-lisaf" }
{ "212.58.253.68"   "tibup-zujah" }
{ "216.35.68.215"   "tobog-higil" }
{ "216.68.232.21"   "todah-vobij" }
{ "198.81.129.136"  "sinid-makam" }
{ "12.110.110.204"  "budov-kuras" }
} [
[ quint>ipv4 = ] [ swap ipv4>quint = ] 2bi and
] assoc-all?
] unit-test
``````

This is now available as the proquint vocabulary in a recent nightly build.