web-dev-qa-db-ja.com

javaScriptで数値をローマ数字に変換する

整数を ローマ数字 に変換するにはどうすればよいですか?

function romanNumeralGenerator (int) {

}

たとえば、次のサンプル入力および出力を参照してください。

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

警告:1〜3999の数字のみをサポート

50
DD77

このブログには、Googleを使用して見つけた素敵なものがあります。

http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

function romanize (num) {
    if (isNaN(num))
        return NaN;
    var digits = String(+num).split(""),
        key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM",
               "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC",
               "","I","II","III","IV","V","VI","VII","VIII","IX"],
        roman = "",
        i = 3;
    while (i--)
        roman = (key[+digits.pop() + (i * 10)] || "") + roman;
    return Array(+digits.join("") + 1).join("M") + roman;
}
81
Rene Pot
function romanize(num) {
  var lookup = {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},roman = '',i;
  for ( i in lookup ) {
    while ( num >= lookup[i] ) {
      roman += i;
      num -= lookup[i];
    }
  }
  return roman;
}

http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter にある2008コメントから再投稿

デモの表示

62
jaggedsoft

みんなのソリューションが非常に長く、複数のforループを使用している理由がわかりません。

function convertToRoman(num) {
  var roman = {
    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
  };
  var str = '';

  for (var i of Object.keys(roman)) {
    var q = Math.floor(num / roman[i]);
    num -= q * roman[i];
    str += i.repeat(q);
  }

  return str;
}
39
August

これらの関数は、正の整数を同等のローマ数字文字列に変換します。そしてその数にローマ数字。

ローマ数字の数:

Number.prototype.toRoman= function () {
    var num = Math.floor(this), 
        val, s= '', i= 0, 
        v = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1], 
        r = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']; 

    function toBigRoman(n) {
        var ret = '', n1 = '', rem = n;
        while (rem > 1000) {
            var prefix = '', suffix = '', n = rem, s = '' + rem, magnitude = 1;
            while (n > 1000) {
                n /= 1000;
                magnitude *= 1000;
                prefix += '(';
                suffix += ')';
            }
            n1 = Math.floor(n);
            rem = s - (n1 * magnitude);
            ret += prefix + n1.toRoman() + suffix;
        }
        return ret + rem.toRoman();
    }

    if (this - num || num < 1) num = 0;
    if (num > 3999) return toBigRoman(num);

    while (num) {
        val = v[i];
        while (num >= val) {
            num -= val;
            s += r[i];
        }
        ++i;
    }
    return s;
};

ローマ数字の文字列から数字へ:

Number.fromRoman = function (roman, accept) {
    var s = roman.toUpperCase().replace(/ +/g, ''), 
        L = s.length, sum = 0, i = 0, next, val, 
        R = { M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1 };

    function fromBigRoman(rn) {
        var n = 0, x, n1, S, rx =/(\(*)([MDCLXVI]+)/g;

        while ((S = rx.exec(rn)) != null) {
            x = S[1].length;
            n1 = Number.fromRoman(S[2])
            if (isNaN(n1)) return NaN;
            if (x) n1 *= Math.pow(1000, x);
            n += n1;
        }
        return n;
    }

    if (/^[MDCLXVI)(]+$/.test(s)) {
        if (s.indexOf('(') == 0) return fromBigRoman(s);

        while (i < L) {
            val = R[s.charAt(i++)];
            next = R[s.charAt(i)] || 0;
            if (next - val > 0) val *= -1;
            sum += val;
        }
        if (accept || sum.toRoman() === s) return sum;
    }
    return NaN;
};
13
kennebec

以下で再帰的なソリューションを開発しました。この関数は1つの文字を返し、それ自体を呼び出して次の文字を返します。関数に渡される数値が0になるまでそれを行います。つまり、すべての文字が見つかったため、再帰を終了できます。

var romanMatrix = [
  [1000, 'M'],
  [900, 'CM'],
  [500, 'D'],
  [400, 'CD'],
  [100, 'C'],
  [90, 'XC'],
  [50, 'L'],
  [40, 'XL'],
  [10, 'X'],
  [9, 'IX'],
  [5, 'V'],
  [4, 'IV'],
  [1, 'I']
];

function convertToRoman(num) {
  if (num === 0) {
    return '';
  }
  for (var i = 0; i < romanMatrix.length; i++) {
    if (num >= romanMatrix[i][0]) {
      return romanMatrix[i][1] + convertToRoman(num - romanMatrix[i][0]);
    }
  }
}
13
Piotr Berebecki

私はこれが古い質問であることを知っていますが、私はこのソリューションをかなり誇りに思っています:)それは1000未満の数字のみを処理しますが、「numeralCodes」2D配列に追加することで必要に応じて簡単に拡張できます。

var numeralCodes = [["","I","II","III","IV","V","VI","VII","VIII","IX"],         // Ones
                    ["","X","XX","XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"],   // Tens
                    ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"]];        // Hundreds

function convert(num) {
  var numeral = "";
  var digits = num.toString().split('').reverse();
  for (var i=0; i < digits.length; i++){
    numeral = numeralCodes[i][parseInt(digits[i])] + numeral;
  }
  return numeral;  
}
<input id="text-input" type="text">
<button id="convert-button" onClick="var n = parseInt(document.getElementById('text-input').value);document.getElementById('text-output').value = convert(n);">Convert!</button>
<input id="text-output" style="display:block" type="text">
8
Deftwun

JavaScript

function romanize (num) {
    if (!+num)
        return false;
    var digits = String(+num).split(""),
        key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM",
               "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC",
               "","I","II","III","IV","V","VI","VII","VIII","IX"],
        roman = "",
        i = 3;
    while (i--)
        roman = (key[+digits.pop() + (i * 10)] || "") + roman;
    return Array(+digits.join("") + 1).join("M") + roman;
}

他の多くの提案は http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter で見つけることができます

5
Senad Meškin

個人的には、最も近い方法(決して最速ではない)が再帰であると思います。

function convert(num) { 
  if(num < 1){ return "";}
  if(num >= 40){ return "XL" + convert(num - 40);}
  if(num >= 10){ return "X" + convert(num - 10);}
  if(num >= 9){ return "IX" + convert(num - 9);}
  if(num >= 5){ return "V" + convert(num - 5);}
  if(num >= 4){ return "IV" + convert(num - 4);}
  if(num >= 1){ return "I" + convert(num - 1);}  
}
console.log(convert(39)); 
//Output: XXXIX

これは数字のみをサポートします1-4ですが、パターンに従うことで簡単に拡張できます。

4
benscabbia

この関数は、3,999,999より小さい数値をローマ字に変換します。 3999より大きい番号は、text-decorationoverlineに設定されたラベル内にあることに注意してください。これにより、番号が3999より大きい場合にx1000の正しい表現であるoverlineが追加されます。

400万(4,000,000)は2つのoverlinesを持つIVであるため、それを表すために何らかのトリックを使用する必要があります。おそらくDIV with border-top、またはこれらの2つのoverlines ...各overlineはx1000を表します。

function convert(num){
    num = parseInt(num);

    if (num > 3999999) { alert('Number is too big!'); return false; }
    if (num < 1) { alert('Number is too small!'); return false; }

    var result = '',
        ref = ['M','CM','D','CD','C','XC','L','XL','X','IX','V','IV','I'],
        xis = [1000,900,500,400,100,90,50,40,10,9,5,4,1];

    if (num <= 3999999 && num >= 4000) {
        num += ''; // need to convert to string for .substring()
        result = '<label style="text-decoration: overline;">'+convert(num.substring(0,num.length-3))+'</label>';
        num = num.substring(num.length-3);
    }

    for (x = 0; x < ref.length; x++){
        while(num >= xis[x]){
            result += ref[x];
            num -= xis[x];
        }
    }
    return result;
}
3
function convertToRoman(num) {
  var roman = {
    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
  }
  var result = '';
  for (var key in roman) {
    if (num == roman[key]) {
      return result +=key;
    }
    var check = num > roman[key];
    if(check) {
      result = result + key.repeat(parseInt(num/roman[key]));
      num = num%roman[key];
    }
  }
 return result;
}

console.log(convertToRoman(36));
3
Garvit Khamesra

この投稿の実装のいくつかをテストした後、より高速に実行するために、最適化された新しい実装を作成しました。実行時間は他と比較して非常に短いですが、明らかにコードはいです:)。すべての可能性を持つインデックス配列を使用すると、さらに高速になる可能性があります。誰かを助けるために。

function concatNumLetters(letter, num) {
    var text = "";
    for(var i=0; i<num; i++){
        text += letter;
    }
    return text;
}


function arabicToRomanNumber(arabic) {
    arabic = parseInt(arabic);
    var roman = "";
    if (arabic >= 1000) {
        var thousands = ~~(arabic / 1000);
        roman = concatNumLetters("M", thousands);
        arabic -= thousands * 1000;
    }

     if (arabic >= 900) {
         roman += "CM";
         arabic -= 900;
     }

     if (arabic >= 500) {
         roman += "D";
         arabic -= 500;
     }

     if (arabic >= 400) {
         roman += "CD";
         arabic -= 400;
     }

     if (arabic >= 100) { 
        var hundreds = ~~(arabic / 100);
        roman += concatNumLetters("C", hundreds);
        arabic -= hundreds * 100;
     }

     if (arabic >= 90) {
         roman += "XC";
         arabic -= 90;
     }

     if (arabic >= 50) {
         roman += "L";
         arabic -= 50;
     }

     if (arabic >= 40) {
         roman += "XL";
         arabic -= 40;
     }

     if (arabic >= 10) {
        var dozens = ~~(arabic / 10);
        roman += concatNumLetters("X", dozens);
        arabic -= dozens * 10;
     }

     if (arabic >= 9) {
         roman += "IX";
         arabic -= 9;
     }

      if (arabic >= 5) {
         roman += "V";
         arabic -= 5;
     }

     if (arabic >= 4) {
         roman += "IV";
         arabic -= 4;
     }

     if (arabic >= 1) {
        roman += concatNumLetters("I", arabic);
     }

     return roman;
}
3
David Vicente

HTMLElement(スパンなど)のこの番号の場合、HTML属性を追加することをお勧めしますdata-format

<p>Phase <span data-format="roman">4 </span> Sales</p>

注:これはhtml標準ではありません。使用したJavascriptコードは、jsfiddleのhtmlセクションを下にスクロールすると表示されます。

[〜#〜] demo [〜#〜]

2
Abdennour TOUMI

アラビア数字とローマ字の2つの双子配列を作成しました。

function convert(num) {

  var result = '';
  var rom = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
  var ara = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];

次に、ローマの要素をスキャンするサイクルを追加し、NUMに含まれる最大の静止画をRESULTに追加してから、同じ量のNUMを減らします。

NUMの一部をローマ数字でマッピングしてから、同じ量だけ減らします。

  for (var x = 0; x < rom.length; x++) {
    while (num >= ara[x]) {
      result += rom[x];
      num -= ara[x];
    }
  }
  return result;
}
2

より多くのシンボルで大きな数値を変換したい場合、このアルゴリズムが役立つかもしれません。

シンボルの唯一の前提は、奇数で、同じルール(1、5、10、50、100 ....、10 ^(N)/ 2、10 ^(N))に従う必要があるということです。

var rnumbers = ["I","V","X","L","C","D","M"];
        rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return '<span style="border-top:1px solid black; padding:1px;">'+n+'</span> '}));
        rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return '<span style="border:1px solid black; border-bottom:1px none black; padding:1px;">'+n+'</span> '}));
        rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return '<span style="border-top:3px double black; padding:1px;">'+n+'</span> '}));


    String.prototype.repeat = function( num ) {
        return new Array( num + 1 ).join( this );
    };

    function toRoman(n) {

        if(!n) return "";

        var strn = new String(n);
        var strnlength = strn.length;
        var ret = "";
        for(var i = 0 ; i < strnlength; i++) {
            var index = strnlength*2 -2 - i*2;
            var str;
            var m = +strn[i];
            if(index > rnumbers.length -1) {
                str = rnumbers[rnumbers.length-1].repeat(m*Math.pow(10,Math.ceil((index-rnumbers.length)/2)));
            }else {
                str = rnumbers[index].repeat(m);
                if (rnumbers.length >= index + 2) {
                    var rnregexp = rnumbers[index]
                            .split("(").join('\\(')
                            .split(")").join('\\)');
                    
                    str = str.replace(new RegExp('(' + rnregexp + '){9}'), rnumbers[index] + rnumbers[index + 2])
                            .replace(new RegExp('(' + rnregexp + '){5}'), rnumbers[index + 1])
                            .replace(new RegExp('(' + rnregexp + '){4}'), rnumbers[index] + rnumbers[index + 1])
                }
            }
            ret +=str;
        }

        return ret;
    }
    
<input type="text" value="" onkeyup="document.getElementById('result').innerHTML = toRoman(this.value)"/>

<br/><br/>

<div id="result"></div>
2
Luca Rainone

私はこれが時代遅れの質問であることを知っていますが、ここにリストされているものの中で最も短い解決策があり、理解しやすいと思うので共有したいと思いました。

このバージョンでは、他のように4(IV)、9(IX)、40(XL)、900(CM)などのEdgeケースにハードコードされたロジックは必要ありません。これは、ローマ字の最大スケール(3999)よりも大きい数値を処理できることも意味します。たとえば、「T」が新しいシンボルになった場合、それをromanLookupオブジェクトの先頭に追加すると、同じアルゴリズム効果が維持されます。または、「同じシンボルが3行以内」というルールが適用されることを前提としています。

1-3999のデータセットに対してこれをテストしましたが、問題なく動作します。

function convertToRoman(num) {
  //create key:value pairs
  var romanLookup = {M:1000, D:500, C:100, L:50, X:10, V:5, I:1};
  var roman = [];
  var romanKeys = Object.keys(romanLookup);
  var curValue;
  var index;
  var count = 1;

  for(var numeral in romanLookup){
    curValue = romanLookup[numeral];
    index = romanKeys.indexOf(numeral);

    while(num >= curValue){

      if(count < 4){
        //Push up to 3 of the same numeral
        roman.Push(numeral);
      } else {
        //else we had to Push four, so we need to convert the numerals 
        //to the next highest denomination "coloring-up in poker speak"

        //Note: We need to check previous index because it might be part of the current number.
        //Example:(9) would attempt (VIIII) so we would need to remove the V as well as the I's
        //otherwise removing just the last three III would be incorrect, because the swap 
        //would give us (VIX) instead of the correct answer (IX)
        if(roman.indexOf(romanKeys[index - 1]) > -1){
          //remove the previous numeral we worked with 
          //and everything after it since we will replace them
          roman.splice(roman.indexOf(romanKeys[index - 1]));
          //Push the current numeral and the one that appeared two iterations ago; 
          //think (IX) where we skip (V)
          roman.Push(romanKeys[index], romanKeys[index - 2]);
        } else {
          //else Example:(4) would attemt (IIII) so remove three I's and replace with a V 
          //to get the correct answer of (IV)

          //remove the last 3 numerals which are all the same
          roman.splice(-3);
          //Push the current numeral and the one that appeared right before it; think (IV)
          roman.Push(romanKeys[index], romanKeys[index - 1]);
        }
      }
      //reduce our number by the value we already converted to a numeral
      num -= curValue;
      count++;
    }
    count = 1;
  }
  return roman.join("");
}

convertToRoman(36);
2
Shawn
function convertToRoman(num) {

  var romans = {
    1000: 'M',
    900: 'CM',
    500: 'D',
    400: 'CD',
    100: 'C',
    90: 'XC',
    50: 'L',
    40: 'XL',
    10: 'X',
    9: 'IX',
    5: 'V',
    4: 'IV',
    1: 'I'
  };
  var popped, rem, roman = '',
    keys = Object.keys(romans);
  while (num > 0) {
    popped = keys.pop();
    m = Math.floor(num / popped);
    num = num % popped;
    console.log('popped:', popped, ' m:', m, ' num:', num, ' roman:', roman);
    while (m-- > 0) {
      roman += romans[popped];
    }
    while (num / popped === 0) {
      popped = keys.pop();
      delete romans[popped];
    }
  }
  return roman;
}
var result = convertToRoman(3999);
console.log(result);
document.getElementById('roman').innerHTML = 'Roman: ' + result;
p {
  color: darkblue;
}
<p>Decimal: 3999</p>
<p id="roman">Roman:</p>
2
Srichakradhar

Freecodecampで作成しました。簡単に拡張できます。

function convertToRoman(num) {

  var roman ="";

  var values = [1000,900,500,400,100,90,50,40,10,9,5,4,1];
  var literals = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"];


  for(i=0;i<values.length;i++){
    if(num>=values[i]){
      if(5<=num && num<=8) num -= 5;
      else if(1<=num && num<=3) num -= 1;
      else num -= values[i];
      roman += literals[i];
      i--;
    }
  }


 return roman;
}
2
Daniel Arroyo

正規表現ソリューションは次のとおりです。

function deromanize(roman) {
  var r = 0;
  // regular expressions to check if valid Roman Number.
  if (!/^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/.test(roman))
    throw new Error('Invalid Roman Numeral.');

  roman.replace(/[MDLV]|C[MD]?|X[CL]?|I[XV]?/g, function(i) {
    r += {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}[i]; 
  });

  return r;
}
2
Gregory R.
function convertToRoman (num) {
    var v = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
    var r = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
    var s = "";
    for(i = 0; i < v.length; i++) {
        value = parseInt(num/v[i]);
        for(j = 0; j < value; j++) {
            s += r[i];
        }
        num = num%v[i];
    }
    return s;
}
1
Heting Wu

この関数は、各桁の異なる文字セットに対して機能します。別の数字を追加するには、1桁、5桁、次の1桁にローマ数字文字列を追加します。使用する次の文字セットのみを知って更新するため、これは素晴らしいことです。

function toRoman(n){
  var d=0,o="",v,k="IVXLCDM".split("");
                    
  while(n!=0){
    v=n%10,x=k[d],y=k[d+1],z=k[d+2];
    o=["",x,x+x,x+x+x,x+y,y,y+x,y+x+x,y+x+x+x,x+z][v]+o;
    n=(n-v)/10,d+=2;
  }
  
  return o
}

var out = "";

for (var i = 0; i < 100; i++) {
  out += toRoman(i) + "\n";
}

document.getElementById("output").innerHTML = out;
<pre id="output"></pre>
1
wolfhammer

まだそれを誇りに思っています:)それは1から3999の間で動作します。

var converterArray = [{"1":["I","IV","V","IX"],
                       "2":["X","XL","L","XC"],
                       "3":["C","CD","D","CM"],
                       "4":["M"]}
                     ];

function convertToRoman(num) {
  var romanNumeral = [];
  var numArr = num.toString().split('');
  var numLength = numArr.length;

  for (var i = 0; i<numArr.length; i++) {
    if (numArr[i] < 4) {
      for (var j = 0; j<numArr[i]; j++) {
        romanNumeral.Push(converterArray[0][numLength][0]);
      }
    } else if (numArr[i] < 5) {
       for (var j = 3; j<numArr[i]; j++) {
        romanNumeral.Push(converterArray[0][numLength][1]);
      }
    } else if (numArr[i] < 9) {
        romanNumeral.Push(converterArray[0][numLength][2]);
        for (var j = 5; j<numArr[i]; j++) {
          romanNumeral.Push(converterArray[0][numLength][0]);
      }
    } else if (numArr[i] < 10) {
        for (var j = 8; j<numArr[i]; j++) {
          romanNumeral.Push(converterArray[0][numLength][3]);
      }
    }
    numLength--;
   }

 return romanNumeral.join('');
}

convertToRoman(9);
1
Zsiga

Freecodecampに夢中になったのは初めてです。私はここでいくつかの解決策を熟読し、それらがどれほど異なっているかに驚いた。これが私のために働いたものです。

function convertToRoman(num) {
var roman = "";

var lookupObj = {
   1000:"M",
   900:"CM",
   500:"D",
   400:"CD",
   100:"C",
   90:"XC",
   50:"L",
   40:"XL",
   10:"X",
   9:"IX",   
   4:"IV",
   5:"V",
   1:"I",
};

var arrayLen = Object.keys(lookupObj).length;

while(num>0){

 for (i=arrayLen-1 ; i>=0 ; i--){

  if(num >= Object.keys(lookupObj)[i]){

    roman = roman + lookupObj[Object.keys(lookupObj)[i]];        
    num = num - Object.keys(lookupObj)[i];
    break;

  }
 }
}    

return roman;

}

convertToRoman(1231);
1
whoisdarien

私のソリューションはより読みやすく、理解しやすいと感じています。

var intToRoman = function(num) {
    let symbolMap = ['I','V','X','L','C','D','M','P','Q'];

    if (num < 1 || num > 9999) {
        return null;
    }

    let i = 0;
    let result = '';

    while (num) {
        let digit = num % 10;
        num = parseInt(num / 10);

        switch (digit) {
            case 1: result = symbolMap[i] + result;
                break;
            case 2: result = symbolMap[i] + symbolMap[i] + result;
                break;
            case 3: result = symbolMap[i] + symbolMap[i] + symbolMap[i] + result;
                break;
            case 4: result = symbolMap[i] + symbolMap[i+1] + result;
                break;
            case 5: result = symbolMap[i+1] + result;
                break;
            case 6: result = symbolMap[i+1] + symbolMap[i] + result;
                break;
            case 7: result = symbolMap[i+1] + symbolMap[i] + symbolMap[i] + result;
                break;
            case 8: result = symbolMap[i+1] + symbolMap[i] + symbolMap[i] + symbolMap[i] + result;
                break;
            case 9: result = symbolMap[i] + symbolMap[i+2] + result;
                break;
        }
        i += 2;
    }

    return result;
 };

私の解決策は、数字を文字列の配列に分割し、配列の長さに対する相対的な位置に基づいて各要素にゼロを追加し、ゼロを持つ新しい文字列をローマ数字に変換し、それらを再び結合します。これは、最大3999の数字でのみ機能します。

function convertToRoman(num){
  var rnumerals = { 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 zeros, romNum;
  var arr = num.toString().split("");
  var romArr = [];
  for(var i=0; i < arr.length; i++){
    zeros = "0".repeat((arr.length - i - 1));
    arr[i] = arr[i].concat(zeros);
    romArr.Push(rnumerals[(arr[i])]); 
  }
  romNum = romArr.join('');
  return romNum;
}
1
InfiniteSet
function toRoman(n) {
    var decimals = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
    var roman = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];

    for (var i = 0; i < decimals.length; i++) {
        if(n < 1)
            return "";       

        if(n >= decimals[i]) {
            return roman[i] + toRoman(n - decimals[i]);        
        }
    }
}
1
stenou

これは、ローマ数字M以下を必要とするすべての数字で機能します。

function convert(num) {
  var code = [
    [1000, "M"], [900, "CM"], [800, "DCCC"], [700, "DCC"], [600, "DC"],
    [500, "D"], [400, "CD"], [300, "CCC"], [200, "CC"], 
    [100, "C"], [90, "XC"], [80, "LXXX"], [70, "LXX"], [60, "LX"], 
    [50, "L"], [40, "XL"], [30, "XXX"], [20, "XX"], 
    [10, "X"], [9, "IX"], [8, "VIII"], [7, "VII"], [6, "VI"], 
    [5, "V"], [4, "IV"], [3, "III"], [2, "II"], [1, "I"],
  ];

  var rom = "";
  for(var i=0; i<code.length; i++) {
    while(num >= code[i][0]) {
      rom += code[i][1];
      num -= code[i][0];
    }
  }
  return rom;
}
1
braham530
/*my beginner-nooby solution for numbers 1-999 :)*/
function convert(num) {
    var RomNumDig = [['','I','II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],['X','XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'], ['C','CC','CCC','CD','D','DC','DCC','DCCC','CM']];
    var lastDig = num%10;
    var ourNumb1 = RomNumDig[0][lastDig]||'';
    if(num>=10) {
        var decNum = (num - lastDig)/10;
        if(decNum>9)decNum%=10; 
    var ourNumb2 = RomNumDig[1][decNum-1]||'';} 
    if(num>=100) {
        var hundNum = ((num-num%100)/100);
        var ourNumb3 = RomNumDig[2][hundNum-1]||'';}
return ourNumb3+ourNumb2+ourNumb1;
}
console.log(convert(950));//CML

/*2nd my beginner-nooby solution for numbers 1-10, but it can be easy transformed for larger numbers :)*/
function convert(num) {
  var ourNumb = '';
  var romNumDig = ['I','IV','V','IX','X'];
  var decNum = [1,4,5,9,10];
  for (var i=decNum.length-1; i>0; i--) {
    while(num>=decNum[i]) {
        ourNumb += romNumDig[i];
        num -= decNum[i];
    }
  }
  return ourNumb;
}
console.log(convert(9));//IX
1
Vasyl Gutnyk

表示のみを目的とする場合は、値(必要な場合)とCSSに少しのJSを使用した標準HTMLを使用して、インラインにします。

ol.roman-lowercase,
ol.roman-uppercase {
  display: inline-flex;
  margin: 0;
  padding: 0;
}

ol.roman-lowercase {
  list-style: lower-roman inside;
}

ol.roman-uppercase {
  list-style: upper-roman inside;
}
<ol class="roman-lowercase"><li value="4"></li></ol> <!-- iv. -->
<ol class="roman-uppercase"><li value="142"></li></ol> <!-- CXLII. -->
1
Tibo
function convertToRoman(num) {
    var arr = [];
    for (var i = 0; i < num.toString().length; i++) {
        arr.Push(Number(num.toString().substr(i, 1)));
    }
    var romanArr = [
        ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"],
        ["X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"],
        ["C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"],
        ["M"]
    ];
    var roman = arr.reverse().map(function (val, i) {
        if (val === 0) {
            return "";
        }
        if (i === 3) {
            var r = "";
            for (var j = 0; j < val; j++) {
                r += romanArr[i][0];
            }
            return r;
        } else {
            return romanArr[i][val - 1];
        }
    });
    console.log(roman.reverse().join(""));
    return roman.join("");
}


convertToRoman(10);
1
Mifind
function convertToRoman(num) {
  var romNumerals = [["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]];
  var runningTotal = 0;
  var roman = "";
  for (var i = 0; i < romNumerals.length; i++) {
    while (runningTotal + romNumerals[i][1] <= num) {
      runningTotal += romNumerals[i][1];
      roman += romNumerals[i][0];
    }
  }

 return roman;
}
1
Yup.
function convertToRoman(num) {

var roNumerals = {
    M: Math.floor(num / 1000),
    CM: Math.floor(num % 1000 / 900),
    D: Math.floor(num % 1000 % 900 / 500),
    CD: Math.floor(num % 1000 % 900 % 500 / 400),
    C: Math.floor(num % 1000 % 900 % 500 % 400 / 100),
    XC: Math.floor(num % 1000 % 900 % 500 % 400 % 100 / 90),
    L: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 / 50),
    XL: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 / 40),
    X: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 / 10),
    IX: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 / 9),
    V: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 % 9 / 5),
    IV: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 % 9 % 5 / 4),
    I: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 % 9 % 5 % 4 / 1)
  };
  var roNuStr = "";

  for (var prop in roNumerals) {
    for (i = 0; i < roNumerals[prop]; i++) {
      roNuStr += prop;
    }

  }
  return roNuStr;
}

convertToRoman(9);
1
Sony ThePony

これが私のコードです、これが役立つことを願っています:

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
yz_n

ローマに変換するために作成した関数を投稿しています。

function converter(numToConv) {
var numToRom = [];
var numToRome = "";
var R = [['M',1000], ['D',500], ['C',100], ['L',50], ['X',10], ['V',5], ['I',1]];
while (numToConv > 0) {
    if (numToConv > R[0][1]) {
        if (numToConv < R[0][1] * 5 - R[0][1]) {   
            numToRom.Push([R[0][0],"next one goes aftah"]);
            numToConv = Math.abs(numToConv - R[0][1]);
            console.log("Next comes after: " + R[0][0] + " (" + R[0][1] + ")");
            console.log(numToConv);
        } else {
            numToConv = 0;
            break;
        }
    }
    for (var i = 0; i < R.length; i++) {
        if (R[i][1] == numToConv) {
            numToRom.Push([R[i][0],"end"]);
            numToConv = Math.abs(numToConv - R[i][1]);
            console.log("End: " + numToConv);
        } else if (i > 0) {
            if ((R[i-1][1] > numToConv) && (R[i][1] < numToConv)) {
                console.log(numToConv + " is between: " + R[i][1]  + " (" + R[i][0] + ") and: " +  R[i - 1][1]  + " (" + R[i - 1][0] + ")");
                var threshold = R[i - 1][1] - Math.pow(10, numToConv.toString().length - 1);
                console.log("threshold: " + threshold + " : " + R[i][1] + " : " + Math.pow(10, numToConv.toString().length - 1));
                if (numToConv  < threshold) {
                    numToRom.Push([R[i][0],"next one goes aftah"]);
                    numToConv = Math.abs(numToConv - R[i][1]);
                    console.log("Next comes after: " + R[i][0] + " (" + R[i][1] + ")");
                    console.log(numToConv);
                } else {
                    numToRom.Push([R[i-1][0],"next one goes befoah"]);
                    numToConv = Math.abs(numToConv - threshold + Math.pow(10, numToConv.toString().length - 1));
                    console.log("Next comes before: " + R[i-1][0] + " (" + R[i-1][1] + ")");
                    console.log(numToConv);
                }
            }
        }
    }
}
console.log("numToRom: " + numToRom);
for (var i = 0; i < numToRom.length; i++) {
    if (numToRom[i][1] == "next one goes befoah") {
        numToRome += (numToRom[i+1][0] + numToRom[i][0]);
        console.log("numToRome goes befoah: " + numToRome + " i: " + i);
        i++;
    } else {
        numToRome += numToRom[i][0];
        console.log("numToRome goes aftah: " + numToRome + " i: " + i);
    }
}
        console.log("numToRome: " + numToRome);
        return numToRome;

}

コメント付きの編集済みコード:

function converter(numToConv) {
    var numToRom = []; //an array empty, ready to store information about the numbers we will use as we analyse the given number 
    var numToRome = ""; // this is a string to add the Roman letters forming our returning number
    var R = [['M',1000], ['D',500], ['C',100], ['L',50], ['X',10], ['V',5], ['I',1]]; //this array stores the matches with the arabic numbers that we are going to need
    while (numToConv > 0) { //just checking, there is no zero
        if (numToConv > R[0][1]) { //checks if the number is bigger than the bigger number in the array
            if (numToConv < R[0][1] * 5 - R[0][1]) { //checks if it is larger even than 4 times the larger number in the array (just because there is not usually a way to express a number by putting 4 times the same letter i.e there is no "IIII", or "XXXX" etc)
                numToRom.Push([R[0][0],"next one goes aftah"]);//here is the information we want to pass, we add the letter we are about to use along with info about the next letter
                numToConv = Math.abs(numToConv - R[0][1]);// and now we are subtracting the value of the letter we are using from the number
                console.log("Next comes after: " + R[0][0] + " (" + R[0][1] + ")");// informing about what we encountering
                console.log(numToConv);//..as well as what's the next number
            } else { //if the number is larger than 4 times the larger number in the array (thus it cannot be expressed)
                numToConv = 0; //then 0 the number (unnecessary but still, no problem doing it)
                break;//and of course, breaking the loop, no need to continue
            }
        }
        for (var i = 0; i < R.length; i++) {//now we are about to search our number for each cell of the array with the roman letters (again and again)
            if (R[i][1] == numToConv) { //if the number is equal to the one in the cell (that means the conversion is over)
                numToRom.Push([R[i][0],"end"]); //we pass the information about that cell along with the indication that the conversion has ended
                numToConv = Math.abs(numToConv - R[i][1]);//thai can also be skipped but again there is o harm in keeping it
                console.log("End: " + numToConv);// again informing about what we encountering
            } else if (i > 0) { //just a precaution because we are about to use "i-1" 
                if ((R[i-1][1] > numToConv) && (R[i][1] < numToConv)) {//we find the range in which is the given number (for instance: the number 4 is between 1[I] and 5[V])
                    console.log(numToConv + " is between: " + R[i][1]  + " (" + R[i][0] + ") and: " +  R[i - 1][1]  + " (" + R[i - 1][0] + ")");// once again informing
                    var threshold = R[i - 1][1] - Math.pow(10, numToConv.toString().length - 1);// we create this "threshold" to check if the next number is going before or after this one (difference between 7[VII] and 9[IX]). it is the larger number of our range - 10^[depends on how large is the number we want to convert] (for 999, the threshold is 900, it is smaller 1000 - 10^2)
                    console.log("threshold: " + threshold + " : " + numToConv + " : " + R[i - 1][1] + " : " + R[i][1] + " : " + Math.pow(10, numToConv.toString().length - 1));
                    if (numToConv  < threshold) {//if the number is smaller than the "threshold" (like 199 where its threshold is 400)
                        numToRom.Push([R[i][0],"next one goes aftah"]);//then the next number is going after
                        numToConv = Math.abs(numToConv - R[i][1]);//and again, subtract the used value of the number we are converting
                        console.log("Next comes after: " + R[i][0] + " (" + R[i][1] + ")");
                        console.log(numToConv);
                    } else { // now, if the number is larger than the threshold (like 99 where its threshold is 90)
                        numToRom.Push([R[i-1][0],"next one goes befoah"]);// then the next number is going before the one we add now
                        numToConv = Math.abs(numToConv - R[i - 1][1]);// again, the subtraction, it was "threshold + Math.pow(10, numToConv.toString().length - 1)" but I changed it to "R[i - 1][1]", same result, less operations
                        console.log("Next comes before: " + R[i-1][0] + " (" + R[i-1][1] + ")");
                        console.log(numToConv);
                    }
                }
            }
        }
    }
    console.log("numToRom: " + numToRom); //now that we have all the info we need about the number, show it to the log (just for a check)
    for (var i = 0; i < numToRom.length; i++) {//..and we start running through that info to create our final number
        if (numToRom[i][1] == "next one goes befoah") {//if our information about the cell tells us that the next letter is going before the current one
            numToRome += (numToRom[i+1][0] + numToRom[i][0]);// we add both to our string (the next one first)
            console.log("numToRome goes befoah: " + numToRome + " i: " + i);
            i++;//and we add an extra '1' to the i, so it will skip the next letter (mind that there won't be more than one letters saying that the next one is going before them in a row
        } else {//if the next one is going after the current one
            numToRome += numToRom[i][0]; //we just add the one we are on to the string and go forth
            console.log("numToRome goes aftah: " + numToRome + " i: " + i);
        }
    }
            console.log("numToRome: " + numToRome);
            return numToRome;//return the string and we are done
}

このソリューションはループを1つだけ実行し、数字をローマ字にマッピングするための最小オブジェクトを持っています

function RomantoNumeral(r){
  let result = 0,
      keys = {M:1000, D:500, C:100, L:50, C:100, L:50, X:10, V:5, I:1},
      order = Object.keys(keys),
      rom = Array.from(r) 

  rom.forEach((e, i)=>{
    if( i  < rom.length -1 && order.indexOf(e) > order.indexOf(rom[i+1])){
      result -= keys[e]
    } else {
      result +=keys[e]
    }
  })  
  return result
}

RomantoNumeral('MMDCCCXXXVII') #2837
0
s1mpl3
function convertToRoman(num) {

  var search = {
    "0":["I","II","III","IV","V","VI","VII","VIII","IX"],
    "1":["X","XX","XXX","XL","L","LX","LXX","LXXX","XC"],
    "2":["C","CC","CCC","CD","D","DC","DCC","DCCC","CM"],
    "3":["M","MM","MMM","MV^","V^","V^M","V^MM","V^MMM","MX^"],
  };

  var numArr = num.toString().split("").reverse();
  var romanReturn = [];
  for(var i=0; i<numArr.length; i++){
    romanReturn.unshift(search[i][numArr[i]-1]);
  }
  return romanReturn.join("");
}
0
llu

これが私の「機能するように機能する」ソリューションです。

var numerals = ["I","V","X","L","C","D","M"],
      number = 1453,
      digits = Array(~~(Math.log10(number)+1)).fill(number).map((n,i) => Math.trunc(n%Math.pow(10,i+1)/Math.pow(10,i))),  // <- [3,5,4,1]
      result = digits.reduce((p,c,i) => (c === 0 ? ""
                                                 : c < 4 ? numerals[2*i].repeat(c)
                                                         : c === 4 ? numerals[2*i] + numerals[2*i+1]
                                                                   : c < 9 ? numerals[2*i+1] + numerals[2*i].repeat(c-5)
                                                                           : numerals[2*i] + numerals[2*i+2]) + p,"");
console.log(result);
0
Redu
function convertToRoman(num) {
  var toTen = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"];
  var toHungred = ["", "X" ,"XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "C"];
  var toThousend = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "M"];                   
  var arrString = String(num).split("");  
  var arr = [];           
  if (arrString.length == 3 ){                                  
                arr.Push(toThousend[arrString[+0]]);
                arr.Push(toHungred[arrString[+1]]);
                arr.Push(toTen[arrString[+2]]);
   } 
  else if (arrString.length == 2 ){                             
          arr.Push(toHungred[arrString[+0]]);
          arr.Push(toTen[arrString[+1]]);                               
  }
  else if (arrString.length == 1 ){                             
        arr.Push(toTen[arrString[+0]]);                                         
  }
  else if (arrString.length == 4 ) {
    for (var i =1; i<=[arrString[+0]]; i++) {
                  arr.Push("M");                  
                }
    arr.Push(toThousend[arrString[+1]]);
        arr.Push(toHungred[arrString[+2]]);
        arr.Push(toTen[arrString[+3]]);
  }              
  console.log (arr.join(""));
}

convertToRoman(36);
0
Yenin Artem
function toRoman(n) {
        var r = '';
        for (var c = 0; c < n.length; c++)
            r += calcDigit(eval(n.charAt(c)), n.length - c - 1);
        return r
    }

function Level(i, v, x) {
    this.i = i;
    this.v = v;
    this.x = x
}

levels = [];
levels[0] = new Level('I','V','X');
levels[1] = new Level('X','L','C');
levels[2] = new Level('C','D','M');

function calcDigit(d, l) {
    if (l > 2) {
        var str = '';
        for (var m = 1; m <= d * Math.pow(10, l - 3); m++)
            str += 'M';
        return str
    } else if (d == 1)
        return levels[l].i;
    else if (d == 2)
        return levels[l].i + levels[l].i;
    else if (d == 3)
        return levels[l].i + levels[l].i + levels[l].i;
    else if (d == 4)
        return levels[l].i + levels[l].v;
    else if (d == 5)
        return levels[l].v;
    else if (d == 6)
        return levels[l].v + levels[l].i;
    else if (d == 7)
        return levels[l].v + levels[l].i + levels[l].i;
    else if (d == 8)
        return levels[l].v + levels[l].i + levels[l].i + levels[l].i;
    else if (d == 9)
        return levels[l].i + levels[l].x;
    else
        return ''
}
0
Jalaj Khajotia

これが私の解決策であり、どの程度うまく機能するかはわかりません。

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('');
}
0
Nicolas
function convertToRoman(int) {
    console.log('Number:', int);
    let roman = [];
    let i, k, replacement;
    let seq = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];

    while (int > 999) {
        roman.Push('M');
        int -= 1000;
    }
    while (int > 499) {
        roman.Push('D');
        int -= 500;
    }
    while (int > 99) {
        roman.Push('C');
        int -= 100;
    }
    while (int > 49) {
        roman.Push('L');
        int -= 50;
    }
    while (int > 9) {
        roman.Push('X');
        int -= 10;
    }
    while (int > 4) {
        roman.Push('V');
        int -= 5;
    }
    while (int >= 1) {
        roman.Push('I');
        int -= 1;
    }

    // Replace recurrences of 4 ('IIII' to 'IV')
    for (i = 0; i < roman.length; i++) {
        if (roman[i] == roman[i + 1] &&
            roman[i] == roman[i + 2] &&
            roman[i] == roman[i + 3]) {
            for (k = 0; k < seq.length; k++) {
                if (roman[i] == seq[k]) {
                    replacement = seq[k + 1];
                }
            }
            roman.splice(i + 1, 3, replacement);
        }
    }

    // Converting incorrect recurrences ('VIV' to 'IX')
    for (i = 0; i < roman.length; i++) {
        if (roman[i] == roman[i + 2] && roman[i] != roman[i + 1]) {
            for (k = 0; k < seq.length; k++) {
                if (roman[i] == seq[k]) {
                    replacement = seq[k + 1];
                }
            }
            roman[i + 2] = replacement;
            roman.splice(i, 1);
        }
    }

    roman = roman.join('');
    return roman;
}
0
Wes

アラビア数字の配列をローマ字のペアの配列にマッピングすることで、これを実行しようとしました。厄介な3レベルの3要素は、読みやすくするためにif(){} else {}ブロックで置き換えることができます。 1から3999まで機能しますが、拡張することができます。

function romanize(num) {
  if(num > 3999 || num < 1) return 'outside range!';
  const roman = [ ['M', ''], [ 'C', 'D' ], [ 'X', 'L' ], [ 'I', 'V' ] ];
  const arabic = num.toString().padStart(4, '0').split('');
  return arabic.map((e, i) => {
    return (
      e < 9 ? roman[i][1].repeat(Math.floor(e / 5)) : ''
    ) + (
      e % 5 < 4
        ? roman[i][0].repeat(Math.floor(e % 5))
        : e % 5 === 4 && Math.floor(e / 5) === 0
          ? roman[i][0] + roman[i][1]
          : Math.floor(e / 5) === 1
            ? roman[i][0] + roman[i - 1][0]
            : ''
    );
  }).join('');
}
0
chezearth

すべての可能性を配列(多くの人がこのパズルを解決するために選んだ)にリストするのは嫌いなので、別の関数を使用してその作業を行います。私の解決策は次のとおりです。

//a function that convert a single number to roman number, you can choose how to convert it so later you can apply to different part of the number
function romannum(num,rnum1,rnum2,rnum3){
  var result = "";
  if(num >= 1 && num < 4){
    while(num>0){
      result += rnum1;
      num--;
    }
  }
  else if(num > 5 && num < 9){
    result = rnum2;
    while(num>5){
      result += rnum1;
      num--;
    }  
  }
  else if(num == 4){
    result += rnum1 + rnum2;
  }
  else if( num == 5){
    result += rnum2;
  }
  else if( num == 9){
    result += rnum1+ rnum3;
  }
  return result;
}
//the main function
function convertToRoman(num) {
 num = num.toString().split('');
 var length = num.length;
 var x = 0;
 var result =[];

 while((length - x) > 0){
   if(length -x === 4){
    result.Push(romannum(num[x],"M","",""));
   }
   else if(length -x  === 3){
     result.Push(romannum(num[x],"C","D","M"));
   }
   else if(length - x  === 2){
     result.Push(romannum(num[x],"X","L","C"));
   }
   else if(length - x === 1){
     result.Push(romannum(num[x],"I","V","X"));
   }
   x++;  
 }
0
Khuong Pham

piotr Berebeckiの答えをつなぐだけです。再帰関数が指定された数値から1を減算するだけでなく、指定された配列の中で最も一致する数値をすぐに減算してプロセスを高速化するように編集しました。

// the arrays 
var arabicFormat = [1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000];
var romanFormat = ['I', 'IV', 'V', 'IX', 'X', 'XL', 'L', 'XC', 'C', 'CD', 'D', 'CM', 'M'];


function convertToRoman(num) {

 // the recursion will stop here returning a blank
 if (num === 0){
 return '';
 }

 var returnValue = [];

 // this is the main For loop of the function
 for (var i=0; i < arabicFormat.length; i++){

   if (num >= arabicFormat[i]){
    // empty the array on every iteration until it gets to the final number
     returnValue = [];
    // store the current highest matched number in the array
     returnValue.Push(romanFormat[i]);
    } 

 }

  // get the correct resulting format 
  returnValue = returnValue.join();

  // get the highest matched number value
  var whatIndex = romanFormat.indexOf(returnValue);
  var substractValue = arabicFormat[whatIndex];

  // here the recursion happens
  return returnValue + convertToRoman(num - substractValue);
}
0
David Vondrovic

私はjaggedsoftのソリューションが本当に好きでしたが、担当者が低すぎるため返信できませんでした:( :(

私はそれを解体して、理解できない人のために少し説明しました。うまくいけば誰かの助けになります。

function convertToRoman(num) {

  var lookup =   
{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},roman = '',i;

  for ( i in lookup ) {
    while ( num >= lookup[i] ) { //while input is BIGGGER than lookup #..1000, 900, 500, etc.
      roman += i; //roman is set to whatever i is (M, CM, D, CD...)
      num -= lookup[i]; //takes away the first num it hits that is less than the input
                    //in this case, it found X:10, added X to roman, then took away 10 from input
                    //input lowered to 26, X added to roman, repeats and chips away at input number
                    //repeats until num gets down to 0. This triggers 'while' loop to stop.    
    }
  }
  return roman;
}


console.log(convertToRoman(36));
0
Matt Outen

このコードでは、新しい文字をletterTableに追加することにより、数値の上限を拡張できます。

letterTable = {
  0:{
    1:'I',
    5:'V',
    10:'X'
  },
  1:{
    1:'X',
    5:'L',
    10:'C'
  },
  2:{
    1:'C',
    5:'D',
    10:'M'
  },
  3:{
    1:'M',
    5:'V', // There should be a dash over this letter
    10:'X' // There should be a dash over this letter
  }, 
  // you can add new level of letters here
};

function romanLetter(i, j){
  romanTable = {
    '0':'',
    '1':letterTable[i][1],
    '2':letterTable[i][1]+letterTable[i][1],
    '3':letterTable[i][1]+letterTable[i][1]+letterTable[i][1],
    '4':letterTable[i][1]+letterTable[i][5],
    '5':letterTable[i][5],
    '6':letterTable[i][5]+letterTable[i][1],
    '7':letterTable[i][5]+letterTable[i][1]+letterTable[i][1],
    '8':letterTable[i][5]+letterTable[i][1]+letterTable[i][1]+letterTable[i][1],
    '9':letterTable[i][1]+letterTable[i][10]
  };

  return romanTable[j];
}


function convertToRoman(num) {

  numStr = String(num);
  var result = '';
  var level = 0;

  for (var i=numStr.length-1; i>-1; i--){
    result = romanLetter(level, numStr[i]) + result;
    level++;
  }

  return result;
}
0
becinyus

これは単一のループを持つ私のソリューションです

function convertToRoman(num) {
  var roman = {
    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
  };

  var romanNum = "";

  for(key in roman){
      var check = num>=roman[key];
      if(check){
          console.log(romanNum);
          romanNum += key;
          num-= roman[key]; 
      }
  }
  return romanNum
}

convertToRoman(150);
0
am guru prasath

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
Jimmay

これは、すべての異なるローマ数字とそれに対応する数字をループすることなく行う方法です。一定の時間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
Amituuush

これを実現するにはいくつかの方法があります。個人的にはオブジェクトの使用を好み、キーと値のペアを反復処理します。

const solution=(n)=>{
   const romanLetters ={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 romanNumber ='';
   let valuesArr = Object.values(romanLetters);

   for(let i in valuesArr){
        while (n - valuesArr[i] >= 0){
            romanNumber+=Object.keys(romanLetters)[i]; 
            n-=valuesArr[i];
        }
   }
   return romanNumber;
}
0
Zeca Afonso

私の答えは他の人ほどパフォーマンスが良くありませんが、ベース番号のハードコーディングではなく、プログラムが残りを理解できるようにすることに重点を置いていました。
例えば...
の代わりに:
number = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
numeral = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']

私が使用した:

base = ['I', 'X', 'C', 'M'];pivot = ['V', 'L', 'D'];

function basicRomanNumerals(num){
let base = ['I', 'X', 'C', 'M'];
let pivot = ['V', 'L', 'D'];
return String(num).split('').reverse().map(function(num, idx){
    let distance = +num - 5;
    let is1AwayFromNext = Math.abs(+num - 10) === 1;
    if(Math.abs(distance)=== 1 || is1AwayFromNext){
        if(is1AwayFromNext){
            return base[idx]+""+base[idx+1];
        }else if ( distance < 0 ){
            return base[idx]+""+pivot[idx];
        }else{
            return pivot[idx]+""+base[idx];
        }
    }else if(distance === 0){
        return pivot[idx];
    }else if(distance > 1){
        return pivot[idx]+""+base[idx].repeat(+num-5);
    }else{
        return base[idx].repeat(+num);
    }
}).reverse().join('');
0
Daryl

私の解決策は次のとおりです。

function convertToRoman(num) { 
    let romanNum = "";
    const strNum = String(num);
    const romans = {
        1: ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"], // ones
        2: ["X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"], // tens
        3: ["C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"], // hundreds
        4: ["M", "MM", "MMM"] // thousands
    };

    for (let i = 1; i <= strNum.length; i++)
        if (Number(strNum[strNum.length - i]) !== 0)
            romanNum = romans[i][strNum[strNum.length - i] - 1] + romanNum;

    return romanNum;
}

Chrome 60- https://jsperf.com/num-to-roman

0
Snip3r

さて、FreeCodeCampでこの課題に巻き込まれたのは私だけではないようです。しかし、とにかくあなたと私のコードを共有したいと思います。これは非常にパフォーマンスが高く、ここでトップ投票されたソリューションよりもほぼ10%高速です(他のすべてをテストしたことはありませんが、私のものは最速ではないでしょう)。しかし、私はそれがきれいで理解しやすいと思います:

function convertToRoman(num) {
    // Some error checking first
    if (+num > 9999) {
        console.error('Error (fn convertToRoman(num)): Can\'t convert numbers greater than 9999. You provided: ' + num);
        return false;
    }
    if (!+num) {
        console.error('Error (fn convertToRoman(num)): \'num\' must be a number or number in a string. You provided: ' + num);
        return false;
    }

    // Convert the number into
    // an array of the numbers
    var arr = String(+num).split('').map((el) => +el );

    // Keys to the roman numbers
    var keys = {
        1: ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],
        2: ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'],
        3: ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'],
        4: ['', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM', 'MMMMMM', 'MMMMMMM', 'MMMMMMMM', 'MMMMMMMMM'],
    };

    // Variables to help building the roman string
    var i = arr.length;
    var roman = '';

    // Iterate over each number in the array and
    // build the string with the corresponding
    // roman numeral
    arr.forEach(function (el) {
        roman += keys[i][el];
        i--;
    });

    // Return the string
    return roman;
}

最大9 999までの数値しか変換できないという制限のように思えるかもしれません。しかし、実際には、10000以上の行をリテラルの上に提供する必要があります。そして、私はまだ解決していません。

これがお役に立てば幸いです。

0
Adam Bergman

ループはよりエレガントかもしれませんが、読みにくいと思います。多かれ少なかれハードコーディングされたバージョンが目に付きやすくなりました。最初の行を理解している限り、残りは簡単です。

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
Louie Bao

この質問が尋ねられて以来、「Number-To-Roman」の以前の46のソリューションすべてを見て、ケネベックによる逆ローマ対数の投稿は1つしかなく、いくつかの問題があります。「Number」オブジェクトは直接拡張できません、プロトタイプを使用する必要があります。また、このコンテキストではプロトタイピングは意味がありません(Stringオブジェクトがあれば、より良い候補です)。次に、不必要に複雑であり、さらにtoRomanメソッドを呼び出します。 3番目に、4000を超える数値では失敗します。以下は、両方のタイプの変換について、47の投稿すべての中で最も簡潔で簡潔なものです。これらの変換は、基本的に任意の数で機能します。 romanToNumberはgregoryrのエレガントなソリューションの小さなバリエーションです。

function numberToRoman(val,rom){ //returns empty string if invalid number
  rom=rom||''
  if(isNaN(val)||val==0) 
    return rom;
  for(i=0;curval=[1000,900,500,400,100,90,50,40,10,9,5,4,1][i],i<13;i++)
    if(val >= curval)
           return numberToRoman(val-curval,rom+['M','CM','D','CD','C','XC','L','XL','X','IX','V','IV','I'][i])
}

function romanToNumber(txtRom){//returns NaN if invalid string
  txtRom=txtRom.toUpperCase();
  if (!/^M*(CM|CD|(D?C{0,3}))?(XC|XL|(L?X{0,3}))?(IX|IV|(V?I{0,3}))?$/.test(txtRom))
    return NaN;
  var retval=0;
  txtRom.replace(/[MDLV]|C[MD]?|X[CL]?|I[XV]?/g, function(i) {
    retval += {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}[i]; 
  });
  return retval;
}
#tblRoman{border-collapse:collapse;font-family:sans-serif;font-size:.8em}
<h3>Roman to Number Conversion</h3>
<input type="button" value="example 1" onclick="document.getElementById('romanval').value='mmmmmmmcdlxxxiv'">
<input type="button" value="example 2" onclick="document.getElementById('romanval').value='mmmmmmmdclxxxiv'">
<input type="button" value="example 3" onclick="document.getElementById('romanval').value='mmmmmmmdxcdlxxxiv'">
<p>
Enter a Roman Number below, or click on an example button. Then click Convert 
</p>
<input type="text" size="40" id="romanval">
 <input type="button" onclick="document.getElementById('resultval').innerText
 = romanToNumber(document.getElementById('romanval').value)" value="Convert"> 
<p />
Numeric Value: <b id="resultval"></b>

<hr>
<h3>Number to Roman Conversion</h3>
<input type="button" value="Generate table upto 2000" onclick="document.getElementById('tblRoman').innerHTML ='</tr>'+[...Array(2000).keys()].map(x => '<td>'+(x+1)+': '+numberToRoman(x+1)+'</td>'+((x+1)%10==0?'</tr><tr>':'')).join('')+'</tr>'">

<table id="tblRoman" border></table>
0
Vijay Jagdale
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
julianusti

おそらく最も簡単なソリューション:

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's CodeSignalのソリューションです。

0
Brendon Shaw
const basicRomanNumeral = 
  ['',
    'I','II','III','IV','V','VI','VII','VIII','IX','',
    'X','XX','XXX','XL','L','LX','LXX','LXXX','XC','',
    'C','CC','CCC','CD','D','DC','DCC','DCCC','CM','',
    'M','MM','MMM'
  ];

function convertToRoman(num) {
  const numArray = num.toString().split('');
  const base = numArray.length;
  let count = base-1;
  const convertedRoman = numArray.reduce((roman, digit) => {
    const digitRoman = basicRomanNumeral[+digit + count*10];
    const result = roman + digitRoman;
    count -= 1;
    return result;
  },'');
  return convertedRoman;
}
0
Alrafik
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
Izaak