Skip to content

Instantly share code, notes, and snippets.

@kyr0
Created November 16, 2025 18:21
Show Gist options
  • Select an option

  • Save kyr0/6a34795a036551af2b82fe17efdc9591 to your computer and use it in GitHub Desktop.

Select an option

Save kyr0/6a34795a036551af2b82fe17efdc9591 to your computer and use it in GitHub Desktop.
Aton Nif
/**
* Base-12 Duodecimal Converter
* Custom digit set: 0, 1, 2, 3, 4, 5, Å, 6, №, 7, 8, 9
* Each digit represents values 0-11 respectively
*/
// Digit mapping: custom digit -> decimal value (0-11)
const DIGIT_TO_VALUE = {
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'Å': 6,
'6': 7,
'№': 8,
'7': 9,
'8': 10,
'9': 11
};
// Reverse mapping: decimal value (0-11) -> custom digit
const VALUE_TO_DIGIT = {
0: '0',
1: '1',
2: '2',
3: '3',
4: '4',
5: '5',
6: 'Å',
7: '6',
8: '№',
9: '7',
10: '8',
11: '9'
};
/**
* Parse a base-N string to a decimal number
* @param {string} str - The base-N string to parse
* @param {number} base - The base to use (default: 12, valid range: 2-12)
* @returns {number} - The decimal equivalent
*/
function parseAtonNif(str, base = 12) {
if (!str || typeof str !== 'string') {
throw new Error('Input must be a non-empty string');
}
if (typeof base !== 'number' || !Number.isInteger(base) || base < 2 || base > 12) {
throw new Error('Base must be an integer between 2 and 12');
}
// Remove whitespace and convert to uppercase for consistency
str = str.trim().toUpperCase();
if (str === '') {
throw new Error('Input string cannot be empty');
}
let result = 0;
// Process from left to right (most significant to least significant)
for (let i = 0; i < str.length; i++) {
const char = str[i];
if (!(char in DIGIT_TO_VALUE)) {
throw new Error(`Invalid digit '${char}' at position ${i}. Valid digits are: 0, 1, 2, 3, 4, 5, A, 6, N, 7, 8, 9`);
}
const digitValue = DIGIT_TO_VALUE[char];
if (digitValue >= base) {
throw new Error(`Digit '${char}' (value ${digitValue}) is invalid for base ${base}. Maximum digit value is ${base - 1}`);
}
result = result * base + digitValue;
}
return result;
}
/**
* Render a decimal number to base-12 duodecimal string
* @param {number} num - The decimal number to convert
* @returns {string} - The base-12 string representation
*/
function renderAtonNif(num) {
if (typeof num !== 'number' || !Number.isInteger(num)) {
throw new Error('Input must be an integer');
}
if (num < 0) {
throw new Error('Negative numbers are not supported');
}
if (num === 0) {
return '0';
}
const base = 12;
const digits = [];
// Convert to base-12
while (num > 0) {
const remainder = num % base;
digits.unshift(VALUE_TO_DIGIT[remainder]);
num = Math.floor(num / base);
}
return digits.join('');
}
// Export for use in other modules
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
parseAtonNif,
renderAtonNif,
DIGIT_TO_VALUE,
VALUE_TO_DIGIT
};
}
// Example usage and testing
if (typeof window !== 'undefined') {
// Make functions available globally for browser console testing
window.parseAtonNif = parseAtonNif;
window.renderAtonNif = renderAtonNif;
// Test cases
console.log('Base-12 Duodecimal Converter Examples:');
console.log('parseAtonNif("0") =', parseAtonNif('0')); // 0
console.log('parseAtonNif("1") =', parseAtonNif('1')); // 1
console.log('parseAtonNif("5") =', parseAtonNif('5')); // 5
console.log('parseAtonNif("Å") =', parseAtonNif('Å')); // 6
console.log('parseAtonNif("6") =', parseAtonNif('6')); // 7
console.log('parseAtonNif("№") =', parseAtonNif('№')); // 8
console.log('parseAtonNif("9") =', parseAtonNif('9')); // 11
console.log('parseAtonNif("10") =', parseAtonNif('10')); // 12 (1*12 + 0 = 12)
console.log('parseAtonNif("99") =', parseAtonNif('99')); // 143 (11*12 + 11 = 132 + 11 = 143)
console.log('\nDifferent base examples:');
console.log('parseAtonNif("10", 8) =', parseAtonNif('10', 8)); // 8 (1*8 + 0 = 8)
console.log('parseAtonNif("Å", 7) =', parseAtonNif('Å', 7)); // 6
console.log('parseAtonNif("5", 6) =', parseAtonNif('5', 6)); // 5
console.log('\nrenderAtonNif(0) =', renderAtonNif(0)); // "0"
console.log('renderAtonNif(1) =', renderAtonNif(1)); // "1"
console.log('renderAtonNif(5) =', renderAtonNif(5)); // "5"
console.log('renderAtonNif(6) =', renderAtonNif(6)); // "Å"
console.log('renderAtonNif(7) =', renderAtonNif(7)); // "6"
console.log('renderAtonNif(8) =', renderAtonNif(8)); // "№"
console.log('renderAtonNif(11) =', renderAtonNif(11)); // "9"
console.log('renderAtonNif(12) =', renderAtonNif(12)); // "10"
console.log('renderAtonNif(143) =', renderAtonNif(143)); // "99"
// Round-trip test
console.log('\nRound-trip test:');
const testNumbers = [0, 1, 5, 11, 12, 25, 50, 100, 143];
testNumbers.forEach(n => {
const converted = renderAtonNif(n);
const back = parseAtonNif(converted);
console.log(`${n} -> "${converted}" -> ${back} ${n === back ? '✓' : '✗'}`);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment