Konwertuj na cyfrę rzymską!

13

Twoim zadaniem jest konwersja danej dodatniej liczby całkowitej z cyfr arabskich na rzymską.

Sprawa staje się trudna, gdy policzysz do 4000.

Romanie zrobili to, dodając linię powyżej symbolu, aby pomnożyć ten symbol 1 000. Jednak podkreślenia nie są dokładnie wyświetlane w ASCII. Istnieją również podwójne linie, aby pomnożyć symbol 1 000 000, a następnie trzy linie, aby pomnożyć symbol 1 000 000 000, itp ...

Dlatego postanowiłem użyć nawiasów, aby zastąpić podkreślenia.

Symbole można indywidualnie umieszczać w nawiasach. Na przykład, zarówno (VI)i (V)(I)są ważne reprezentacje 6 000. (V)Mjest również prawidłową reprezentacją 6000.

(I)jest prawidłowym sposobem reprezentacji 1 000.

Przypadki testowe

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

Punktacja

To jest . Najkrótszy kod w bajtach wygrywa.

Leaky Nun
źródło
1
Uzasadnienie, dlaczego nie jest to duplikat, zaśmieca specyfikację. Bez IMO byłoby lepiej.
Mego
Gdzie mam dodać uzasadnienie?
Leaky Nun
1
Zostaw to. Jeśli ktoś zastanawia się, czy jest to duplikat, należy omówić go w komentarzach lub na czacie.
Mego
@Mego Gotowe. :-)
Leaky Nun
Czy (IV)akceptowalna reprezentacja wynosi 4000?
Neil

Odpowiedzi:

9

Mathematica, 67 bajtów

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

Pozwala uniknąć kłopotów z Mkonwersją danych wejściowych na bazę 1000 i konwersją każdej cyfry osobno za pomocą RomanNumeral. Następnie składamy je, wkładając (...)od lewej.

Niestety Mathematica reprezentuje zera, Ndlatego musimy się ich pozbyć.

Martin Ender
źródło
1
darn mathematica z wbudowanymi funkcjami do wszystkiego> :(
OldBunny2800 17.04.16
1
@ OldBunny2800 Byłbym zaskoczony, gdyby to nie zostało pobite przez żaden z języków golfowych.
Martin Ender
@ OldBunny2800 I kosztuje to prawdziwe pieniądze. To źle.
Erik the Outgolfer
@ MartinBüttner Myślałem, że po prostu RomanNumeralmogę to zrobić?
Leaky Nun
1
Wyjścia @KennyLau To MMMMza 4000to tylko zacznie działać do specyfikacji w 5000(i wtedy masz ten sam problem dla 4000000etc.). Nawet wtedy używa overbarów zamiast nawiasów. Jeśli nie masz nic przeciwko, powinieneś to powiedzieć w specyfikacji wyzwania.
Martin Ender,
7

JavaScript (ES6), 136 bajtów

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

W przypadku liczb poniżej 4000 powtarza każdą rzymską „literę” tyle razy, ile to możliwe, używając listy rzymskich „liter” i ich wartości dziesiętnych. W przeciwnym razie rekurencyjnie buduje odpowiedź z dywizji i modulo z 1000. Na szczęście repeatobcina się, więc nie muszę tego robić sam.

Neil
źródło
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))))))

Nie golfił

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

Testy

Dwa testy dają inne wyniki niż te z pytania:

(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"))
rdzeń rdzeniowy
źródło
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=")")

To nie jest najlepsza opcja, ale myślę, że pomysł powinien być podobny do tego.

Tusz do rzęs
źródło
1

Python, 188 194

-6 bajtów od pozbycia się białych znaków

To wyzwanie przypomniało mi, kiedy uczyłem się programowania ...

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

To może nie być najkrótsze rozwiązanie, ale dobrze się bawiłem grając w ten problem.

Wypróbuj to!

Mr Public
źródło
1

Rubin, 137 134 130 bajtów

Funkcja rekurencyjna, która zwraca ciąg. Jeśli to możliwe, staram się zagrać w kodowanie numeryczne, ale nie jestem pewien, jak to zrobić.

Ups, to praktycznie bezpośredni port odpowiedzi ES6 @ Neila.

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]}"}
Wartość tuszu
źródło
1

Rubin, 185 161 144 bajtów

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

Wydaje mi się, że ponad rok po opublikowaniu postu nauczyłem się czegoś o golfie.

Dziękuję Value Ink za cenne komentarze.

MegaTom
źródło
gsubmoże przyjąć ciąg znaków jako pierwszy argument, eliminując potrzebę podstawienia do wzorca wyrażenia regularnego, ponieważ s.gsub! x,yrobi to automatycznie. Poza tym prawdopodobnie możesz po prostu zrezygnować z przypisania atablicy, ponieważ używasz jej tylko raz i umieszczasz bezpośrednio w each_slicewywołaniu.
Wartość tuszu
"IVXXLCCDM".scan(/(.)(.)(.)/){|x,b,c|...też działa
Value Ink
r[x]Jest również funkcjonalnie równoważny za r.(x)każdym razem, gdy w grę zaangażowane są mocne lambdy
Value Ink
@ValueInk dziękuję. Ta r[x]sztuczka przyda się w moim rekurencyjnym golfie w rubinach!
MegaTom,
1

TCL 134 bajty

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}

Wypróbuj tutaj: https://rextester.com/BJC92885

Chau Giang
źródło