Skip to content

Instantly share code, notes, and snippets.

@Sigmus
Last active December 24, 2015 00:49
Show Gist options
  • Save Sigmus/6719824 to your computer and use it in GitHub Desktop.
Save Sigmus/6719824 to your computer and use it in GitHub Desktop.
//
// Escolhe qual conversão utilizar dependendo do input
//
function converter(input) {
if (typeof input === 'number') {
return toRoman(input);
}
else {
return toIndu(input);
}
}
//
// Converte algarismos romanos para indu-arábicos
//
function toIndu(roman) {
var roman = roman.split('');
var matrix = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000 };
var order = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];
//
// Validações
//
if (roman.some(nextFiveInvalid) || ! roman.every(nextBiggerValid) || roman.some(fourEquals)) {
return false;
}
//
// Engine da parada
//
function convert(indu, letter, index, roman) {
if (nextBigger(letter, index, roman)) {
indu -= matrix[letter];
}
else {
indu += matrix[letter];
}
return indu;
}
//
// Aplica engine para cada um dos algarismos
//
return roman.reduce(convert, 0);
//
// Fuções utilitárias
//
function hasNext(letter, index, roman) {
return typeof roman[index + 1] === 'string';
}
function nextEqual(letter, index, roman) {
return hasNext(letter, index, roman)
&& roman[index] === roman[index + 1];
}
function nextBigger(letter, index, roman) {
return hasNext(letter, index, roman)
&& matrix[roman[index + 1]] > matrix[roman[index]];
}
function biggerValid(letter, index, roman) {
return (order.indexOf(roman[index + 1]) - order.indexOf(roman[index])) <= 2
&& (matrix[roman[index + 1]] / matrix[letter]) != 2;
}
function nextBiggerValid(letter, index, roman) {
return ! nextBigger(letter, index, roman)
|| biggerValid(letter, index, roman);
}
function nextFiveInvalid(letter, index, roman) {
return nextEqual(letter, index, roman)
&& beginsWithFive(letter[index]);
}
function beginsWithFive(value) {
return new String(matrix[value])[0] === '5';
}
function fourEquals(letter, index, roman) {
return nextEqual(letter, index, roman)
&& nextEqual(letter, index + 1, roman)
&& nextEqual(letter, index + 2, roman)
}
}
//
// Converte algarismos indu-arábicos para romanos
//
function toRoman(indu) {
var r1000 = convert(indu, 1000, 'M'); //console.log(r1000)
var r100 = convert(r1000.indu, 100, 'C', 'D', 'M'); //console.log(r100)
var r10 = convert(r100.indu, 10, 'X', 'L', 'C'); //console.log(r10)
var r1 = convert(r10.indu, 1, 'I', 'V', 'X'); //console.log(r1)
return r1000.roman + r100.roman + r10.roman + r1.roman;
function repeat(times, char) {
var snippet = '';
for (var i = 0; i < times; i++) {
snippet += char;
}
return snippet;
}
function convert(indu, base, low, middle, high) {
var roman = ''
var times;
if (indu >= (1 * base) && indu < (4 * base)) {
times = Math.floor(indu / base);
roman = repeat(times, low);
indu -= (times * base);
}
else if (indu >= (4 * base) && indu < (5 * base)) {
times = Math.floor(indu / base);
roman = low + middle;
indu -= (times * base);
}
else if (indu === (5 * base)) {
roman = middle;
}
else if (indu > (5 * base) && indu < (9 * base)) {
times = Math.floor(indu / base) - 5;
roman = middle + repeat(times, low);
indu -= (times * base + (5 * base));
}
else if (indu >= (9 * base) && indu < (10 * base)) {
roman = low + high;
indu -= (9 * base);
}
else if (indu === (10 * base)) {
roman = high;
}
return {
roman: roman,
indu: indu
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment