整数を ローマ数字 に変換するにはどうすればよいですか?
function romanNumeralGenerator (int) {
}
たとえば、次のサンプル入力および出力を参照してください。
1 = "I"
5 = "V"
10 = "X"
20 = "XX"
3999 = "MMMCMXCIX"
警告:1〜3999の数字のみをサポート
このブログには、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;
}
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コメントから再投稿
みんなのソリューションが非常に長く、複数の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;
}
これらの関数は、正の整数を同等のローマ数字文字列に変換します。そしてその数にローマ数字。
ローマ数字の数:
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;
};
以下で再帰的なソリューションを開発しました。この関数は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]);
}
}
}
私はこれが古い質問であることを知っていますが、私はこのソリューションをかなり誇りに思っています:)それは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">
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 で見つけることができます
個人的には、最も近い方法(決して最速ではない)が再帰であると思います。
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ですが、パターンに従うことで簡単に拡張できます。
この関数は、3,999,999より小さい数値をローマ字に変換します。 3999より大きい番号は、text-decoration
がoverline
に設定されたラベル内にあることに注意してください。これにより、番号が3999より大きい場合にx1000の正しい表現であるoverline
が追加されます。
400万(4,000,000)は2つのoverline
sを持つIVであるため、それを表すために何らかのトリックを使用する必要があります。おそらくDIV
with border-top
、またはこれらの2つのoverline
s ...各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;
}
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));
この投稿の実装のいくつかをテストした後、より高速に実行するために、最適化された新しい実装を作成しました。実行時間は他と比較して非常に短いですが、明らかにコードはいです:)。すべての可能性を持つインデックス配列を使用すると、さらに高速になる可能性があります。誰かを助けるために。
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;
}
HTMLElement(スパンなど)のこの番号の場合、HTML属性を追加することをお勧めしますdata-format
:
<p>Phase <span data-format="roman">4 </span> Sales</p>
注:これはhtml標準ではありません。使用したJavascriptコードは、jsfiddleのhtmlセクションを下にスクロールすると表示されます。
アラビア数字とローマ字の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;
}
より多くのシンボルで大きな数値を変換したい場合、このアルゴリズムが役立つかもしれません。
シンボルの唯一の前提は、奇数で、同じルール(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>
私はこれが時代遅れの質問であることを知っていますが、ここにリストされているものの中で最も短い解決策があり、理解しやすいと思うので共有したいと思いました。
このバージョンでは、他のように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);
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>
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;
}
正規表現ソリューションは次のとおりです。
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;
}
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桁、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から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);
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);
私のソリューションはより読みやすく、理解しやすいと感じています。
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;
}
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]);
}
}
}
これは、ローマ数字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;
}
/*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
表示のみを目的とする場合は、値(必要な場合)と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. -->
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);
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;
}
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);
これが私のコードです、これが役立つことを願っています:
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);
ローマに変換するために作成した関数を投稿しています。
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
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("");
}
これが私の「機能するように機能する」ソリューションです。
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);
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);
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 ''
}
これが私の解決策であり、どの程度うまく機能するかはわかりません。
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('');
}
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;
}
アラビア数字の配列をローマ字のペアの配列にマッピングすることで、これを実行しようとしました。厄介な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('');
}
すべての可能性を配列(多くの人がこのパズルを解決するために選んだ)にリストするのは嫌いなので、別の関数を使用してその作業を行います。私の解決策は次のとおりです。
//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++;
}
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);
}
私は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));
このコードでは、新しい文字を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;
}
これは単一のループを持つ私のソリューションです
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);
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より大きい数字に正しいシンボルを提供すると仮定すると、ほぼ無限の可能性を秘めていることを意味しますが、それについては引用しないでください。
これは、すべての異なるローマ数字とそれに対応する数字をループすることなく行う方法です。一定の時間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;
}
これを実現するにはいくつかの方法があります。個人的にはオブジェクトの使用を好み、キーと値のペアを反復処理します。
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;
}
私の答えは他の人ほどパフォーマンスが良くありませんが、ベース番号のハードコーディングではなく、プログラムが残りを理解できるようにすることに重点を置いていました。
例えば...
の代わりに: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('');
私の解決策は次のとおりです。
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
さて、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以上の行をリテラルの上に提供する必要があります。そして、私はまだ解決していません。
これがお役に立てば幸いです。
ループはよりエレガントかもしれませんが、読みにくいと思います。多かれ少なかれハードコーディングされたバージョンが目に付きやすくなりました。最初の行を理解している限り、残りは簡単です。
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;
}
この質問が尋ねられて以来、「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>
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)
)
おそらく最も簡単なソリューション:
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のソリューションです。
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;
}
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;
}
};