Преобразовать число в римскую цифру в javaScript - PullRequest
50 голосов
/ 31 января 2012

Как я могу преобразовать целые числа в римские цифры ?

function romanNumeralGenerator (int) {

}

Например, см. Следующие примеры входов и выходов:

1 = "I"
5 = "V"
10 = "X"
20 = "XX"
3999 = "MMMCMXCIX"

Предупреждение: поддерживаются только цифры от 1 до 3999

Ответы [ 58 ]

0 голосов
/ 19 сентября 2018

Наверное, самое простое решение:

rome = n => {
    b=0
    s=''
    for(a=5; n; b++,a^=7)
        for(o=n%a, n=n/a^0;o--;)
            s='IVXLCDM'[o>2?b+n-(n&=-2)+(o=1):b]+s
    return s
}

r = [rome(892),rome(3999)];

console.log(r);

Я не могу взять кредит, хотя. Это решение vetalperko для CodeSignal.

0 голосов
/ 18 мая 2017

Я только что завершил это на freeCodeCamp, я не видел этого конкретного решения.Я знаю, что это решение можно оптимизировать с помощью рекурсии, но я просто хотел добавить его, чтобы, по крайней мере, вы могли видеть другие варианты:

function convertToRoman(num) {
  var value = [];
  var temp, base, buffer;

  var letters = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];
  var offsets = [
    [1, 0],  // 1
    [2, 0],  // 2
    [3, 0],  // 3
    [-1, 1], // 4
    [0, 1],  // 5
    [1, 1],  // 6
    [2, 1],  // 7
    [3, 1],  // 8
    [-2, 2],  // 9
  ];

  // cascade through each denomination (1000's, 100's, 10's, 1's) so that each denomination is triggered

  // Thousands
  if (num >= 1000) {
    temp = Math.floor(num / 1000);

    buffer = offsets[temp - 1];

    base = 6;

    value.push(getValue(base, letters, buffer));

    num -= temp * 1000;
  }

  // Hundreds
  if (num >= 100) {
    temp = Math.floor(num / 100);

    buffer = offsets[temp - 1];

    base = 4;

    value.push(getValue(base, letters, buffer));

    num -= temp * 100;
  }

  // Tens
  if (num >= 10) {
    temp = Math.floor(num / 10);

    buffer = offsets[temp - 1];

    base = 2;

    value.push(getValue(base, letters, buffer));

    num -= temp * 10;
  }

  // Ones
  if (num > 0) {

    buffer = offsets[num - 1];

    base = 0;

    value.push(getValue(base, letters, buffer));
  }

  // Finish

  return value.join('');
}


function getValue(base, letters, buffer) {
  var val1 = buffer[0], val2 = buffer[1];
  var value = [];

  // If val1 is less than 0 then we know it is either a 4 or 9, which has special cases
  if (val1 < 0) {
    // Push the base index, then push the base plus the val2 offset
    value.push(letters[base]);
    value.push(letters[base + val2]);
  } else {
    // Push a letter if val2 is set - meaning we need to offset a number that is equal to or higher than 5
    // 5 is basically the only scenario which this will exist
    if (val2 > 0) value.push(letters[base + val2]);

    // Now add in the next letters of the base for the inciment
    for (var i = 0; i < val1; i++) {
      value.push(letters[base]);
    }
  }

  return value.join('');
}

convertToRoman(90);

Я почти уверен, что функция-компаньон означает, что она может иметь почти безграничныйпотенциал, при условии, что вы предоставляете правильные символы для чисел, превышающих M, но не указывайте меня на этом.

0 голосов
/ 24 октября 2018

Вот мой код, надеюсь, это полезно:

function convertToRoman(num) {
    let numArr = [];//[M,D,C,L,X,V,I]
    let numStr = "";

    //get num Array
    numArr.push(parseInt(num / 1000));
    num %= 1000;
    numArr.push(parseInt(num / 500));
    num %= 500;
    numArr.push(parseInt(num / 100));
    num %= 100;
    numArr.push(parseInt(num / 50));
    num %= 50;
    numArr.push(parseInt(num / 10));
    num %= 10;
    numArr.push(parseInt(num / 5));
    num %= 5;
    numArr.push(num);

    //cancat num String
    for(let i = 0; i < numArr.length; i++) {
        switch(i) {
            case 0://M
                for(let j = 0; j < numArr[i]; j++) {
                    numStr = numStr.concat("M");
                }
                break;
            case 1://D
                switch(numArr[i]) {
                    case 0:
                        
                        break;
                    case 1:
                        if(numArr[i + 1] === 4) {
                            numStr = numStr.concat("CM");
                            i++;
                        }else {
                            numStr = numStr.concat("D");
                        }
                        break;
                }
                break;
            case 2://C
                switch(numArr[i]) {
                    case 0:
                        
                        break;
                    case 1:
                        numStr = numStr.concat("C");
                        break;
                    case 2:
                        numStr = numStr.concat("CC");
                        break;
                    case 3:
                        numStr = numStr.concat("CCC");
                        break;
                    case 4:
                        numStr = numStr.concat("CD");
                        break;
                }
                break;
            case 3://L
                switch(numArr[i]) {
                    case 0:
                        
                        break;
                    case 1:
                        if(numArr[i + 1] === 4) {
                            numStr = numStr.concat("XC");
                            i++;
                        }else {
                            numStr = numStr.concat("L");
                        }
                        break;
                }
                break;
            case 4://X
                switch(numArr[i]) {
                    case 0:
                        
                        break;
                    case 1:
                        numStr = numStr.concat("X");
                        break;
                    case 2:
                        numStr = numStr.concat("XX");
                        break;
                    case 3:
                        numStr = numStr.concat("XXX");
                        break;
                    case 4:
                        numStr = numStr.concat("XL");
                        break;
                }
                break;
            case 5://V
                switch(numArr[i]) {
                    case 0:
                        
                        break;
                    case 1:
                        if(numArr[i + 1] === 4) {
                            numStr = numStr.concat("IX");
                            i++;
                        }else {
                            numStr = numStr.concat("V");
                        }
                        break;
                }
                break;
            case 6://I
                switch(numArr[i]) {
                    case 0:
                        
                        break;
                    case 1:
                        numStr = numStr.concat("I");
                        break;
                    case 2:
                        numStr = numStr.concat("II");
                        break;
                    case 3:
                        numStr = numStr.concat("III");
                        break;
                    case 4:
                        numStr = numStr.concat("IV");
                        break;
                }
                break;
        }
    }
    console.log(numStr);
    return numStr;
}

convertToRoman(3999);
0 голосов
/ 24 мая 2017

Вот способ сделать это без необходимости циклически перебирать все различные римские цифры и их соответствующие номера. Он имеет постоянное время поиска O(1), что немного экономит время.

Он разбивает каждое целое число справа налево, поэтому 2,473 становится 3 + 70 + 400 + 2,000, а затем находит соответствующую римскую цифру, используя хэш-таблицу romanNumerals, и добавляет ее к результирующей строке. Это делается путем добавления дополнительного 0 к каждому целому числу перед поиском при перемещении справа налево. Это решение работает только для чисел от 1 до 3 999.

    function integerToRoman(int) {
    if (int < 1 || int > 3999) {
        return -1;
    }

    var result = '';
    var intStr = int.toString();
    var romanNumerals = { 1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V', 6: 'VI', 7: 'VII', 8: 'VIII', 9: 'IX', 10: 'X', 20: 'XX', 30: 'XXX', 40: 'XL', 50: 'L', 60: 'LX', 70: 'LXX', 80: 'LXXX', 90: 'XC', 100: 'C', 200: 'CC', 300: 'CCC', 400: 'CD', 500: 'D', 600: 'DC', 700: 'DCC', 800: 'DCCC', 900: 'CM', 1000: 'M', 2000: 'MM', 3000: 'MMM'};
    var digit = '';

    for (var i = intStr.length - 1; i >= 0; i-- ) {
        if (intStr[i] === '0') {
            digit += '0';
            continue;
        }
        var num = intStr[i] + digit;
        result = romanNumerals[num] + result;
        digit += '0';
    }

    return result;
}
0 голосов
/ 15 апреля 2015
var romanNumerals = [
  ['M', 1000],['CM', 900],['D', 500],['CD', 400],['C', 100],['XC', 90],['L', 50],['XL', 40],['X', 10],['IX', 9],['V', 5],['IV', 4],['I', 1]];

RomanNumerals = {
  romerate: function(foo) {
    var bar = '';
    romanNumerals.forEach(function(buzz) {
      while (foo >= buzz[1]) {
        bar += buzz[0];
        foo -= buzz[1]; 
      }
    });
    return bar;
  },
  numerate: function(x) {
    var y = 0;
    romanNumerals.forEach(function(z) {
      while (x.substr(0, z[0].length) == z[0]) {
        x = x.substr(z[0].length);
        y += z[1];
      }
    });
    return y;
  }
};
0 голосов
/ 11 июля 2017

const romanize = num => {
  const romans = {
    M:1000,
    CM:900,
    D:500,
    CD:400,
    C:100,
    XC:90,
    L:50,
    XL:40,
    X:10,
    IX:9,
    V:5,
    IV:4,
    I:1
  };
  
  let roman = '';
  
  for (let key in romans) {
    const times = Math.trunc(num / romans[key]);
    roman += key.repeat(times);
    num -= romans[key] * times;
  }

  return roman;
}

console.log(
  romanize(38)
)
0 голосов
/ 04 июня 2019

Циклы могут быть более элегантными, но мне трудно их прочитать. Придумали более или менее жестко закодированную версию, которая проста для глаз. Пока вы понимаете самую первую строчку, остальное не составляет труда.

function romanNumeralGenerator (int) {
  let roman = '';

  roman +=  'M'.repeat(int / 1000);  int %= 1000; 
  roman += 'CM'.repeat(int / 900);   int %= 900; 
  roman +=  'D'.repeat(int / 500);   int %= 500;  
  roman += 'CD'.repeat(int / 400);   int %= 400;
  roman +=  'C'.repeat(int / 100);   int %= 100;
  roman += 'XC'.repeat(int / 90);    int %= 90;
  roman +=  'L'.repeat(int / 50);    int %= 50;
  roman += 'XL'.repeat(int / 40);    int %= 40;
  roman +=  'X'.repeat(int / 10);    int %= 10;
  roman += 'IX'.repeat(int / 9);     int %= 9;
  roman +=  'V'.repeat(int / 5);     int %= 5;
  roman += 'IV'.repeat(int / 4);     int %= 4;
  roman +=  'I'.repeat(int);

  return roman;
}
0 голосов
/ 26 июля 2016

Это мое решение, я не слишком уверен, насколько хорошо оно работает.

function convertToRoman(num) {

  var uni = ["","I","II","III","IV","V","VI","VII","VIII","IX"];
  var dec = ["","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"];
  var cen = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"];
  var mil = ["","M","MM","MMM","MMMM","MMMMM","MMMMMM","MMMMMMM","MMMMMMMM","MMMMMMMMMM"];

  var res =[];

  if(num/1000 > 0)
    {
      res = res.concat(mil[Math.floor(num/1000)]);
    }

  if(num/100 > 0)
    {
      res = res.concat(cen[Math.floor((num%1000)/100)]);
    }

  if(num/10 >0)
    {
      res = res.concat(dec[Math.floor(((num%1000)%100)/10)]);
    }

  res=res.concat(uni[Math.floor(((num%1000)%100)%10)]);

  return res.join('');
}
...