สร้างเครื่องคิดเลขตัวเลข


18

สร้างเครื่องคิดเลขพื้นฐานสำหรับเลขโรมัน

ความต้องการ

  • รองรับ+, -, *,/
  • อินพุทและเอาท์พุทควรคาดหวังว่าจะมีเพียงหนึ่งคำนำหน้าตัวลบต่อสัญลักษณ์ (เช่น 3 ไม่สามารถเป็นIIVเพราะมีสองIก่อนหน้านี้V)
  • การจัดการของหลักการการลบในการป้อนข้อมูลและต้องส่งออกที่สนับสนุนขั้นต่ำการประชุมมาตรฐานทันสมัยซึ่งมีเพียงอำนาจของสิบจะถูกหักออกจากตัวเลขขนาดใหญ่ (เช่นI, X, Csubtractors จะต้อง แต่ไม่V, L, D) และการลบก็ไม่เคยทำได้จากจำนวนมากกว่า ลบ 10x (เช่นIXต้องได้รับการสนับสนุน แต่ICไม่จำเป็น)
  • อินพุตและเอาต์พุตควรจากซ้ายไปขวาตามลำดับของค่าเริ่มต้นด้วยค่าที่ใหญ่ที่สุด (เช่น 19 = XIXไม่IXX, 10 มีค่ามากกว่า 9)
  • จากซ้ายไปขวาไม่มีความสำคัญของโอเปอเรเตอร์ราวกับว่าคุณกำลังใช้เครื่องคิดเลขมือ
  • รองรับทั้งตัวเลขบวกเข้า / ออกระหว่าง 1-4999 (ไม่จำเป็นต้องV̅)
  • ไม่มีห้องสมุดที่แปลงเลขโรมันให้คุณ

เพื่อให้คุณตัดสินใจ

  • กรณีที่ไว
  • ช่องว่างหรือไม่มีช่องว่างในอินพุต
  • จะเกิดอะไรขึ้นถ้าคุณได้รับผลลัพธ์ทศนิยม ตัดทอนไม่มีคำตอบข้อผิดพลาด ฯลฯ
  • สิ่งที่ต้องทำสำหรับเอาต์พุตที่คุณไม่สามารถจัดการได้ จำนวนลบหรือจำนวนถึงมากที่จะพิมพ์
  • สนับสนุนการใช้หลักการลบอย่างเสรีมากกว่าข้อกำหนดขั้นต่ำหรือไม่

สินเชื่อพิเศษ

  • -50 - จัดการได้ถึง 99999 หรือมากกว่า สัญลักษณ์จะต้องมีvinculum

ตัวอย่างอินพุต / เอาต์พุต

XIX + LXXX                 (19+80)
XCIX

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

รหัสที่สั้นที่สุดชนะ


(99 + 1/50 * 500 + 4) = (99 + 10 + 4) = 113 แต่อินพุต / เอาต์พุตตัวอย่างของคุณระบุว่าเป็น MIV (1004)
Victor Stafusa

1
@Victor - การดำเนินการจากซ้ายไปขวาอย่างเข้มงวด - ไม่มีกฎมาก่อน - ดังนั้นควรคำนวณ 99 +

การจัดการตัวเลขเป็นIM = 999สิ่งจำเป็นหรือไม่?
Kendall Frey

@KendallFrey ฉันคาดว่าคุณสามารถป้อนข้อมูลIMได้ ไม่ว่าจะเป็นผลผลิตIMหรือCMXCIX999 ขึ้นอยู่กับคุณ ทั้งพอดีกับความต้องการ
แดนนี่

2
IM นั้นไม่ใช่มาตรฐานสำหรับการใช้ตัวเลขโรมันสมัยใหม่ โดยปกติแล้วจะเป็นเพียง 4s และ 9 ของลำดับแต่ละขนาด (4, 9, 40, 90, 400, 900, ฯลฯ ) ซึ่งทำโดยการลบ สำหรับปี 1999 MCMXCIX จะเป็นที่ยอมรับไม่ใช่ MIM ... ดูเครดิตของภาพยนตร์ทุกเรื่องจากปีนั้น ไม่งั้นมันจะจบที่ไหน? เราคาดว่าจะสนับสนุนการลบที่ไม่ได้มาตรฐานเช่น VL สำหรับ 45 หรือไม่? IC ที่มี vinculum มากกว่า C ต้องได้รับการสนับสนุนเป็น 99999 สำหรับโบนัสหรือไม่
Jonathan Van Matre

คำตอบ:


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}

การใช้งาน:

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

รุ่นข้อเขียน:

/**
 * 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 ไบต์

ฉันรู้ว่าการเล่นกอล์ฟใน SQL นั้นเทียบเท่ากับการเล่น 18 หลุมโดยไม่มีอะไรเลยนอกจากลิ่มทราย แต่ฉันได้ลองท้าทายสิ่งนี้และฉันคิดว่าฉันสามารถทำสิ่งที่น่าสนใจได้หลายวิธี

สิ่งนี้จะสนับสนุน vinculum สำหรับทั้งอินพุตและเอาต์พุต ฉันยอมรับการประชุมโดยใช้เครื่องหมายตัวหนอนเพื่อเป็นตัวแทนดังนั้น V ~ คือ 5,000, X ~ คือ 10,000 เป็นต้นและควรจัดการเอาต์พุตได้สูงถึง 399,999 ตามการใช้ตัวเลขโรมันแบบมาตรฐาน หลังจากนั้นจะทำการเข้ารหัสแบบโรมันที่ไม่ได้มาตรฐานบางส่วนของสิ่งใดก็ตามในช่วงที่ได้รับการสนับสนุนของ INT

เนื่องจากเป็นเลขจำนวนเต็มทั้งหมดผลลัพธ์ที่ไม่เป็นจำนวนเต็มจะถูกปัดเศษโดยปริยาย

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

ฉันยังคงแก้ปัญหาด้วย set-based solution เพื่อแทนที่การวนลูปบางอันที่อาจลดจำนวนไบต์ลงและเป็นตัวอย่างที่ดีกว่าของ SQL ที่ใช้สำนวน นอกจากนี้ยังมีบางไบต์ที่จะได้รับโดยการลดการใช้นามแฝงของตารางให้น้อยที่สุด แต่เนื่องจากภาษานี้ไม่สามารถเอาชนะได้ฉันจึงมาที่นี่เพื่อแสดงชุด Don Quixote ของฉัน :)

SELECT @i ที่ด้านบนป้อนข้อมูลซ้ำ:

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

และ SELECT เมื่อสิ้นสุดจะส่งคืน:

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

และคุณสามารถทดสอบด้วยตัวเองได้ที่SQLFiddle นี้

และฉันจะกลับไปเพิ่มความเห็นเกี่ยวกับวิธีการทำงานเพราะเหตุใดจึงโพสต์คำตอบที่หายไปอย่างเห็นได้ชัดถ้าคุณไม่ใช้ประโยชน์จากคุณค่าทางการศึกษา?


2

Javascript - 482 476 ตัวอักษร

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))))

ตัวอย่างอินพุต / เอาต์พุตทำงาน:

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

มันจัดการกับตัวเลขจำนวนมากได้ไม่ดีเช่นกัน:

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

และมันก็ยอมรับ แต่ไม่ต้องการช่องว่างด้วย

แต่เนื่องจากฉันเล่นกอล์ฟจึงมีปัญหา:

  • มันจะไม่ตรวจสอบหากอินพุตมีรูปแบบที่ถูกต้อง หากอินพุตไม่ได้อยู่ในรูปแบบที่ดีพฤติกรรมจะไม่ได้กำหนด (และในทางปฏิบัติมันแปลกมากและแปลก)
  • มันตัดทอนหมายเลขเศษส่วนบนเอาต์พุต (แต่สามารถทำการคำนวณระดับกลางกับพวกมันได้)
  • มันใช้ฟังก์ชัน eval อย่างไม่เหมาะสม
  • มันไม่ได้พยายามจัดการกับจำนวนลบ
  • มันเป็นกรณี ๆ ไป

รุ่นทางเลือกนี้จัดการกับตัวเลขที่มากกว่า 5,000 ถึง 99999 แต่มี600 598 584 ตัวอักษร:

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))))

ฉันไม่คิดว่าจะใช้ -20: ดูvinculum
SeanC

เห็นด้วยกับ @SeanCheshire ที่นี่ สำหรับการจัดการจำนวนที่มากขึ้นความตั้งใจคือการเพิ่มvinculumเหนือตัวเลขให้เป็น 1,000 เท่าของมูลค่าของมันตามปกติ บางทีมันควรจะใหญ่กว่า -20 ดังนั้นมันจึงคุ้มค่าที่จะลองกับคนอื่น
แดนนี่

1
@ Danny ฉันเพิ่มเวอร์ชันที่จัดการกับ vinculus แต่เพิ่มรหัสเป็น 116 ตัวอักษร
Victor Stafusa

2

Javascript 479 361 348 278 253

303 ตัวอักษร - 50 สำหรับรองรับตัวเลขสูงถึง 1 ล้านพร้อมด้วยการรองรับ 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

การใช้งาน: p(text)เช่นผลตอบแทนp('XIX + LXXX')XCIX

รหัสที่มีความคิดเห็นอธิบาย:

// 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;
}

สิ่งนี้ใช้ได้กับตัวอย่างที่ให้มาและสำหรับคนอื่น ๆ ที่ฉันได้ลองแล้ว ตัวอย่าง:

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

ทับทิม 2.1, 353 (และหลายซ้ำอื่น ๆ ) , 295-50 = 245

การจัดการ vinculum เพิ่ม ~ 23 ตัวอักษร

สิ่งนี้จัดการ "IL" หรือ "VM" ในอินพุตและล้มเหลวโดยไม่มีข้อผิดพลาดเกี่ยวกับเนกาทีฟ (ไปที่ ints สูง) หรือทศนิยม (ตัด) หรือช่องว่างใด ๆ ตอนนี้ยังจัดการหมายเลขแรกที่เป็นลบ (แม้ว่าจำนวนทั้งหมดจะเป็นลบ แต่ก็ยังไม่ดีพอ) นอกจากนี้ยังล้มเหลวได้ไม่ดีหากคุณเริ่มต้นด้วย * หรือ / หรือถ้าผลลัพธ์นั้นมี 4 ล้านหรือใหญ่กว่า

ใช้ Object # ส่งสำหรับฟังก์ชั่น "เครื่องคิดเลขมือ"

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))}

Ungolfed:

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 ตัวอักษร

อ่านจากอินพุตมาตรฐาน รองรับเฉพาะตัวพิมพ์ใหญ่เท่านั้น (อาจทำให้ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่เสียค่าใช้จ่าย 8 อักขระพิเศษ) และต้องใช้ช่องว่าง ไม่มีการตรวจสอบ - ฉันไม่ได้ทดสอบเพื่อดูว่ามันแตกในหลายกรณี อย่างไรก็ตามมันจัดการกับตัวเลขเช่น 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

และเวอร์ชั่นที่ไม่ดีขึ้น:

# 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

ฉันมีความรู้สึก Perl คงจะดีกว่านี้ แต่ฉันก็ไม่รู้พอ สำหรับการแทงครั้งแรกที่รหัสกอล์ฟฉันรู้สึกดีกับเรื่องนี้มาก


1

PHP - 549 525 524 520 ไบต์

ไม่มีอะไรที่สร้างสรรค์เกินไป: ทำให้ตัวดำเนินการเป็นปกติเพื่อให้มั่นใจว่าจากซ้ายไปขวานำหน้าการแปลง Roman เป็นทศนิยมเรียกใช้evalบนคำสั่งเช่นXCIX + I / L * D + IVถูกแปลงเป็นผลตอบแทนเช่น(((((+90 +9)) + (+1)) / (+50)) * (+500)) + (+4)); จากนั้นแปลงทศนิยมกลับเป็นโรมัน

  • ผลลัพธ์สุดท้ายจะถูกปัดเศษ
  • คำตอบน้อยกว่า 1 กลับมาว่างเปล่า
  • ผลลัพธ์ไม่ถูกกำหนดหากได้รับอินพุตที่ไม่ถูกต้อง
$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";

เช่น

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

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

0

Python - 446 ไบต์

สิ่งนี้สามารถปรับปรุงได้อย่างมาก ฉันรู้สึกว่าฉันต้องสวิงครั้งแรกโดยใช้ Python มันทำ 3 สิ่งในรอบแรก

  1. โทเค็นตัวเลขและตัวดำเนินการ
  2. ประเมินตัวเลขและขยายตารางสัญลักษณ์xเพื่อรวมชุดค่าผสมที่เป็นไปได้ทั้งหมดที่พบ (แม้ว่าจะไม่ได้ใช้) ตัวอย่างเช่นในขณะXIXนี้จะถูก lexed ค่าบางส่วน"X":10, "XI":11และ"XIX":19จะมีการเพิ่มตารางสัญลักษณ์
  3. แทรก parens ที่ซ้อนกันเพื่อบังคับใช้การประเมินผลจากซ้ายไปขวา

ในตอนท้ายมันจะเรียกevalสตริงเดิม (ยกเว้นด้วย parens เพิ่ม) และให้มันตารางสัญลักษณ์

จากนั้นฉันเพิ่งวางโซลูชั่นที่รู้จักกันในการแปลงจำนวนเต็มเป็นโรมันเนื่องจากฉันทำงานมานานพอแล้ว ... โปรดอย่าลังเลที่จะปรับปรุงเพื่อที่ฉันจะได้เรียนรู้สิ่งใหม่ :)

m = ซิป ((1000,900,500,400,100,90,50,40,10,9,5,4,1)
( 'M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'ทรงเครื่อง', 'V', 'IV',' ผม'))
def doit (s):
 x = {M: 1e3, 'D': 500, 'C' 100 'L': 50 'X': 10 'V': 5 '' ฉัน': 1}; Y = [] ; Z = ''; A = '0'; s = '+' + s
 สำหรับ c ใน s.upper ():
  ถ้า c ใน x:
   Z + c =; y.append (x [C])
   ถ้า len (y)> 1 และ y [-1]> y [-2]: y [-2] * = - 1
   x [Z] = SUM (y)
  elif c ใน "+ / * -": a = '(' + a + z + ')' + c; y = []; z = ''
 a + = z; i = eval (a, x); r = ''
 สำหรับ n, c ใน m: d = int (i / n); r + = c * d; i- = n * d
 ส่งคืน r


พิมพ์ doit ("XIX + LXXX")
print doit ("XCIX + I / L * D + IV")
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.