freeCodeCamp/curriculum/challenges/japanese/10-coding-interview-prep/project-euler/problem-89-roman-numerals.md

118 lines
15 KiB
Markdown
Raw Normal View History

---
id: 5900f3c51000cf542c50fed7
title: '問題 89: ローマ数字'
challengeType: 5
forumTopicId: 302204
dashedName: problem-89-roman-numerals
---
# --description--
ローマ数字で書かれた数字が有効とみなされるには、従うべき基本ルールがあります。 ルール上、複数の方法で表現できる数がいくつかありますが、特定の数字を書く*最良*の方法が必ず存在します。
- 数字は大きさの降順に並べなければならない。
- M, C, X は、それよりも小さい単位と等しくなったりそれに超えられたりしてはならない。
- D, L, V はそれぞれ一度のみ使用できる。
減算の組み合わせを用いる場合には、上の 3 つのルールに加えて次の 4 つのルールに従う必要があります。
- 減算ペア部分の先頭には、I, X, C をそれぞれ 1 つのみ使用できる
- I は V と X の前にしか置けない。
- X は L と C の前にしか置けない。
- C は D と M の前にしか置けない。
例えば、16 という数の書き方は少なくとも 6 通りあるように思えるでしょう。
<div style="margin-left: 4em; font-family: 'courier new', monospace;">
IIIIIIIIIIIIIIII<br>
VIIIIIIIIIII<br>
VVIIIIII<br>
XIIIIII<br>
VVVI<br>
XVI<br><br>
</div>
しかしルールによれば、XIIIIII と XVI のみが有効です。最後の例は、使う数字が最も少ないので、最も効率が良いといえます。
配列 `roman` には、有効ではあるが必ずしも最小形式ではないローマ数字が含まれています。
それらの各数字を最小形式で書くことで文字をいくつ減らせるか答えなさい。
**注:** 配列内のすべてのローマ数字について、同じ単位が 4 つより多く連続することはないと仮定できます。
# --hints--
`romanNumerals(testNumerals1)` は数値を返す必要があります。
```js
assert(typeof romanNumerals(_testNumerals1) === 'number');
```
`romanNumerals(testNumerals1)``19` を返す必要があります。
```js
assert.strictEqual(romanNumerals(_testNumerals1), 19);
```
`romanNumerals(testNumerals2)``743` を返す必要があります。
```js
assert.strictEqual(romanNumerals(_testNumerals2), 743);
```
# --seed--
## --after-user-code--
```js
const _testNumerals1 = [
'XIIIIII', 'XVI', 'MMMCCLXVIIII', 'XXXXVI', 'MMMMXX', 'CCLI', 'CCCCXX', 'MMMMDCXXXXI', 'DCCCCIIII', 'MXVIIII'
];
const _testNumerals2 = [
'MMMMDCLXXII','MMDCCCLXXXIII','MMMDLXVIIII','MMMMDXCV','DCCCLXXII','MMCCCVI','MMMCDLXXXVII','MMMMCCXXI','MMMCCXX','MMMMDCCCLXXIII','MMMCCXXXVII','MMCCCLXXXXIX','MDCCCXXIIII','MMCXCVI','CCXCVIII','MMMCCCXXXII','MDCCXXX','MMMDCCCL','MMMMCCLXXXVI','MMDCCCXCVI','MMMDCII','MMMCCXII','MMMMDCCCCI','MMDCCCXCII','MDCXX','CMLXXXVII','MMMXXI','MMMMCCCXIV','MLXXII','MCCLXXVIIII','MMMMCCXXXXI','MMDCCCLXXII','MMMMXXXI','MMMDCCLXXX','MMDCCCLXXIX','MMMMLXXXV','MCXXI','MDCCCXXXVII','MMCCCLXVII','MCDXXXV','CCXXXIII','CMXX','MMMCLXIV','MCCCLXXXVI','DCCCXCVIII','MMMDCCCCXXXIV','CDXVIIII','MMCCXXXV','MDCCCXXXII','MMMMD','MMDCCLXIX','MMMMCCCLXXXXVI','MMDCCXLII','MMMDCCCVIIII','DCCLXXXIIII','MDCCCCXXXII','MMCXXVII','DCCCXXX','CCLXIX','MMMXI','MMMMCMLXXXXVIII','MMMMDLXXXVII','MMMMDCCCLX','MMCCLIV','CMIX','MMDCCCLXXXIIII','CLXXXII','MMCCCCXXXXV','MMMMDLXXXVIIII','MMMDCCCXXI','MMDCCCCLXXVI','MCCCCLXX','MMCDLVIIII','MMMDCCCLIX','MMMMCCCCXIX','MMMDCCCLXXV','XXXI','CDLXXXIII','MMMCXV','MMDCCLXIII','MMDXXX','MMMMCCCLVII','MMMDCI','MMMMCDLXXXIIII','MMMMCCCXVI','CCCLXXXVIII','MMMMCML','MMMMXXIV','MMMCCCCXXX','DCCX','MMMCCLX','MMDXXXIII','CCCLXIII','MMDCCXIII','MMMCCCXLIV','CLXXXXI','CXVI','MMMMCXXXIII','CLXX','DCCCXVIII','MLXVII','DLXXXX','MMDXXI','MMMMDLXXXXVIII','MXXII','LXI','DCCCCXLIII','MMMMDV','MMMMXXXIV','MDCCCLVIII','MMMCCLXXII','MMMMDCCXXXVI','MMMMLXXXIX','MDCCCLXXXI','MMMMDCCCXV','MMMMCCCCXI','MMMMCCCLIII','MDCCCLXXI','MMCCCCXI','MLXV','MMCDLXII','MMMMDXXXXII','MMMMDCCCXL','MMMMCMLVI','CCLXXXIV','MMMDCCLXXXVI','MMCLII','MMMCCCCXV','MMLXXXIII','MMMV','MMMV','DCCLXII','MMDCCCCXVI','MMDCXLVIII','CCLIIII','CCCXXV','MMDCCLXXXVIIII','MMMMDCLXXVIII','MMMMDCCCXCI','MMMMCCCXX','MMCCXLV','MMMDCCCLXIX','MMCCLXIIII','MMMDCCCXLIX','MMMMCCCLXIX','CMLXXXXI','MCMLXXXIX','MMCDLXI','MMDCLXXVIII','MMMMDCCLXI','MCDXXV','DL','CCCLXXII','MXVIIII','MCCCCLXVIII','CIII','MMMDCCLXXIIII','MMMDVIII','MMMMCCCLXXXXVII','MMDXXVII','MMDCCLXXXXV','MMMMCXLVI','MMMDCCLXXXII','MMMDXXXVI','MCXXII','CLI','DCLXXXIX','MMMCLI','MDCLXIII','MMMMDCCXCVII','MMCCCLXXXV','MMMDCXXVIII','MMMCDLX','MMMCMLII','MMMIV','MMMMDCCCLVIII','MMMDLXXXVIII','MCXXIV','MMMMLXXVI','CLXXIX','MMMCCCCXXVIIII','DCCLXXXV','MMMDCCCVI','LI','CLXXXVI','MMMMCCCLXXVI','MCCCLXVI','CCXXXIX','MMDXXXXI','MMDCCCXLI','DCCCLXXXVIII','MMMMDCCCIV','MDCCCCXV','MMCMVI','MMMMCMLXXXXV','MMDCCLVI','MMMMCCXLVIII','DCCCCIIII','MMCCCCIII','MMMDCCLXXXVIIII','MDCCCLXXXXV','DVII','MMMV','DCXXV','MMDCCCXCV','DCVIII','MMCDLXVI','MCXXVIII','MDCCXCVIII','MMDCLX','MMMDCCLXIV','MMCDLXXVII','MMDLXXXIIII','MMMMCCCXXII','MMMDCCCXLIIII','DCCCCLXVII','MMMCLXXXXIII','MCCXV','MMMMDCXI','MMMMDCLXXXXV','MMMCCCLII','MMCMIX','MMDCCXXV','MMDLXXXVI','MMMMDCXXVIIII','DCCCCXXXVIIII','MMCCXXXIIII','MMDCCLXXVIII','MDCCLXVIIII','MMCCLXXXV','MMMMDCCCLXXXVIII','MMCMXCI','MDXLII','MMMMDCCXIV','MMMMLI','DXXXXIII','MMDCCXI','MMMMCCLXXXIII','MMMDCCCLXXIII','MDCLVII','MMCD','MCCCXXVII','MMMMDCCIIII','MMMDCCXLVI','MMMCLXXXVII','MMMCCVIIII','MCCCCLXXIX','DL','DCCCLXXVI','MMDXCI','MMMMDCCCCXXXVI','MMCII','MMMDCCCXXXXV','MMMCDXLV','MMDCXXXXIV','MMD','MDCCCLXXXX','MMDCXLIII','MMCCXXXII','MMDCXXXXVIIII','DCCCLXXI','MDXCVIIII','MMMMCCLXXVIII','MDCLVIIII','MMMCCCLXXXIX','MDCLXXXV','MDLVIII','MMMMCCVII','MMMMDCXIV','MMMCCCLXIIII','MMIIII','MMMMCCCLXXIII','CCIII','MMMCCLV','MMMDXIII','MMMCCCXC','MMMDCCCXXI','MMMMCCCCXXXII','CCCLVI','MMMCCCLXXXVI','MXVIIII','MMMCCCCXIIII','CLXVII','MMMCCLXX','CCCCLXIV','MMXXXXII','MMMMCCLXXXX','MXL','CCXVI','CCCCLVIIII','MMCCCII','MCCCLVIII','MMMMCCCX','MCDLXXXXIV','MDCCCXIII','MMDCCCXL','MMMMCCCXXIII','DXXXIV','CVI','MMMMDCLXXX','DCCCVII','MMCMLXIIII','MMMDCCCXXXIII','DCCC','MDIII','MMCCCLXVI','MMMCCCCLXXI','MMDCCCCXVIII','CCXXXVII','CCCXXV','MDCCCXII','MMMCMV','MMMMCMXV','MMMMDCXCI','DXXI','MMCCXLVIIII','MMMMCMLII','MDLXXX','MMDCLXVI','CXXI','MMMDCCCLIIII','MMMCXXI','MCCIII','MMDCXXXXI','CCXCII','MMMMDXXXV','MMMCCCLXV','MMMMDLXV','MMMCCCCXXXII','MMMCCCVIII','DCCCCLXXXXII','MMCLXIV','MMMMCXI','MLXXXXVII','MMMCDXXXVIII','MDXXII','MLV','MMMMDLXVI','MMMCXII','XXXIII','MMMMDCCCXXVI','MMMLXVIIII','MMMLX','MMMCDLXVII','MDCCCLVII','MMCXXXVII','M
];
```
## --seed-contents--
```js
function romanNumerals(roman) {
return true;
}
// Only change code above this line
const testNumerals1 = [
'XIIIIII', 'XVI', 'MMMCCLXVIIII', 'XXXXVI', 'MMMMXX', 'CCLI', 'CCCCXX', 'MMMMDCXXXXI', 'DCCCCIIII', 'MXVIIII'
];
romanNumerals(testNumerals1);
```
# --solutions--
```js
function romanNumerals(roman) {
const numerals = [...roman];
const replaces = [
['VIIII', 'IX'],
['IIII', 'IV'],
['LXXXX', 'XC'],
['XXXX', 'XL'],
['DCCCC', 'CM'],
['CCCC', 'CD']
];
let savedChars = 0;
for (let i = 0; i < numerals.length; i++) {
const charsBefore = numerals[i].length;
for (let j = 0; j < replaces.length; j++) {
numerals[i] = numerals[i].replace(...replaces[j]);
}
const charsAfter = numerals[i].length;
savedChars += charsBefore - charsAfter;
}
return savedChars;
}
```