暗号化されたローマ数字をアラビア数字に変換します


16

一連の文字をローマ数字として解釈するアルゴリズムを作成します。(以下のローマ数字の規則を参照)

それぞれ異なる文字には、一致するアラビア語の10進数値があり、最大値はありません。しかし、あなたは事前にキーを持っていないので{A=10, I=1, X=5, ... Z=1000000}、あなたの解釈によって決定されます。

チャレンジ

  1. 介して読み出し入力STDIN出力経由または同等の書き込みSTDOUTまたは同等
  2. 有効な入力は、大文字と小文字の組み合わせ、つまり一致です \[a-zA-Z]+\
  3. 入力を検証して、文字シーケンスが有効なローマ数字として解釈できるかどうかを確認する必要があります
  4. 入力が検証に合格した場合、有効な出力はアラビア語の10進数の最低解釈であり、使用されるキーAaはそうでは4 {a=5, A=1} ない と解釈される6 {A=5, a=1} か、または 9 {a=10, a=1}

ローマ数字の規則

  1. 10のべき乗を表す文字のみを繰り返すことができます。連続して最大3回、合計で4回などです。 II III XXXIX

  2. 値が大きい別の文字の後に1つ以上の文字が配置されている場合は、その量を追加します

    AAaa   => 22 {A=10, a=1}          (20 + 2 = 22)  
    bbAAaa => 222 {b=100, A=10, a=1}  (200 + 20 + 2 = 222)   
    
  3. 文字がより大きな値の別の文字の前に配置されている場合、その量を減算します

    Aa    => 4 {a=5, A=1}                 (5 – 1 = 4)  
    AaA   => 19 {A=10, a=1}               (10 + 10 – 1 = 19)  
    BbBaA => 194 {B=100, b=10, A=5, a=1}  (100 + 100 - 10 + 5 - 1 = 194)  
    

    ローマ数字から金額を引くには、いくつかの規則が適用されます。

    • すなわち10の減算力だけ1, 10, 100... ではありません 5, 50, 500...
    • したがって、二重減算18ないように書かれてXVIII います IIXX (10 + 10 - 1 - 1)
    • 10倍を超える数値を1から減算しないでください。
      あなたは引くことができます1から、5 または 10が、ないから50, 100, 500...

Input:

Aa  
BAa  
CCCXLVII   
MMMCDVII  
ABADDF  
XVVX  
FAASGSH  
DXCCDA  
AaBbcDEf   

Output:

4 {a=5, A=1}  
14 {B=10, a=5, A=1}  
347 {C=100, L=50, X=10, V=5, I=1}  
347 {M=100, D=50, C=10, V=5, I=1}  
1921 {A=1000, B=100, D=10, F=1}  
'XVVX' failed Roman numeral test  
7191 {F=5000, A=1000, S=100, G=10, H=1}  
'DXCCDA' failed Roman numeral test
4444 {a=5000, A=1000, b=500, B=100, D=50, c=10, f=5, E=1}  

3
@IamOgbzこれは素晴らしい質問になりましたが、途中でコメントに多くの質問を集めました。評判が十分になったので、サンドボックスをお勧めします。投稿する直前に質問をするのにとても便利だと思います。
trichoplax

CCCLXVIIはCCCXLVIIと解釈され、347になりませんか?
スカイラー

@Skyler絶対に正しいです、今すぐ更新します!ありがとう。
iamogbz

個々の文字が持つことができる値に制限はありません(実際、20は標準のローマ数字の値ではありません)。あなたはそれを言うことを意味するか任意の正の整数をローマ数字で表すことができますか?その場合、Aa値は1(A = 1、a = 2)です。
msh210

文字はローマ数字としてのみ解釈できるため、@ msh210は個々の文字値は10のべき乗または10の5のべき乗の倍数にしかなれないということになります。 19は有効な減算ではありません)。それがあなたのためにそれを解決することを願っています。
iamogbz

回答:


1

Pythonの2、415の 444 440 419 416バイト

結局のところ、それほど多くのローマ数字はありません。このスクリプトはそれらすべてを作成し、入力のすべての順列をチェックしてから、最小一致を返します。

a=raw_input()
g=range
b=list(set(a))+[' ']*9
from itertools import*
c=[]
s={}
u=1000
for i in g(10*u):
 t,f=(10*u,9*u,5*u,4*u,u,900,500,400,100,90,50,40,10,9,5,4,1),i;r=""
 for j in g(17):k=i/t[j];r+=('W MW Q MQ M CM D CD C XC L XL X IX V IV I').split()[j]*k;i-=t[j]*k
 s[r]=f
for i in permutations(b[:9]):
 r=''
 for j in a:r+='IVXLCMQWE'[i.index(j)]
 if r in s:c+=[s[r]]
print c and min(c)or'%s failed Roman numeral test'%a

それは現在の挑戦に対する良い答えです。しかし、早めに消されたコメントの会話では、この(実際ではない)システムはM = 1000の後に続き、5k、10kなどのシンボルを持っていることが示唆されました。一番上の最初の例を見てください:{A = 10、I = 1、X = 5、... Z = 1000000}は解釈によって決定されます
-edc65

..、および最後の例、a = 5000
...-edc65

指定されたすべてのテストケースを処理するように更新しました。ローマ数字の数にO(n!)時間を要するため、このアプローチを10,000を超えて拡張できるとは思いません。
スカイラー

@Skylerのテストケースは完全ではありません。プログラムは、あいまいな場合には低い数字を優先して、ローマ数字の規則に従って解釈できる有効な入力のすべての可能な順列を処理する必要があります。また、コードは最後のテストケースリンクを
iamogbz

ありませんimport itertools as iし、その後i.permutations短いですか?
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.