portunus
Version:
Converts from decimal numbers to roman numerals and the other way around.
112 lines • 5.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const romanNumeralToDecimalValueMap = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000,
};
const decimalValueToRomanNumeralMap = Object.keys(romanNumeralToDecimalValueMap)
.reduce((acc, currentValue) => {
return Object.assign({ [romanNumeralToDecimalValueMap[currentValue]]: currentValue }, acc);
}, {});
const sortedNumeralCollection = Object.keys(romanNumeralToDecimalValueMap)
.sort((a, b) => romanNumeralToDecimalValueMap[b] - romanNumeralToDecimalValueMap[a]);
const sortedDecimalCollection = Object.keys(decimalValueToRomanNumeralMap)
.map(d => parseInt(d, 10))
.sort((a, b) => b - a);
function isPortunusInput(input) {
return typeof input === 'string' || typeof input === 'number';
}
function portunus(input) {
if (!isPortunusInput(input)) {
return {
error: `Provided input (${input}) not a valid portunus input.`,
};
}
if (typeof input === 'string') {
return { convertedValue: portunusPeonNumeralToDecimal(input.toUpperCase()) };
}
if (typeof input === 'number') {
return { convertedValue: portunusPeonDecimalToNumeral(input) };
}
return {
error: `Something went wrong, perhaps input type check failed? I expect a number or string as input and got: ${typeof input}`,
};
}
exports.portunus = portunus;
function portunusPeonNumeralToDecimal(numeral) {
const numeralCollection = [].slice.call(numeral);
return numeralCollection.reduce((acc, currentValue, currentIndex) => {
const decimalValueForCurrentNumeral = romanNumeralToDecimalValueMap[currentValue];
const previousNumeral = numeralCollection[currentIndex - 1];
const decimalValueForPreviousNumeral = romanNumeralToDecimalValueMap[previousNumeral];
const subtractiveNotationPresent = !!decimalValueForPreviousNumeral && (decimalValueForPreviousNumeral < decimalValueForCurrentNumeral);
let runningTally = acc + decimalValueForCurrentNumeral;
if (subtractiveNotationPresent) {
runningTally -= (decimalValueForPreviousNumeral * 2);
}
return runningTally;
}, 0);
}
function portunusPeonDecimalToNumeral(integer) {
const numeralWithoutSubtractiveNotation = sortedDecimalCollection
.reduce((acc, currentDecimal) => {
let numeral = decimalValueToRomanNumeralMap[currentDecimal];
let occurencesOfNumeral = Math.floor(integer / currentDecimal);
integer -= (currentDecimal * occurencesOfNumeral);
return `${acc}${numeral.repeat(occurencesOfNumeral)}`;
}, '');
const numeralWithoutSubtractiveNotationCollection = [].slice.call(numeralWithoutSubtractiveNotation);
let numeralWithSubtractiveNotationCollection = [];
for (let i = 0; i < numeralWithoutSubtractiveNotationCollection.length; ++i) {
const numeral = numeralWithoutSubtractiveNotationCollection[i];
const numeralRankIndex = sortedNumeralCollection.indexOf(numeral);
const nextLowestRankingNumeralIndex = numeralRankIndex + 1;
const nextLowestRankingNumeral = sortedNumeralCollection[nextLowestRankingNumeralIndex];
const nextHighestRankingNumeralIndex = numeralRankIndex - 1;
const nextHighestRankingNumeral = sortedNumeralCollection[nextHighestRankingNumeralIndex];
const nextFourNumerals = [1, 2, 3, 4].map(indexOffset => numeralWithoutSubtractiveNotationCollection[i + indexOffset]);
const nextThreeNumerals = nextFourNumerals.slice(0, 3);
/*console.log({
numeralWithSubtractiveNotationCollection,
numeral,
numeralRankIndex,
nextLowestRankingNumeral,
nextLowestRankingNumeralIndex,
nextHighestRankingNumeral,
nextHighestRankingNumeralIndex,
nextFourNumerals,
nextThreeNumerals,
});*/
if (!!nextHighestRankingNumeral) {
if (nextThreeNumerals.every(n => sortedNumeralCollection.indexOf(n) === numeralRankIndex)) {
/*console.log({
msg: 'here in next three',
nextThreeNumerals,
numeralWithoutSubtractiveNotation,
});*/
numeralWithSubtractiveNotationCollection.push(`${numeral}${nextHighestRankingNumeral}`);
i += 3;
continue;
}
if (nextFourNumerals.every(n => sortedNumeralCollection.indexOf(n) === nextLowestRankingNumeralIndex)) {
/*console.log({
msg: 'here in next four',
nextFourNumerals,
numeralWithoutSubtractiveNotation,
});*/
numeralWithSubtractiveNotationCollection.push(`${nextLowestRankingNumeral}${nextHighestRankingNumeral}`);
i += 4;
continue;
}
}
numeralWithSubtractiveNotationCollection.push(numeral);
}
;
return numeralWithSubtractiveNotationCollection.join('');
}
//# sourceMappingURL=portunus.js.map