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?