Konversi ke Angka Romawi!

13

Tugas Anda adalah mengubah bilangan bulat positif yang diberikan dari angka Arab ke angka Romawi.

Segala sesuatunya menjadi sulit ketika Anda menghitung sampai 4000.

Orang Romawi melakukan ini dengan menambahkan garis di atas simbol untuk melipatgandakan simbol itu 1 000. Namun, overline tidak dapat ditampilkan di ASCII. Juga, ada garis ganda untuk menggandakan simbol 1 000 000, dan kemudian garis ganda tiga kali lipat dengan simbol 1 000 000 000, dll ...

Oleh karena itu, saya memutuskan untuk menggunakan tanda kurung untuk mengganti overline.

Simbol dapat ditempatkan secara individual dalam tanda kurung. Misalnya, keduanya (VI)dan (V)(I)merupakan representasi valid dari 6 000. (V)Mjuga merupakan representasi valid dari 6000.

(I)adalah cara yang valid untuk mewakili 1 000.

Testcases

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

Mencetak gol

Ini adalah . Kode terpendek dalam byte menang.

Biarawati Bocor
sumber
1
Pembenaran untuk mengapa ini bukan duplikat mengacaukan spesifikasi. Akan lebih baik tanpanya IMO.
Mego
Di mana saya akan menambahkan justifikasi?
Leaky Nun
1
Biarkan saja. Jika seseorang mempertanyakan apakah itu duplikat atau tidak, lakukan diskusi dalam komentar atau dalam obrolan.
Mego
@Mego Done. :-)
Leaky Nun
Apakah (IV)representasi 4000 dapat diterima?
Neil

Jawaban:

9

Mathematica, 67 byte

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

Hindari semua masalah dengan Mmengubah input ke basis 1000 dan mengonversi setiap digit secara terpisah RomanNumeral. Lalu kami melipatnya dengan memasukkan (...)dari kiri.

Sayangnya, Mathematica mewakili angka nol Nsehingga kita harus menyingkirkannya.

Martin Ender
sumber
1
darn Mathematica dengan bawaannya untuk semuanya> :(
OldBunny2800
1
@ OldBunny2800 Saya akan terkejut jika ini tidak dikalahkan oleh bahasa golf.
Martin Ender
@ OldBunny2800 Dan butuh uang sungguhan untuk mendapatkannya. Itu buruk.
Erik the Outgolfer
@ MartinBüttner saya pikir RomanNumeralbisa melakukannya?
Leaky Nun
1
@ KennyLau Ini keluaran MMMMuntuk 4000, itu hanya mulai bekerja untuk spec di 5000(dan kemudian Anda mendapatkan masalah yang sama untuk 4000000dll). Bahkan kemudian, ia menggunakan overbars alih-alih tanda kurung. Jika Anda setuju dengan itu, Anda harus mengatakannya dalam spesifikasi tantangan.
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)

Untuk angka di bawah 4000, ulangi setiap "huruf" Romawi sebanyak mungkin, menggunakan daftar "huruf" Romawi dan nilai desimalnya. Kalau tidak, secara rekursif membangun jawaban dari divisi dan modulo dengan 1000. Untungnya repeatmemotong jadi saya tidak harus melakukannya sendiri.

Neil
sumber
3

Common Lisp, 108

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

Tidak disatukan

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

Tes

Dua tes memberikan output yang berbeda dari yang dari pertanyaan:

(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"))
coredump
sumber
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=")")

Ini bukan pilihan terbaik, tapi saya pikir idenya harus mirip dengan ini.

Masclins
sumber
1

Python, 188 194

-6 byte dari menghilangkan spasi

Tantangan ini membawa saya kembali ke ketika saya pertama kali belajar memprogram ...

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

Mungkin bukan solusi terpendek, tapi saya senang bermain golf masalah ini.

Cobalah!

Tuan Umum
sumber
1

Ruby, 137 134 130 byte

Fungsi rekursif yang mengembalikan string. Saya mencoba bermain golf di penyandian angka sedikit lebih jika mungkin, tapi saya tidak yakin bagaimana.

Aduh, ini praktis merupakan port langsung jawaban ES6 @ Neil sekarang.

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]}"}
Nilai Tinta
sumber
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)}

Lebih dari setahun setelah posting asli, saya pikir saya belajar sesuatu tentang golf.

Terima kasih, Nilai Tinta untuk komentar Anda yang berharga.

MegaTom
sumber
gsubdapat mengambil string sebagai argumen pertama, menghapus kebutuhan substitusi ke dalam pola regex sejak s.gsub! x,ydilakukan secara otomatis. Selain itu, Anda mungkin bisa mengabaikan penugasan aarray Anda karena Anda hanya menggunakannya sekali, dan langsung memasukkannya ke dalam each_slicepanggilan.
Value Ink
"IVXXLCCDM".scan(/(.)(.)(.)/){|x,b,c|...berfungsi juga
Value Ink
Juga r[x]secara fungsional setara dengan r.(x)setiap kali lambdas yang terlibat
Value Ink
@ ValueInk terima kasih. Itu r[x]trik akan berguna untuk semua futer saya golf rekursif di ruby!
MegaTom
1

TCL 134 byte

proc f r {
set map {M 1000+ CM 900+ D 500+ CD 400+ C 100+ XC 90+ L 50+ XL 40+ X 10+ IX 9+ V 5+ IV 4+ I 1+}
expr [string map $map $r]0}

Cobalah di sini: https://rextester.com/BJC92885

chau giang
sumber