( stringInBaseOne, baseOneCharacterString, baseTwoCharacterString )
| 19 | * @returns {string} |
| 20 | */ |
| 21 | const convertArbitraryBase = ( |
| 22 | stringInBaseOne, |
| 23 | baseOneCharacterString, |
| 24 | baseTwoCharacterString |
| 25 | ) => { |
| 26 | if ( |
| 27 | [stringInBaseOne, baseOneCharacterString, baseTwoCharacterString] |
| 28 | .map((arg) => typeof arg) |
| 29 | .some((type) => type !== 'string') |
| 30 | ) { |
| 31 | throw new TypeError('Only string arguments are allowed') |
| 32 | } |
| 33 | |
| 34 | const baseOneCharacters = [...baseOneCharacterString] |
| 35 | const baseTwoCharacters = [...baseTwoCharacterString] |
| 36 | |
| 37 | for (const charactersInBase of [baseOneCharacters, baseTwoCharacters]) { |
| 38 | if (charactersInBase.length !== new Set(charactersInBase).size) { |
| 39 | throw new TypeError( |
| 40 | 'Duplicate characters in character set are not allowed' |
| 41 | ) |
| 42 | } |
| 43 | } |
| 44 | const reversedStringOneChars = [...stringInBaseOne].reverse() |
| 45 | const stringOneBase = baseOneCharacters.length |
| 46 | let value = 0 |
| 47 | let placeValue = 1 |
| 48 | for (const digit of reversedStringOneChars) { |
| 49 | const digitNumber = baseOneCharacters.indexOf(digit) |
| 50 | if (digitNumber === -1) { |
| 51 | throw new TypeError(`Not a valid character: ${digit}`) |
| 52 | } |
| 53 | value += digitNumber * placeValue |
| 54 | placeValue *= stringOneBase |
| 55 | } |
| 56 | const outputChars = [] |
| 57 | const stringTwoBase = baseTwoCharacters.length |
| 58 | while (value > 0) { |
| 59 | const [divisionResult, remainder] = floorDiv(value, stringTwoBase) |
| 60 | outputChars.push(baseTwoCharacters[remainder]) |
| 61 | value = divisionResult |
| 62 | } |
| 63 | return outputChars.reverse().join('') || baseTwoCharacters[0] |
| 64 | } |
| 65 | |
| 66 | /** |
| 67 | * Converts a arbitrary-length string from one base to other. Doesn't lose accuracy. |
no test coverage detected