Chuyển đổi sang số La Mã!


13

Nhiệm vụ của bạn là chuyển đổi một số nguyên dương cho trước từ chữ số Ả Rập sang chữ số La Mã.

Mọi thứ trở nên khó khăn khi bạn đếm đến 4000.

Những người lãng mạn đã làm điều này bằng cách thêm một dòng phía trên một biểu tượng để nhân biểu tượng đó với 1 000. Tuy nhiên, các đường viền không thể hiển thị chính xác trong ASCII. Ngoài ra, có các đường viền đôi để nhân một biểu tượng theo 1 000 000, và sau đó nhân ba đường thẳng để nhân một biểu tượng với 1 000 000 000, v.v ...

Do đó, tôi quyết định sử dụng dấu ngoặc đơn để thay thế đường viền.

Các biểu tượng có thể được đặt riêng trong ngoặc đơn. Ví dụ, cả hai (VI)(V)(I)là đại diện hợp lệ của 6 000. (V)Mcũng là một đại diện hợp lệ của 6000.

(I)là một cách hợp lệ để đại diện 1 000.

Tủ thử

Input: 1
Output: I
Input: 2
Output: II
Input: 3
Output: III
Input: 4
Output: IV
Input: 15
Output: XV
Input: 40
Output: XL
Input: 60
Output: LX
Input: 67
Output: LXVII
Input: 400
Output: CD
Input: 666
Output: DCLXVI
Input: 3000
Output: MMM
Input: 3999
Output: MMMCMXCIX
Input: 4000
Output: M(V)
Input: 4999
Output: M(V)CMXCIX
Input: 6000
Output: (VI)
Input: 6000000
Output: ((VI))
Input: 6006000
Output: ((VI)VI)
Input: 6666666666
Output: (((VI)DCLXVI)DCLXVI)DCLXVI

Chấm điểm

Đây là . Mã ngắn nhất trong byte thắng.


1
Sự biện minh cho lý do tại sao đây không phải là một bản sao trùng lặp thông số kỹ thuật. Nó sẽ tốt hơn nếu không có nó IMO.
Mego

Tôi sẽ thêm lời biện minh ở đâu?
Leaky Nun

1
Để nó ra. Nếu ai đó thắc mắc liệu nó có phải là một bản sao hay không, hãy thảo luận trong các bình luận hoặc trong trò chuyện.
Mego

@Mego Xong. :-)
Leaky Nun

(IV)một đại diện chấp nhận được của 4000?
Neil

Câu trả lời:


9

Toán học, 67 byte

Fold["("<>#<>")"<>#2&,RomanNumeral[#~IntegerDigits~1000]/."N"->""]&

Tránh mọi rắc rối bằng Mcách chuyển đổi đầu vào thành cơ sở 1000 và chuyển đổi từng chữ số riêng biệt với RomanNumeral. Sau đó, chúng tôi gấp chúng lên bằng cách chèn (...)từ bên trái.

Thật không may, Mathematica đại diện cho số không vì Nvậy chúng ta cần loại bỏ chúng.


1
nhà toán học darn với các nội trang của nó cho mọi thứ> :(
OldBunny2800

1
@ OldBunny2800 Tôi sẽ rất ngạc nhiên nếu điều này không bị đánh bại bởi bất kỳ ngôn ngữ chơi gôn nào.
Martin Ender

@ OldBunny2800 Và phải trả tiền thật để có được nó. Thật tồi tệ.
Erik the Outgolfer

@ MartinBüttner Tôi nghĩ đơn giản là RomanNumeralcó thể làm được?
Leaky Nun

1
@KennyLau Nó ra MMMMcho 4000, nó chỉ bắt đầu làm việc để spec tại 5000(và sau đó bạn nhận được cùng một vấn đề cho 4000000vv). Thậm chí sau đó, nó sử dụng overbars thay vì dấu ngoặc đơn. Nếu bạn ổn với điều đó, bạn nên nói như vậy trong đặc tả thử thách.
Martin Ender

7

JavaScript (ES6), 136 byte

f=n=>n<4e3?"M1000CM900D500CD400C100XC90L50XL40X10IX9V5IV4I1".replace(/(\D+)(\d+)/g,(_,r,d)=>r.repeat(n/d,n%=d)):`(${f(n/1e3)})`+f(n%1e3)

Đối với các số dưới 4000, lặp lại mỗi "chữ cái" La Mã càng nhiều lần càng tốt, sử dụng danh sách "chữ cái" La Mã và các giá trị thập phân của chúng. Mặt khác, đệ quy xây dựng câu trả lời từ phép chia và modulo với 1000. May mắn là repeatcắt ngắn để tôi không phải tự làm điều đó.


3

Lisp thường gặp, 108

(defun p(n)(if(> n 0)(if(< n 4000)(format()"~@R"n)(format()"(~A)~@[~A~]"(p(floor n 1000))(p(mod n 1000))))))

Ung dung

(defun p(n)
  (if (> n 0)
      (if (< n 4000)

          ;; Built-in Roman formatter (between 1 and 3999)
          (format () "~@R" n)

          ;; Divide N by 1000, as 1000*Q + R.
          ;; First print (p Q) in parentheses (recursively)
          ;; Then, if it is not NIL, the remainder R.
          (format () "(~A)~@[~A~]"
                  (p (floor n 1000))
                  (p (mod n 1000))))))

Xét nghiệm

Hai bài kiểm tra cho kết quả đầu ra khác với kết quả từ câu hỏi:

(loop for (in out) in '((1 "I")
                        (2 "II")
                        (3 "III")
                        (4 "IV")
                        (15 "XV")
                        (40 "XL")
                        (60 "LX")
                        (67 "LXVII")
                        (400 "CD")
                        (666 "DCLXVI")
                        (3000 "MMM")
                        (3999 "MMMCMXCIX")
                        (4000 "M(V)")
                        (4999 "M(V)CMXCIX")
                        (6000 "(VI)")
                        (6000000 "((VI))")
                        (6006000 "((VI)VI)")
                        (6666666666 "(((VI)DCLXVI)DCLXVI)DCLXVI"))
   for computed = (p in)
   unless (string= out computed)
   collect (list in out computed))

=> ((4000 "M(V)" "(IV)")
    (4999 "M(V)CMXCIX" "(IV)CMXCIX"))

2

R, 134

m=1000;x=scan();while(x[1]>=m)x=c(floor(x[1]/m),x[1]%%m,x[-1]);cat(rep("(",length(x)),sep="");cat(as.character(as.roman(x)),sep=")")

Đó không phải là lựa chọn tốt nhất, nhưng tôi nghĩ ý tưởng này khá giống với điều này.


1

Con trăn, 188 194

-6 byte thoát khỏi một số khoảng trắng

Thử thách này đã đưa tôi trở lại khi lần đầu tiên học lập trình ...

def f(x,s=zip("M CM D CD C XC L XL X IX V IV I".split(),[1e3,900,500,400,100,90,50,40,10,9,5,4,1])):
 r=""if x<4e3else"("+f(x/1e3)+")";x%=1e3
 for a,b in s:
    while x>=b:r+=a;x-=b
 return r

Nó có thể không phải là giải pháp ngắn nhất, nhưng tôi rất vui khi chơi golf vấn đề này.

Hãy thử nó!


1

Ruby, 137 134 130 byte

Hàm đệ quy trả về chuỗi. Tôi đang cố gắng đánh golf mã hóa số một chút nữa nếu có thể, nhưng tôi không biết làm thế nào.

Rất tiếc, thực tế đây là một cổng trực tiếp trả lời ES6 của @ Neil.

f=->x{(x<t=1e3)?"CM900D500CD400C100XC90L50XL40X10IX9V5IV4I1".gsub(/(\D+)(\d+)/){v=$2.to_i;s=x/v;x%=v;$1*s}:"(#{f[x/t]})#{f[x%t]}"}

1

Ruby, 185 161 144 byte

r=->i{i>(t=1e3)? "(#{r[i/t]})"+r[i%t]:(s=?I*i;"IVXXLCCDM".scan(/(.)(.)(.)/){|x,y,z|{x*5=>y,x*4=>x+y,y*2=>z,y+x+y=>x+z}.map{|x,y|s.gsub!x,y}};s)}

Hơn một năm sau bài viết gốc, tôi nghĩ rằng tôi đã học được điều gì đó về việc chơi golf.

Cảm ơn bạn Ink Ink cho ý kiến ​​có giá trị của bạn.


gsubcó thể lấy một chuỗi làm đối số đầu tiên, loại bỏ sự cần thiết phải thay thế thành một mẫu biểu thức chính vì s.gsub! x,ynó tự động. Ngoài ra, bạn có thể chỉ cần từ bỏ việc gán amảng của mình vì bạn chỉ sử dụng nó một lần và đặt nó trực tiếp vào each_slicecuộc gọi.
Mực giá trị

"IVXXLCCDM".scan(/(.)(.)(.)/){|x,b,c|...cũng hoạt động
Ink Ink

Cũng r[x]có chức năng tương đương với r.(x)bất cứ khi nào lambdas đâm liên quan
Value Ink

@ValueInk cảm ơn bạn. r[x]Thủ thuật đó sẽ hữu ích cho tất cả các môn đánh gôn đệ quy của tôi trong ruby!
MegaTom

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.