Patoshi パトシ
Patoshi パトシ

Reputation: 23445

Compress alphanumeric characters with a limit of 8 bytes hex character

My application has a limit input of 16 hex characters to represent 8 ASCII characters. The only characters I need are A-Z and 0-9. I do not need lower cases or any non-standard alphanumeric characters. A 2 character hex can represent all of the characters on the keyboard, but I don't need all of it.

Is there some type of library that can compress the alphanumeric string to be able to fit it in 16 hex characters?

Example:

12345678 = 31 32 33 34 35 36 37 38

I want to be able to pack in more alphanumeric characters like this:

ABCDEFGHI12345678 = 31 32 33 34 35 36 37 38

Is there a library that does this?

Upvotes: 0

Views: 650

Answers (1)

Stratubas
Stratubas

Reputation: 3067

After some experimentation, here's my compression algorithm.

It takes a 6-character message containing A-Z and 0-9 and turns it into 8 hex characters.

It can be used twice to compress as 12-character string into 16 hex characters.

If my math is correct, this is the best compression you can achieve, because 16^16 is almost equal to 36^(12.38), which means that you can fit at most 12 characters of a 36-character set (A-Z, 0-9) into 16 hex characters.

I hope it'll be useful for your application.

const testMessage = '6CHARS';

function charToInt(char, shift) {
  let charCode = char.charCodeAt(0) - 48;
  if (charCode > 9) {
    charCode -= 7;
  }
  charCode *= 36 ** shift;
  return charCode;
}

function intToChar(int, shift) {
  let number = int / (36 ** shift);
  if (number > 9) {
    number += 7;
  }
  number += 48;
  return String.fromCharCode(number);
}

function stringToInt(stringWithSixCharacters) {
  let result = 0;
  for (let index = 0; index < 6; index++) {
    result += charToInt(stringWithSixCharacters.charAt(index), 5 - index);
  }
  return result;
}

function intToString(intFromSixCharacters) {
  let number = intFromSixCharacters;
  let result = '';
  for (let index = 0; index < 6; index++) {
    const mod = number % (36 ** (index + 1));
    const char = intToChar(mod, index);
    result = char + result;
    number = number - mod;
  }
  return result;
}

function intToHex(int) {
    return int.toString(16).padStart(8, '0').toUpperCase();
}

function hexToInt(hex) {
    return parseInt(messageHex, 16);
}

console.log('testMessage:', testMessage);
const messageCode = stringToInt(testMessage);
const messageHex = intToHex(messageCode);
console.log('messageCode:', messageCode);
console.log('hex:', messageHex); // prints '16DFB4C8'
const extractedMessageCode = hexToInt(messageHex);
const extractedMessage = intToString(extractedMessageCode);
console.log('extractedMessageCode:', extractedMessageCode);
console.log('extractedMessage:', extractedMessage); // prints '6CHARS'

Upvotes: 1

Related Questions