Tạo một máy tính số La Mã


18

Tạo một máy tính cơ bản cho chữ số La Mã.

Yêu cầu

  • Hỗ trợ +, -, *,/
  • Đầu vào và đầu ra chỉ mong đợi một tiền tố trừ cho mỗi ký hiệu (nghĩa là 3 không thể IIVvì có hai I'trước V)
  • Xử lý theo nguyên tắc trừ ở đầu vào và đầu ra phải tại vùng hỗ trợ tối thiểu ước tiêu chuẩn hiện đại, trong đó chỉ có quyền hạn trong mười được trừ vào số lớn hơn (ví dụ như I, X, Csubtractors được yêu cầu nhưng không V, L, D) và trừ không bao giờ được thực hiện từ một số hơn 10 lần phép trừ (ví dụ: IXphải được hỗ trợ nhưng ICkhông bắt buộc).
  • Đầu vào và đầu ra phải từ trái sang phải theo thứ tự giá trị, bắt đầu bằng giá trị lớn nhất (nghĩa là 19 = XIXkhông IXX, 10 lớn hơn 9)
  • Trái sang phải, không có quyền ưu tiên của nhà điều hành, như thể bạn đang sử dụng máy tính cầm tay.
  • Hỗ trợ toàn bộ đầu vào / đầu ra số dương trong khoảng 1-4999 (không cần V̅)
  • Không có thư viện nào thực hiện chuyển đổi số La Mã cho bạn

Để bạn quyết định

  • Độ nhạy trường hợp
  • Dấu cách hoặc không có khoảng trắng trên đầu vào
  • Điều gì xảy ra nếu bạn nhận được một đầu ra thập phân. Cắt ngắn, không có câu trả lời, lỗi, vv ..
  • Phải làm gì cho đầu ra mà bạn không thể xử lý. Số âm hoặc số lớn sẽ được in.
  • Có ủng hộ việc sử dụng nguyên tắc trừ tự do hơn yêu cầu tối thiểu hay không.

Tín dụng thêm

  • -50 - Xử lý lên tới 99999 hoặc lớn hơn. Các biểu tượng phải bao gồm một con vinculum

Đầu vào / đầu ra mẫu

XIX + LXXX                 (19+80)
XCIX

XCIX + I / L * D + IV      (99+1/50*500+4)
MIV

Mã ngắn nhất sẽ thắng.


(99 + 1/50 * 500 + 4) = (99 + 10 + 4) = 113, nhưng đầu vào / đầu ra mẫu của bạn cho biết đó là MIV (1004).
Victor Stafusa

1
@Victor - Hoạt động nghiêm ngặt từ trái sang phải - không có quy tắc ưu tiên - vì vậy 99 + 1/50 * 500 + 4 phải được tính là ((((99 + 1) / 50) * 500) + 4)

Là xử lý số lượng như IM = 999yêu cầu?
Kendall Frey

@KendallFrey Tôi mong bạn có thể nhập IM. Cho dù đầu ra là IMhoặc CMXCIXcho 999 là tùy thuộc vào bạn. Cả hai đều phù hợp với yêu cầu.
Danny

2
IM là không chuẩn cho việc sử dụng chữ số La Mã hiện đại. Thông thường, chỉ có 4 và 9 của mỗi thứ tự cường độ (4, 9, 40, 90, 400, 900, v.v.) được thực hiện bằng phép trừ. Năm 1999, MCMXCIX sẽ là kinh điển, không phải MIM ... xem các khoản tín dụng của bất kỳ bộ phim nào từ năm đó. Nếu không, nó kết thúc ở đâu? Chúng tôi cũng dự kiến ​​sẽ hỗ trợ các phép trừ không chuẩn khác như VL cho 45? IC có vinculum trên C có được hỗ trợ là 99999 cho phần thưởng không?
Jonathan Van Matre

Câu trả lời:


9

JavaScript (ES6), 238

c=s=>{X={M:1e3,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1}
n=eval('W='+s.replace(/[\w]+/g,n=>(o=0,n.replace(/[MDLV]|C[MD]?|X[CL]?|I[XV]?/g,d=>o+=X[d]),
o+';W=W')));o='';for(i in X)while(n>=X[i])o+=i,n-=X[i];return o}

Sử dụng:

c("XIX + LXXX")
> "XCIX"
c('XCIX + I / L * D + IV')
> "MIV"

Phiên bản chú thích:

/**
 * Process basic calculation for roman numerals.
 * 
 * @param {String} s The calculation to perform
 * @return {String} The result in roman numerals
 */
c = s => {
  // Create a lookup table.
  X = {
    M: 1e3, CM: 900, D: 500, CD: 400, C: 100, XC: 90, 
    L: 50,  XL: 40,  X: 10,  IX: 9,   V: 5,   IV: 4, I: 1
  };
  // Do the calculation.
  // 
  // The evaluated string is instrumented to as below:
  //   99+1/50*500+4 -> W=99;W=W+1;W=W/50;W=W*500;W=W+4;W=W
  //                 -> 1004
  n = eval('W=' + s.replace(
    // Match all roman numerals.
    /[\w]+/g,
    // Convert the roman number into an integer.
    n => (
      o = 0,
      n.replace(
        /[MDLV]|C[MD]?|X[CL]?|I[XV]?/g,
        d => o += X[d]
      ),
      // Instrument number to operate left-side operations.
      o + ';W=W'
    )
  ));

  // Convert the result into roman numerals.
  o = '';
  for (i in X)
    while (n >= X[i])
      o += i,
      n -= X[i];

  // Return calculation result.
  return o
}

9

T-SQL, 1974 - 50 = 1924 byte

Tôi biết rằng chơi golf trong SQL tương đương với chơi 18 lỗ mà không có gì ngoài một cái nêm cát, nhưng tôi thích thử thách của cái này và tôi nghĩ rằng tôi đã xoay sở để làm một vài điều thú vị về phương pháp.

Điều này không hỗ trợ vinculum cho cả đầu vào và đầu ra. Tôi đã thông qua quy ước sử dụng dấu ngã để biểu thị nó, vì vậy V ~ là 5000, X ~ là 10000, v.v. Nó cũng nên xử lý các đầu ra lên tới 399.999 theo cách sử dụng chữ số La Mã hiện đại tiêu chuẩn. Sau đó, nó sẽ thực hiện mã hóa La Mã không chuẩn một phần cho bất kỳ thứ gì trong phạm vi được hỗ trợ của INT.

Bởi vì đó là tất cả toán học số nguyên, bất kỳ kết quả không nguyên nào đều được làm tròn hoàn toàn.

DECLARE @i VARCHAR(MAX)
SET @i='I+V*IV+IX*MXLVII+X~C~DCCVI'
SELECT @i

DECLARE @t TABLE(i INT IDENTITY,n VARCHAR(4),v INT)
DECLARE @u TABLE(n VARCHAR(50),v INT)
DECLARE @o TABLE(n INT IDENTITY,v CHAR(1))
DECLARE @r TABLE(n INT IDENTITY,v INT,r VARCHAR(MAX))
DECLARE @s TABLE(v INT,s VARCHAR(MAX))
DECLARE @p INT,@x VARCHAR(4000)='SELECT ',@j INT=1,@m INT,@y INT,@z VARCHAR(2),@q VARCHAR(50)='+-/*~]%'
INSERT @t(n,v) VALUES('i',1),('iv',4),('v',5),('ix',9),('x',10),('xl',50),('l',50),('xc',90),('c',100),('cd',400),('d',500),('cm',900),('m',1000),('mv~',4000),('v~',5000),('mx~',9000),('x~',10000),('x~l~',40000),('l~',50000),('x~c~',90000),('c~',100000)
INSERT @u VALUES('%i[^i'+@q,-2),('%v[^vi'+@q,-10),('%x[^xvi'+@q,-20),('%l[^lxvi'+@q,-100),('%c[^clxvi'+@q,-200),('%d[^dclxvi'+@q,-1000),('%mx~%',-2010),('%x~l~%',-20060),('%x~c~%',-20110)
WHILE PATINDEX('%[+-/*]%', @i)!=0
BEGIN
    SET @p=PATINDEX('%[+-/*]%', @i)
    INSERT @o(v) SELECT SUBSTRING(@i,@p,1)
    INSERT @r(r) SELECT SUBSTRING(@i,1,@p-1)
    SET @i=STUFF(@i,1,@p,'')
END 
INSERT @r(r) SELECT @i
UPDATE r SET v=COALESCE(q.v,0) FROM @r r LEFT JOIN (SELECT r.r,SUM(u.v)v FROM @u u JOIN @r r ON r.r LIKE u.n GROUP BY r.r)q ON q.r=r.r
UPDATE r SET v=r.v+q.v FROM @r r JOIN (SELECT r.n,r.r,SUM((LEN(r.r)-LEN(REPLACE(r.r,t.n,REPLICATE(' ',LEN(t.n)-1))))*t.v) v FROM @r r JOIN @t t ON CHARINDEX(t.n,r.r) != 0 AND (LEN(t.n)=1 OR (LEN(t.n)=2 AND RIGHT(t.n,1)='~')) GROUP BY r.n,r.r) q ON q.r=r.r AND q.n = r.n
SELECT @m=MAX(n) FROM @o
SELECT @x=@x+REPLICATE('(',@m)+CAST(v AS VARCHAR) FROM @r WHERE n=1
WHILE @j<=@m
BEGIN
    SELECT @x=@x+o.v+CAST(r.v AS VARCHAR)+')'
    FROM @o o JOIN @r r ON r.n=o.n+1 WHERE o.n=@j
    SET @j=@j+1
END 
INSERT @s(v,s) EXEC(@x+',''''')
UPDATE @s SET s=s+CAST(v AS VARCHAR(MAX))+' = '
SET @j=21
WHILE @j>0
BEGIN
    SELECT @y=v,@z=n FROM @t WHERE i = @j
    WHILE @y<=(SELECT v FROM @s)
    BEGIN
        UPDATE @s SET v=v-@y,s=s+@z
    END  
    SET @j=@j-1
END
SELECT @x+' = '+UPPER(s) FROM @s

Tôi vẫn đang nghiên cứu một giải pháp dựa trên tập hợp để thay thế một số vòng lặp WHILE có thể làm giảm số lượng byte và là một ví dụ thanh lịch hơn về SQL thành ngữ. Ngoài ra còn có một số byte đạt được bằng cách giảm sử dụng bí danh bảng xuống mức tối thiểu. Nhưng vì về cơ bản, nó không thể chiến thắng được bằng ngôn ngữ này, tôi chủ yếu chỉ ở đây để thể hiện trang phục Don Quixote của mình. :)

CHỌN @i ở đầu lặp lại đầu vào:

I+V*IV+IX*MXLVII+X~C~DCCVI

Và CHỌN ở cuối trả về:

SELECT (((((1+5)*4)+9)*1047)+90706) = 125257 = C~X~X~V~CCLVII

Và bạn có thể tự kiểm tra nó tại SQLFiddle này

Và tôi sẽ trở lại để thêm một số bình luận về cách thức hoạt động của nó, bởi vì tại sao đăng một câu trả lời rõ ràng bị mất nếu bạn sẽ không khai thác nó cho giá trị giáo dục?


2

Javascript - 482 476 ký tự

String.prototype.m=String.prototype.replace;eval("function r(a){return a>999?'Mk1e3j899?'CMk900j499?'Dk500j399?'CDk400j99?'Ck100j89?'XCk90j49?'Lk50j39?'XLk40j9?'Xk10j8?'IX':a>4?'Vk5j3?'IV':a>0?'Ik1):''}".m(/k/g,"'+r(a-").m(/j/g,"):a>"));s=prompt();h=s.match(/\w+/gi);for(k in h)s=s.m(h[k],eval(eval("'0'+h[k].m(/IVu4pIXu9pXLu40pXCu90pCDu400pCMu900pMu1000pDu500pCu100pLu50pXu10pVu5pIu1')".m(/u/g,"/g,'+").m(/p/g,"').m(/")))+")");for(k in h)s="("+s;alert(r(Math.floor(eval(s))))

Đầu vào / đầu ra mẫu hoạt động:

XIX + LXXX -> XCIX
XCIX + I / L * D + IV -> MIV

Nó cũng xử lý số lượng lớn quá lớn:

MMM+MMM -> MMMMMM
M*C -> MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

Và nó chấp nhận, nhưng không yêu cầu, không gian quá.

Nhưng, vì tôi đã chơi golf nên có một số vấn đề:

  • Nó không xác nhận nếu đầu vào được hình thành tốt. Nếu đầu vào không được định dạng tốt, hành vi không được xác định (và trong thực tế, nó rất kỳ quái và kỳ lạ).
  • Nó cắt các số phân số trên đầu ra (nhưng nó có thể thực hiện các phép tính trung gian với chúng).
  • Nó thực sự lạm dụng chức năng eval.
  • Nó không cố gắng để xử lý số âm.
  • Nó là trường hợp nhạy cảm.

Phiên bản thay thế này xử lý số lượng trên 5000 lên tới 99999, nhưng nó có 600 598 584 ký tự:

String.prototype.m=String.prototype.replace;eval("function r(a){return a>8zz?'XqCqk9e4j4zz?'Lqk5e4j3zz?'XqLqk4e4jzz?'Xqk1e4j89z?'IqXqk9e3j49z?'Vqk5e3j9z?'Mk1e3j8z?'CMk900j4z?'Dk500j3z?'CDk400jz?'Ck100j89?'XCk90j49?'Lk50j39?'XLk40j9?'Xk10j8?'IX':a>4?'Vk5j3?'IV':a>0?'Ik1):''}".m(/k/g,"'+r(a-").m(/j/g,"):a>").m(/q/g,"\u0305").m(/z/g,"99"));s=prompt();h=s.match(/\w+/gi);for(k in h)s=s.m(h[k],eval(eval("'0'+h[k].m(/IVu4pIXu9pXLu40pXCu90pCDu400pCMu900pMu1000pDu500pCu100pLu50pXu10pVu5pIu1')".m(/u/g,"/g,'+").m(/p/g,"').m(/")))+")");for(k in h)s="("+s;console.log(r(Math.floor(eval(s))))

Tôi không nghĩ rằng -20 được áp dụng: xem vinculum
SeanC

Đồng ý với @SeanCheshire tại đây. Đối với việc xử lý số lớn hơn, ý định là thêm một vinculum trên chữ số để gấp 1000 lần giá trị của nó. Có lẽ nó phải lớn hơn -20 để nó đáng để mọi người thử.
Danny

1
@Danny Tôi đã thêm một phiên bản xử lý vinculus, nhưng nó tăng mã trong 116 ký tự.
Victor Stafusa

2

Javascript 479 361 348 278 253

303 ký tự - 50 cho số hỗ trợ lên tới 1 triệu, hoàn thành với hỗ trợ vinculum:

function p(s){s=s[r](/(^|[*\/+-])/g,"0;s$1=");for(i in v){f=R("\\b"+i);while(f.test(s))s=s[r](f,v[i]+"+")}eval(s+"0");h="";for(i in v)while(s>=v[i]){h+=i;s-=v[i]}return h}v={M̅:1e6,D̅:5e5,C̅:1e5,L̅:5e4,X̅:1e4,V̅:5e3,M:1e3,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1};r="replace";R=RegExp

Cách sử dụng: p(text)ví dụ: p('XIX + LXXX')trả về XCIX.

Mã với ý kiến ​​giải thích:

// Array mapping characters to values
v={M¯:1e6,D¯:5e5,C¯:1e5,L¯:5e4,X¯:1e4,V¯:5e3,M:1e3,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1};
// Shortcut for String.replace
r='replace';
R=RegExp;

// The heart of the program
function p(s) {
    // Replace operators with ";s+=", ";s-=", and so on
    s=s[r](/(^|[*\/+-])/g,'0;s$1=');
    // Loop over the character map and replace all letters with numbers
    for(i in v){
        f=R('\\b'+i);
        while(f.test(s))
            s=s[r](f, v[i]+'+')
    }
    eval(s+'0');
    // Set up our return string
    h='';
    // Replace digits with characters
    for(i in v)
        while(s>=v[i]) {
            h+=i;
            s-=v[i];
        }
    return h;
}

Điều này làm việc cho các mẫu nhất định và cho tất cả những người khác tôi đã thử. Ví dụ:

XIX + LXXX = XCIX
XCIX + I / L * D + IV = MIV
XL + IX/VII + II * XIX = CLXXI
CD + C + XL + X + I = DLI
M̅ + I = M̅I
MMMM + M = V̅

2

Ruby 2.1, 353 (và nhiều lần lặp khác) , 295 - 50 = 245

Việc xử lý vinculum thêm ~ 23 ký tự.

Điều này xử lý "IL" hoặc "VM" trong đầu vào, và không có lỗi về phủ định (chuyển đến ints cao) hoặc số thập phân (cắt ngắn) hoặc bất kỳ khoảng trắng nào. Bây giờ cũng xử lý một số đầu tiên âm (mặc dù nếu tổng số âm, nó vẫn thất bại kém). Cũng thất bại kém nếu bạn bắt đầu bằng * hoặc / hoặc nếu kết quả là 4 triệu hoặc lớn hơn.

Sử dụng đối tượng # gửi cho chức năng "máy tính tay".

m=%w{I V X L C D M V̅ X̅ L̅ C̅ D̅ M̅};n=m.zip((0..12).map{|v|(v%2*4+1)*10**(v/2)}).to_h
d=0
gets.scan(/([-+*\/])?([A-Z̅]+)/){|o,l|f=t=0
l.scan(/.̅?/){t-=2*f if f<v=n[$&]
t+=f=v}
d=d.send o||:+,t}
7.downto(1){|v|z=10**v
y=(d%z)*10/z
q,w,e=m[v*2-2,3]
$><<(y>8?q+e : y<4?q*y : y<5?q+w : w+q*(y-5))}

Ung dung:

m=%w{I V X L C D M V̅ X̅ L̅ C̅ D̅ M̅} # roman numerals
n=m.zip((0..12).map{|v|(v%2*4+1)*10**(v/2)}).to_h # map symbols to values
d=0
gets. # get input and...
  scan(/([-+*\/])?([A-Z̅]+)/) { |l,o|  # for each optional operator plus number
    f=t=0
    l.scan(/.̅?/){                           # read the number in one letter at a time
      t -= 2 * f if f < (v=n[$&])           # if the number's greater than the prev, subtract the prev twice since you already added it
      t += (f = v)                          # add this, and set prev to this number
    }
    d = d.send((o || :+), t)                # now that we've built our number, "o" it to the running total (default to +)
}
7.upto(1) { |v|                        # We now print the output string from left to right
  z = 10**v                            # z = [10, 100, 1000, etc.]
  y = (d%z)*10/z                       # if d is 167 and z is 100, y = 67/10 = 6 
  q,w,e = m[v*2-2,3]                   # q,w,e = X, L, C
  $><< (                               # print: 
    y>8 ? q+e :                        # if y==9,    XC
      y<4 ? q*y :                      # if y<4,     X*y
        y>3 ? q+w :                    # if y==4,    XL
          q*(y-5)                      # else,       L + X*(y-5)
  )
}

2

Python 2 - 427 418 404 401 396 395 392 ký tự

Đọc từ đầu vào tiêu chuẩn. Nó chỉ xử lý chữ hoa (có thể làm cho nó không phân biệt chữ hoa chữ thường với giá 8 ký tự phụ) và yêu cầu khoảng trắng. Không có xác nhận - Tôi chưa thử nghiệm để xem nó phá vỡ như thế nào trong các trường hợp khác nhau. Tuy nhiên, nó xử lý các số như VC = 95.

N=['?M','DC','LX','VI'];t=0;o='+'
for q in raw_input().split():
 if q in"+-*/":o=q;continue
 n=s=0;X=1
 for l in q:
  x=''.join(N).find(l);v=(5-x%2*4)*10**(3-x/2)
  if X<x:n+=s;s=v;X=x
  elif X>x:n+=v-s;s=0
  else:n+=v+s;s=0
 exec"t"+o+"=n+s"
r=t/1000*'M'
for p,d in enumerate("%04d"%(t%1e3)):
 i="49".find(d);g=N[p]
 if i<0:
  if'4'<d:r+=g[0]
  r+=int(d)%5*g[1]
 else:r+=g[1]+N[p-i][i]
print r

Và phiên bản vô văn hóa:

# Numerals grouped by powers of 10
N = ['?M','DC','LX','VI']
# Start with zero plus whatever the first number is
t = 0
o = '+'
for q in raw_input().split():
    if q in "+-*/":
        # An operator; store it and skip to the next entry
        o = q
        continue
    # n holds the converted Roman numeral, s is a temp storage variable
    n = s = 0
    # X stores our current index moving left-to-right in the string '?MDCLXVI'
    X = 1
    for l in q:
        # x is the index of the current letter in '?MDCLXVI'
        x = ''.join(N).find(l)
        # Calculate the value of this letter based on x
        v = (5 - x%2 * 4) * 10 ** (3 - x/2)
        if X < x:
            # We're moving forward in the list, e.g. CX
            n += s      # Add in any previously-stored value
            s = v       # Store this value in case we have something like CXL
            X = x       # Advance the index
        elif X > x:
            # Moving backward, e.g. XC
            n += v - s  # Add the current value and subtract the stored one
            s=0
        else:
            # Same index as before, e.g. XX
            n += v + s  # Add the current value and any stored one
            s = 0
    # Update total using operator and value (including leftover stored value
    # if any)
    exec "t" + o + "=n+s"

# Now convert the answer back to Roman numerals
# Special-case the thousands digit
r = t / 1000 * 'M'
# Loop over the number mod 1000, padded with zeroes to four digits (to make
# the indices come out right)
for p, d in enumerate("%04d" % (t % 1e3)):
    i = "49".find(d)
    g = N[p]
    if i < 0:
        # i == -1, thus d isn't '4' or '9'
        if '4' < d:
            # >= 5, so add the 5's letter
            r += g[0]
        # ... plus (digit % 5) copies of the 1's letter
        r += int(d) % 5 * g[1]
    else:
        # If it's a 4 or 9, add the 1's letter plus the appropriate
        # larger-valued letter
        r += g[1] + N[p-i][i]
print r

Tôi có cảm giác Perl sẽ tốt hơn, nhưng tôi không biết đủ về nó. Tuy nhiên, đối với cú đâm đầu tiên vào môn đánh gôn, tôi cảm thấy khá tốt về điều này.


1

PHP - 549 525 524 520 byte

Không có gì quá sáng tạo: bình thường hóa các toán tử để đảm bảo quyền ưu tiên từ trái sang phải, chuyển đổi La Mã thành số thập phân, chạy evaltrên câu lệnh, ví dụ XCIX + I / L * D + IV được chuyển đổi thành thứ gì đó như return (((((+90 +9) + (+1)) / (+50)) * (+500)) + (+4)); , sau đó chuyển đổi thập phân trở lại La Mã.

  • kết quả cuối cùng bị cắt ngắn
  • câu trả lời ít hơn 1 trở lại trống
  • kết quả không xác định nếu đưa ra đầu vào không chính xác
$f='str_replace';$g='str_split';$c=array('M'=>1e3,'CM'=>900,'D'=>500,'CD'=>400,'C'=>100,'XC'=>90,'L'=>50,'XL'=>40,'X'=>10,'IX'=>9,'V'=>5,'IV'=>4,'I'=>1);$j='['.$f(array('+','-','*','/'),array('])+[','])-[','])*[','])/['), $argv[1]).'])';$j=str_repeat('(',substr_count($j,')')).$j;$j=$f('[','(',$j);$j=$f(']',')',$j);foreach($g('IVIXXLXCCDCM',2)as$w)$j=$f($w,'+'.$c[$w],$j);foreach($g('IVXLCDM')as$w)$j=$f($w,'+'.$c[$w],$j);$k=eval('return '.$j.';');$l='';foreach($c as$a=>$b){while($k>=$b){$l.=$a;$k-=$b;}}print$l."\n";

ví dụ

$ php roman.php 'XCIX + I / L * D + IV' — test case
MIV                                     — 1004

$ php roman.php 'XXXII * LIX'           — 32 × 59
MDCCCLXXXVIII                           — 1888

0

Python - 446 byte

Điều này có thể được cải thiện đáng kể. Tôi cảm thấy mình phải thực hiện cú swing đầu tiên bằng Python. Nó làm 3 điều trên đường chuyền đầu tiên

  1. mã hóa số và toán tử
  2. đánh giá các con số và mở rộng bảng ký hiệu xđể bao gồm tất cả các kết hợp có thể gặp phải (ngay cả khi chúng không được sử dụng). Ví dụ, trong khi XIXđang được lexed, các giá trị một phần "X":10, "XI":11"XIX":19được bổ sung vào bảng biểu tượng
  3. chèn parens lồng nhau để thực thi đánh giá từ trái sang phải

Cuối cùng, nó gọi evalchuỗi gốc (ngoại trừ các parens được thêm vào) và cung cấp cho nó bảng biểu tượng.

Sau đó, tôi chỉ cần dán một giải pháp đã biết để chuyển đổi số nguyên sang Roman, vì tôi đã làm việc này đủ lâu rồi ... xin vui lòng cải thiện để tôi học được điều gì đó mới :)

m = zip ((1000.900.500.400,100,90,50,40,10,9,5,4,1),
('M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', ' TÔI'))
def doit (s):
 x = {'M': 1e3, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}; y = [] ; z = ''; a = '0'; s = '+' + s
 cho c trong s.upper ():
  nếu c trong x:
   z + = c; y.append (x [c])
   nếu len (y)> 1 và y [-1]> y [-2]: y [-2] * = - 1
   x [z] = tổng (y)
  elif c trong "+ / * -": a = '(' + a + z + ')' + c; y = []; z = ''
 a + = z; i = eval (a, x); r = ''
 với n, c tính bằng m: d = int (i / n); r + = c * d; i- = n * d
 trở lại r


in doit ("XIX + LXXX")
in doit ("XCIX + I / L * D + IV")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.