Converti in numero romano!


13

Il tuo compito è convertire un dato intero positivo dal numero arabo al numero romano.

Le cose diventano difficili quando conti fino a 4000.

I romani lo fecero aggiungendo una linea sopra un simbolo per moltiplicare quel simbolo 1 000. Tuttavia, gli overline non sono esattamente visualizzabili in ASCII. Inoltre, ci sono doppie linee di sovrapposizione per moltiplicare un simbolo 1 000 000, quindi triplicare la linea per moltiplicare un simbolo per 1 000 000 000, ecc.

Pertanto, ho deciso di utilizzare le parentesi per sostituire gli overline.

I simboli possono essere posizionati singolarmente tra parentesi. Ad esempio, entrambi (VI)e (V)(I)sono rappresentazioni valide di 6 000. (V)Mè anche una rappresentazione valida di 6000.

(I)è un modo valido per rappresentare 1 000.

Casi test

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

punteggio

Questo è . Il codice più corto in byte vince.


1
La giustificazione del perché questo non è un duplicato ingombra le specifiche. Sarebbe meglio senza di essa IMO.
Mego,

Dove aggiungerei la giustificazione?
Leaky Nun,

1
Lascialo fuori. Se qualcuno si domanda se si tratta di un duplicato o meno, fai una discussione nei commenti o in chat.
Mego,

@Mego Fatto. :-)
Leaky Nun,

È (IV)una rappresentazione accettabile del 4000?
Neil,

Risposte:


9

Mathematica, 67 byte

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

Evita tutti i problemi Mconvertendo l'input in base 1000 e convertendo ogni cifra separatamente con RomanNumeral. Quindi li pieghiamo inserendoli (...)da sinistra.

Sfortunatamente, Mathematica rappresenta gli zeri, Nquindi dobbiamo liberarcene.


1
maledettamente matematica con i suoi builtin per tutto> :(
OldBunny2800

1
@ OldBunny2800 Sarei sorpreso se comunque non fosse battuto da nessuna delle lingue del golf.
Martin Ender,

@ OldBunny2800 E costa soldi veri per ottenerlo. Questo è male.
Erik the Outgolfer,

@ MartinBüttner pensavo che semplicemente RomanNumeralpotesse farlo?
Leaky Nun,

1
@KennyLau Emette MMMMper 4000, inizia a funzionare solo su spec in 5000(e quindi ottieni lo stesso problema per 4000000ecc.). Anche in questo caso, utilizza barre sovrapposte anziché parentesi. Se stai bene, dovresti dirlo nella specifica della sfida.
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)

Per i numeri inferiori a 4000, ripete ogni "lettera" romana il più volte possibile, usando l'elenco delle "lettere" romane e i loro valori decimali. Altrimenti costruisce ricorsivamente la risposta della divisione e del modulo con 1000. Fortunatamente si repeattronca, quindi non devo farlo da solo.


3

Lisp comune, 108

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

Ungolfed

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

test

Due test danno risultati diversi rispetto a quelli della domanda:

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

Praticamente non è l'opzione migliore, ma penso che l'idea dovrebbe essere abbastanza simile a questa.


1

Python, 188 194

-6 byte dall'eliminazione di alcuni spazi bianchi

Questa sfida mi ha riportato a quando stavo imparando a programmare per la prima volta ...

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

Potrebbe non essere la soluzione più breve, ma mi sono divertito a giocare a golf con questo problema.

Provalo!


1

Rubino, 137 134 130 byte

Funzione ricorsiva che restituisce la stringa. Sto provando a golfare le codifiche numeriche un po 'di più, se possibile, ma non sono sicuro di come.

Spiacenti, è praticamente un porto diretto della risposta ES6 di @ Neil ora.

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

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

Più di un anno dopo il post originale, penso di aver imparato qualcosa sul golf.

Grazie Value Ink per i tuoi preziosi commenti.


gsubpuò prendere una stringa come primo argomento, rimuovendo la necessità di sostituzioni in un modello regex poiché lo s.gsub! x,yfa automaticamente. A parte questo, probabilmente puoi semplicemente rinunciare all'assegnazione adell'array poiché lo usi solo una volta e lo metti direttamente nella each_slicechiamata.
Value Ink

"IVXXLCCDM".scan(/(.)(.)(.)/){|x,b,c|...funziona anche
Value Ink

Inoltre r[x]è funzionalmente equivalente a r.(x)quando sono coinvolti stabby lambdas
Value Ink

@ValueInk grazie. Questo r[x]trucco sarà utile per tutto il mio golf ricorsivo più intenso in rubino!
MegaTom,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.