Diese gierigen Römer!

30

Bei einer streng positiven Ganzzahl geben Sie die kürzestmögliche römische Zahl nur mit der additiven Regel zurück. Die Ausgabe muss aus null oder mehr Zeichen MDCLXVIin dieser Reihenfolge bestehen. Die Nummer 14muss also XIIIIeher geben als XIV.

Die numerischen Werte der Zeichen sind M= 1000, D= 500, C= 100, L= 50, X= 10, V= 5, I= 1.

Beispiele

3III

4 → IIII

9VIIII

42XXXXII

796DCCLXXXXVI

2017MMXVII

16807MMMMMMMMMMMMMMMMDCCCVII

Adam
quelle
1
Du bist ein gütiger Fragesteller zu ermöglichen , 4 -> IIIIist 9 -> VIIIIauch statt IX?
Magic Octopus Urn
1
Siehe auch
@MagicOctopusUrn VIIIIist die einzig erlaubte Ausgabe für 9.
Adám
@ Adám hat nur darauf hingewiesen, dass Sie dies auch als Beispiel hinzufügen möchten, da die Regeln für 4 und 9 identisch sind.
Magic Octopus Urn
1
Related
Arnauld

Antworten:

12

Plain English , 1059 1025 678 641 451 399 Bytes

34 Byte durch Entfernen einer Fehlerfalle eingespart. Dann werden 384 Bytes durch Golfen eingespart. Dann werden 190 Bytes gespart, indem die Divisionsoperation mit der Anfügungsoperation ("z") zu einer neuen Operation ("p") kombiniert wird. Dann wurden durch Golfen 52 Bytes gespart.

A s is a string.
To p a r remainder a s a x string a n number:
If the x is "", exit.
Divide the r by the n giving a q quotient and the r.
Fill a t s with the x's first's target given the q.
Append the t to the s.
To convert a r number to a s:
p the r the s "M" 1000.
p the r the s "D" 500.
p the r the s "C" 100.
p the r the s "L" 50.
p the r the s "X" 10.
p the r the s "V" 5.
p the r the s "I" 1.

Hier ist die unbenutzte Version des endgültigen Codes sowie eine Fehlerfalle für eine negative Zahl:

A roman numeral is a string.

To process a remainder given a roman numeral and a letter string is a number:
  If the letter is "", exit.
  Divide the remainder by the number giving a quotient and the remainder.
  Fill a temp string with the letter's first's target given the quotient.
  Append the temp string to the roman numeral.

To convert a number to a roman numeral:
  If the number is negative, exit.
  Put the number in a remainder.
  Process the remainder given the roman numeral and "M" is 1000.
  Process the remainder given the roman numeral and "D" is  500.
  Process the remainder given the roman numeral and "C" is  100.
  Process the remainder given the roman numeral and "L" is   50.
  Process the remainder given the roman numeral and "X" is   10.
  Process the remainder given the roman numeral and "V" is    5.
  Process the remainder given the roman numeral and "I" is    1.
Jaspis
quelle
10
Warten Sie, ist dies eine Programmiersprache?
Adám
3
@Adam - Ja. Plain English kompiliert und läuft und alles. Der Quellcode und die IDE stehen unter github.com/Folds/english
Jasper zur Verfügung
1
Spielen Sie Golf - schließlich ist dies Codegolf und kein Sprachschaufenster.
Sanchises
2
Das ist also die Sprache, die Sie verwenden, wenn Sie nicht möchten, dass Ihr Job ausgelagert wird.
CorsiKa
@ corsiKa - LOL! Nur wenn genug von uns anfangen, es zu verwenden (und es zu seinen Bibliotheken hinzuzufügen), erreicht es eine kritische Masse.
Jasper
5

APL (Dyalog) , 25 22 Bytes

'MDCLXVI'/⍨(0,62 5)∘⊤

Probieren Sie es online!

TwiNight
quelle
Schön und im Grunde die Lösung, die ich mir vorgestellt hatte. Sie können jedoch replicate ( /) anstelle von reshape ( ) verwenden, um die Verkettungsreduktion ( ¨und ,/) auszuschneiden .
Am
Sie können auch in tradfn body konvertieren und Eingaben ( ) nehmen und commute ( ) verwenden, um die Parens zu entfernen und zu komponieren ( ).
Adám
Danke, aber was meinst du mit deinem zweiten Kommentar? Ich kann mir keine Möglichkeit
vorstellen
1
Das wäre ein Schnipsel, wenn Sie nicht die {}oder ∇f∇um die Funktion
herum
5

Retina , 57-42 Bytes

Konvertiert zu Unary und ersetzt gierig Bündel von Is durch die höheren Konfessionen in der angegebenen Reihenfolge.

.*
$*I
I{5}
V
VV
X
X{5}
L
LL
C
C{5}
D
DD
M

Probieren Sie es online aus

Dank Martin 15 Bytes gespart

mbomb007
quelle
Das ist sehr schlau.
Adám
7
Umgekehrt ist es
Martin Ender
Könnten Sie keine unären Eingaben Ials Einheit verwenden?
Adám,
2
@ Adám Angesichts der Tatsache, dass Retina jetzt ganzzahlige Eingaben problemlos verarbeiten kann, halte ich das für recht billig.
mbomb007
5

Python 2 , 64 Bytes

f=lambda n,d=5,r='IVXLCD':r and f(n/d,7-d,r[1:])+n%d*r[0]or'M'*n

Probieren Sie es online!

Anstatt die Ausgabezeichenfolge von Anfang an zu erstellen, indem der größte Teil gierig übernommen wird, wird sie vom Ende an erstellt. Zum Beispiel ist die Anzahl von I's n%5, dann ist die Anzahl von V' s n/5%2und so weiter. Dies ist eine gemischte Basenumwandlung mit aufeinanderfolgenden Verhältnissen von 5 und 2 abwechselnd.

Hier ist ein iteratives Äquivalent:

Python 2 , 68 Bytes

n=input();s='';d=5
for c in'IVXLCD':s=n%d*c+s;n/=d;d^=7
print'M'*n+s

Probieren Sie es online!

Die Mmüssen separat behandelt werden, da eine beliebige Anzahl von ihnen vorhanden sein kann, da es keine größere Ziffer gibt. Nachdem die anderen Platzwerte zugewiesen wurden, wird der verbleibende Wert in M's umgewandelt.

Zum Vergleich eine gierige Strategie (69 Bytes):

Python 2 , 69 Bytes

f=lambda n,d=1000,r='MDCLXVI':r and n/d*r[0]+f(n%d,d/(d%3*3-1),r[1:])

Probieren Sie es online!

Der aktuelle Ziffernwert dwird durch 2 oder 5 geteilt, um die nächste Ziffer zu erhalten. Der Wert von d%3sag uns welches: wenn d%3==1, dividiere durch 2; und wenn d%3==2, durch 5 teilen.

xnor
quelle
4

Mathematica, 81 Bytes

Table@@@Thread@{r=Characters@"MDCLXVI",#~NumberDecompose~FromRomanNumeral@r}<>""&

Die explizite Verwendung der Werte und die Ableitung der entsprechenden Ziffern scheint ein Byte länger zu sein:

Table@@@Thread@{RomanNumeral[n={1000,500,100,50,10,5,1}],#~NumberDecompose~n}<>""&
Martin Ender
quelle
1
Schön !:FromRomanNumeral@r
DavidC
4

Excel, 236 193 161 Bytes

43 Bytes gespart dank @ BradC

Zu diesem Zeitpunkt gehört die Antwort wirklich ganz @ BradC . Weitere 32 Bytes gespeichert.

=REPT("M",A1/1E3)&REPT("D",MOD(A1,1E3)/500)&REPT("C",MOD(A1,500)/100)&REPT("L",MOD(A1,100)/50)&REPT("X",MOD(A1,50)/10)&REPT("V",MOD(A1,10)/5)&REPT("I",MOD(A1,5))

Formatiert:

=REPT("M",A1/1E3)
    &REPT("D",MOD(A1,1E3)/500)
    &REPT("C",MOD(A1,500)/100)
    &REPT("L",MOD(A1,100)/50)
    &REPT("X",MOD(A1,50)/10)
    &REPT("V",MOD(A1,10)/5)
    &REPT("I",MOD(A1,5))
Wernisch
quelle
Sie werden einige durch Ersetzen sparen CONCATENATEmit &zwischen den einzelnen Elementen, und QUOTIENTmit INT(A/B).
BradC
2 weitere Einsparungen: Es stellt sich heraus, dass die ZahlREPT bereits abgeschnitten wird, wenn es sich nicht um eine Ganzzahl handelt. Sie können also 30 weitere Bytes einsparen, indem Sie jede einzelne entfernen INT(). Save 2 mehr durch beide ersetzen 1000mit 1E3(obwohl Excel scheint nicht zu wollen , dass die Art und Weise zu halten , wenn Sie die Eingabetaste drücken).
BradC
Ja, ich habe das 1E3Verhalten gesehen. Antwort aktualisiert.
Wernisch
3

Perl 5 , 66 Bytes

65 Byte Code + -pFlag.

$s=1e3;for$@(MDCLXVI=~/./g){$\.=$@x($_/$s);$_%=$s;$s/=--$|?2:5}}{

Probieren Sie es online!

MDCLXVI=~/./gKann ohne Änderung der Byteanzahl durch ersetzt werden M,D,C,L,X,V,I. und --$|?2:5von $|--*3+2.

Viel länger ( 99 Bytes ) gibt es:

$_=M x($_/1e3).D x($_%1e3/500).C x($_%500/100).L x($_%100/50).X x($_%50/10).V x($_%10/5).I x($_%5)
Dada
quelle
3

CJam , 35 28 Bytes

-7 Bytes dank Martin Ender

q~{5md\2md\}3*]W%"MDCLXVI".*

Probieren Sie es online!

Erläuterung

q~         e# Read and eval input (push the input as an integer).
{          e# Open a block:
 5md\      e#  Divmod the top value by 5, and bring the quotient to the top.
 2md\      e#  Divmod that by 2, and bring the quotient to the top.
}3*        e# Run this block 3 times.
]W%        e# Wrap the stack in an array and reverse it. Now we've performed the mixed-base
           e# conversion.
"MDCLXVI"  e# Push this string.
.*         e# Element-wise repetition of each character by the numbers in the other array.
           e# Implicitly join and print.
Geschäfts-Katze
quelle
3

C #, 127 Bytes

f=n=>n>999?"M"+f(n-1000):n>499?"D"+f(n-500):n>99?"C"+f(n-100):n>49?"L"+f(n-50):n>9?"X"+f(n-10):n>4?"V"+f(n-5):n>0?"I"+f(n-1):""

Eine rein hartcodierte ternäre Anweisung mit Rekursion.

Voll / Formatierte Version:

using System;

class P
{
    static void Main()
    {
        Func<int, string> f = null;
        f = n => n > 999 ? "M" + f(n - 1000)
                         : n > 499 ? "D" + f(n - 500)
                                   : n > 99 ? "C" + f(n - 100)
                                            : n > 49 ? "L" + f(n - 50)
                                                     : n > 9 ? "X" + f(n - 10)
                                                             : n > 4 ? "V" + f(n - 5)
                                                                     : n > 0 ? "I" + f(n - 1)
                                                                             : "";

        Console.WriteLine(f(3));
        Console.WriteLine(f(4));
        Console.WriteLine(f(42));
        Console.WriteLine(f(796));
        Console.WriteLine(f(2017));
        Console.WriteLine(f(16807));

        Console.ReadLine();
    }
}
TheLethalCoder
quelle
n>0ist einfach n.
CalculatorFeline
@CalculatorFeline Nicht in C #, intkann nicht implizit in a umgewandelt werden bool.
TheLethalCoder
Das ist bedauerlich.
CalculatorFeline
@CalculatorFeline Ja, C # ist manchmal zu stark getippt.
TheLethalCoder
3

05AB1E , 29 26 25 Bytes

¸5n3×Rvćy‰ì}"MDCLXVI"Ss×J

Probieren Sie es online!

Erläuterung

¸                           # wrap input in a list
 5n                         # push 5**2
   3×                       # repeat it 3 times
     Rv                     # for each digit y in its reverse
       ć                    # extract the head of the list 
                            # (div result of the previous iteration, initially input)
        y‰                  # divmod with y
          ì                 # prepend to the list
           }                # end loop
            "MDCLXVI"S      # push a list of roman numerals
                      s×    # repeat each a number of times corresponding to the result
                            # of the modulus operations
                        J   # join to string
Emigna
quelle
3

JavaScript (ES6), 81 75 69 Bytes

6 Bytes gespart dank @Neil für die Portierung der Antwort von @ Jörg Hülsermann

6 Bytes gespart dank @Shaggy

n=>'MDCLXVI'.replace(/./g,(c,i)=>c.repeat(n/a,n%=a,a/=i%2?5:‌​2),a=1e3)

Testfälle:

Craig Ayre
quelle
1
Sie sollten in der Lage sein, das n%=xinnerhalb der repeatMethode zu verschieben, um einige Bytes zu sparen.
Shaggy
1
Zu Ihrer Information, ein Port der PHP-Antwort ist nur 69 Bytes:n=>'MDCLXVI'.replace(/./g,(c,i)=>c.repeat(n/a,n%=a,a/=i%2?5:2),a=1e3)
Neil
Danke @Neil, ich habe den Beitrag aktualisiert. Entfernt das hartcodierte Array, das ich noch einmal besuchen wollte
Craig Ayre
2

/// , 50 bytes

/1/I//IIIII/V//VV/X//XXXXX/L//LL/C//CCCCC/D//DD/M/

Probieren Sie es online!

Nimmt die Eingabe in unary auf, und ich verwende (ab) das Fußzeilenfeld von TIO für die Eingabe, sodass der Ausgabe eine neue Zeile vorangestellt wird.

steenbergh
quelle
2

Python 3 , 100 97 96 94 93 91 90 Bytes

  • 4 + 2 Bytes gespeichert: Verwendung von def; Array als Standardparameter reduzierte einen Einrückungsraum; unerwünschte Variablendeklaration entfernt
  • @shooqie 1 Byte a%=Kurzschrift gespeichert
  • 2 Bytes gespart: neu angeordnet und geschweifte Klammern (a//i)entfernt
  • @Wondercricket 1 Byte gespart: Verschiebt das Array vom Standardparameter in die Funktion, die []auf Kosten eines Einrückungsraums entfernt wurde, wodurch 1 Byte gespart wird.
def f(a):
 b=1000,500,100,50,10,5,1
 for i in b:print(end=a//i*'MDCLXVI'[b.index(i)]);a%=i

Probieren Sie es online!

officialaimm
quelle
1
a%=iist ein Byte kürzer :)
Shooqie
1
Sie können ein Byte auch speichern, indem Sie es bals Variable in der Funktion speichern . Das beseitigt die Notwendigkeit von Klammern -b=1000,500,100,50,10,5,1
Wondercricket
2

Cubix , 69 74 80 Bytes

/.UI,..N&..0\0&/52"IVXLCDM"U,r%ws;rr3tu;pw..u;qrUosv!s.u\psq,!@Us(0;U

Probieren Sie es online!

        / . U I
        , . . N
        & . . 0
        \ 0 & /
5 2 " I V X L C D M " U , r % w
s ; r r 3 t u ; p w . . u ; q r
U o s v ! s . u \ p s q , ! @ U
s ( 0 ; U . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

Beobachten Sie es laufen

Ich habe es geschafft, es ein bisschen mehr zu komprimieren, aber es gibt immer noch einige nervige No-Ops, besonders auf der Oberseite.

  • 52"IVXLCDM"ULegen Sie die erforderlichen Teiler und Zeichen auf den Stapel. Die 5 und 2 werden verwendet, um den div / mod-Wert zu verringern, und die Zeichen werden nach der Verwendung verworfen.
  • UIN0/&0\&,/UWendet euch auf die Oberseite und startet eine lange Tour, um die Eingabe zu erhalten und 1000 auf den Stapel zu schieben. Eine erste Teilung wird durchgeführt und eine Kehrtwende rzum nächsten Snippet durchgeführt. In diesem Bereich wollte ich Einsparungen erzielen.
  • ,r%ws;rrBeginn der Divmod-Schleife. Ganzzahl-Teilung, drehen Sie den Mod "Ergebnis weg" und ordnen Sie den oberen Bereich des Stapels neu an, um die Eingabe, den aktuellen Teiler und das Divisionsergebnis zu reduzieren.
  • 3tus Bringe das aktuelle Zeichen nach oben und tausche es mit dem Divisionsergebnis aus.
  • !vsoUs(0;UDies ist die Druckschleife. Wenn das Div-Ergebnis größer als 0 ist, tauschen Sie es mit der Zeichenausgabe aus, tauschen Sie es zurück, dekrementieren Sie es, drücken Sie eine 0 und lassen Sie sie fallen. Bei 0 umleiten über den Pop-Stack (Ergebnis der Teilung entfernen) und um den Würfel.
  • \u;pwpsq,!@Urq;uMit ein wenig Umleitung wird der Charakter vom Stapel entfernt, die 5 und 2 werden nach oben verschoben, vertauscht und einer wird nach unten gedrückt. Der Rest wird verwendet, um den Teiler zu reduzieren. Halten Sie an, wenn es auf 0 reduziert wird, andernfalls drücken Sie die 5 oder 2 nach unten und betreten Sie die Schleife erneut.
MickyT
quelle
1

Mathematica, 130 Bytes

(f=#~NumberDecompose~{1000,500,100,50,10,5,1};""<>{Flatten@Table[Table[{"M","D","C","L","X","V","I"}[[i]],f[[i]]],{i,Length@f}]})&
J42161217
quelle
1

Python 2 , 109 90 Bytes

lambda n,r=[1000,500,100,50,10,5,1]:''.join(n%a/b*c for a,b,c in zip([n+1]+r,r,'MDCLXVI'))

Probieren Sie es online!

Stange
quelle
1000kann sein 1e3(wenn es Ihnen nichts ausmacht, ein Schwimmer zu sein, der kein Problem sein sollte)
CalculatorFeline
@CalculatorFeline es würde das Ergebnis in eine verwandeln float, und Sie können einen String nicht mit einem Float multiplizieren: c
Rod
1

T-SQL, 164 Bytes

SELECT REPLICATE('M',n/1000)+IIF(n%1000>499,'D','')
      +REPLICATE('C',n%500/100)+IIF(n%100>49,'L','')
      +REPLICATE('X',n%50/10)+IIF(n%10>4,'V','')
      +REPLICATE('I',n%5)
FROM t

Zeilenumbrüche wurden nur zur besseren Lesbarkeit hinzugefügt.

Diese Version ist viel länger (230 Zeichen), fühlt sich aber viel "SQL-ähnlicher" an:

DECLARE @ INT,@r varchar(99)=''SELECT @=n FROM t
SELECT'I's,1v INTO m
INSERT m VALUES('V',5),('X',10),('L',50),('C',100),('D',500),('M',1000)
L:
    SELECT @-=v,@r+=s 
    FROM m WHERE v=(SELECT MAX(v)FROM m WHERE v<=@)
IF @>0GOTO L
SELECT @r

Erstellt eine Tabelle m mit allen Zeichenwertzuordnungen und durchläuft dann die Suche nach dem größten Wert <= der Zahl, wobei das übereinstimmende Zeichen verkettet wird.

BradC
quelle
1

Japt , 34 Bytes

"IVXLCD"£%(U/=Y=v *3+2Y)îXÃw i'MpU

Online testen!

"IVXLCD"£    %(U/=Y=v  *3+2Y )îXÃ w i'MpU
"IVXLCD"mXY{U%(U/=Y=Yv *3+2,Y)îX} w i'MpU : Ungolfed
                                          : Implicit: U = input number
"IVXLCD"mXY{                    }         : Map each char X and its index Y in this string to:
                  Y=Yv *3+2               :   Set Y to 5 for even indexes, 2 for odd.
               U/=                        :   Divide U by this amount.
            U%(            ,Y)            :   Modulate the old value of U by 5.
                              îX          :   Repeat the character that many times.
                                          : This returns e.g. "IIVCCCD" for 16807.
                                  w       : Reverse the entire string.
                                    i'MpU : Prepend U copies of 'M' (remember U is now the input / 1000).
                                          : Implicit: output result of last expression
ETHproductions
quelle
1

JavaScript (ES6), 65 Byte

Eine rekursive Funktion.

f=(n,a=(i=0,1e3))=>n?a>n?f(n,a/=i++&1?5:2):'MDCLXVI'[i]+f(n-a):''

Wie?

Der zweite rekursive Aufruf f(n-a)sollte wirklich sein f(n-a,a). Durch den zweiten Parameter weggelassen, aund ineu initialisiert (bis 1000 bzw. 0) jedes Mal , wenn eine neue römische Ziffer wird auf das Endergebnis angehängt. Dies führt zu mehr Rekursion als erforderlich, ändert jedoch nicht das Ergebnis der Funktion und spart 2 Bytes.

Testfälle

Arnauld
quelle
1

J , 26-23 Bytes

3 Bytes gespart dank Adám.

'MDCLXVI'#~(_,6$2 5)&#:

Probieren Sie es online!

Ähnlich wie bei der APL antworte im Grunde das Gleiche.

'MDCLXVI'#~(_,6$2 5)&#:
           (       )&#:   mixed base conversion from decimal
              6$2 5       2 5 2 5 2 5
            _,            infinity 2 5 2 5 2 5
                          this gives us e.g. `0 0 0 0 1 0 4` for input `14`
'MDCLXVI'#~               shape each according to the number of times on the right
                          this is greedy roman numeral base conversion
Conor O'Brien
quelle
Nicht dass ich J kenne, aber warum #.invstatt #:?
Adám
@Adam Ah, guter Punkt. Ich benutze normalerweise #.invanstelle von #:, da so etwas 2 #: 4ist 0, während 2 #.inv 4ist1 0 0
Conor O'Brien
Ja, ich mache dasselbe in APL. Jetzt entspricht Ihre Lösung wirklich der APL-Lösung.
Am
#ist /; ~ist ; $ist ; &ist ; #:ist . Der einzige Unterschied ist, dass Sie unendlich verwenden, _während Sie 0wie die APL-Antwort verwenden könnten .
Adám
@Adam Huh, cool.
Conor O'Brien
1

Batch, 164 Bytes

@set/pn=
@set s=
@for %%a in (1000.M 500.D 100.C 50.L 10.X 5.V 1.I)do @call:c %%~na %%~xa
@echo %s:.=%
@exit/b
:c
@if %n% geq %1 set s=%s%%2&set/an-=%1&goto c

Übernimmt die Eingabe für STDIN.

Neil
quelle
1

Oracle SQL, 456 Byte

select listagg((select listagg(l)within group(order by 1)from dual start with trunc((n-nvl(n-mod(n,p),0))/v)>0 connect by level<=trunc((n-nvl(n-mod(n,p),0))/v)))within group(order by v desc)from (select 2849n from dual)cross join(select 1000v,null p,'m'l from dual union select 500,1000,'d'from dual union select 100,500,'c'from dual union select 50,100,'l'from dual union select 10,50,'x'from dual union select 5,10,'v'from dual union select 1,5,'i'from dual)

Ausgänge:

mmdcccxxxxviiii

Bitte beachten Sie, dass die tatsächliche Größe der Zeile 460 Byte beträgt, da sie die Eingabenummer (2849) enthält.

Ungolfed:

select listagg(
            (select listagg(l, '') within group(order by 1) 
             from dual 
             start with trunc((n-nvl(p*trunc(n/p),0))/v) > 0 
             connect by level <= trunc((n-nvl(p*trunc(n/p),0))/v) )
        ) within group(order by v desc)
from (select 2348 n
    from dual
) cross join (
    select 1000v, null p, 'm' l from dual union 
    select 500, 1000, 'd' from dual union
    select 100, 500, 'c' from dual union
    select 50, 100, 'l' from dual union
    select 10, 50, 'x' from dual union
    select 5, 10, 'v' from dual union
    select 1, 5, 'i' from dual     
)

Wie es funktioniert: Ich berechne, wie viele von jedem Buchstaben ich brauche, indem ich mit dem höheren Wert eins (unendlich für M) das Maximum errechne und dann eine ganzzahlige Division zwischen dem Wert des aktuellen Buchstabens und dem Ergebnis desselben durchführe.

ZB 2348, wie viele Cs brauche ich? trunc((2348-mod(2348,500))/100)= 3.

Dann habe ich listaggdiesen Brief 3 mal zusammen (ausnutzen CONNECT BY, um die 3 Zeilen zu generieren, die ich brauche). Zum Schluss hab ich listaggalles zusammen.

Ein bisschen sperrig, aber das meiste ist das select from duals in der Umrechnungstabelle und ich kann nicht wirklich viel dagegen tun ...

Dämonenschwarz
quelle
0

Java (OpenJDK 8) , 119 bis 118 Byte

n->{String s="";for(int v[]={1,5,10,50,100,500,1000},i=7;i-->0;)for(;n>=v[i];n-=v[i])s+="IVXLCDM".charAt(i);return s;}

Probieren Sie es online!

Dank @TheLethalCoder ein Byte gespeichert

Olivier Grégoire
quelle
1
Können Sie deklarieren vund iin der ersten for-Schleife ein Byte speichern?
TheLethalCoder
@TheLethalCoder Ja, mit Sicherheit. Anfangs hatte ich eine ganz andere Idee, dass dies meine interne Überprüfung nicht bestand: p
Olivier Grégoire
0

Charcoal , 61 50 46 Bytes

NνA⁰χWφ«W¬‹νφ«§MDCLXVIχA⁻νφν»A⁺¹χχA÷φ⎇﹪χ²¦²¦⁵φ

Probieren Sie es online!

Erläuterung:

Nν                   Take input as number and assign it to ν
A⁰χ                  Let χ=0
Wφ«                  While φ>0 (φ has a predefined value of 1000)
    W¬‹νφ«               While v>=φ 
        §MDCLXVIχ             Take the char from string "MDCLXVI" at position χ
        A⁻νφν»               Let ν=ν-φ
    A⁺¹χχ                Increment χ
    A÷φ⎇﹪χ²¦²¦⁵φ        If χ is odd, divide φ by 5, else divide φ by 2
  • 4 Bytes gespart dank Neil, während ich immer noch versuche herauszufinden, wie ich mit dem zweiten Teil seines Kommentars vorgehen soll.
Charlie
quelle
1
Nνist ein Byte kürzer als ANν, ¬‹ist ein Byte kürzer als das Subtrahieren von 1, und wenn Sie ÷(IntDivide) anstelle von (Divide) verwenden, können Sie dies φals äußere Schleifenbedingung verwenden. Ich denke jedoch, dass Sie es auf 40 Bytes reduzieren können, indem Sie MDCLXVIstattdessen direkt eine Schleife ausführen.
Neil
@Neil natürlich albern ich, versuche zu verstehen, warum es keinen "größer oder gleich" Operator gibt, wenn ich "nicht weniger" verwenden könnte. Sehr cleverer Trick die Verwendung der Integer Division. Gestatten Sie mir nun etwas Zeit, über den letzten Teil Ihres Kommentars nachzudenken ...
Charlie,
Ich habe meine String-Loop-Idee verbessert und als separate Antwort zusammen mit einer Portierung von @ xnors Python-Antwort veröffentlicht, die sich als gleich lang herausstellte.
Neil
0

C ++, 272 Bytes

#include <cstdio>
#include <map>
std::map<int,char> m = {{1000,'M'},{500,'D'},{100,'C'},{50,'L'},{10,'X'},{5,'V'},{1,'I'}};
int main(){unsigned long x;scanf("%d",&x);for(auto i=m.rbegin();i!=m.rend();++i)while(x>=i->first){printf("%c", i->second);x=x-i->first;}return 0;}
HSchmale
quelle
0

C 183 Bytes

#include <stdio.h>
int v[]={1000,500,100,50,10,5,1};
char*c="MDCLXVI";
int main(){int x;scanf("%d",&x);for(int i=0;i<sizeof v/sizeof(int);i++)for(;x>=v[i];x-=v[i])putc(c[i],stdout);}

Gleicher Algorithmus wie zuvor, nur mit einfachen c-Arrays anstelle einer std :: map, teilweise inspiriert von der Antwort von @ xnor, und unter Verwendung einer Zeichenfolge zum Speichern der Buchstaben.

HSchmale
quelle
98 Bytes
Ceilingcat
0

Common Lisp, 113 Bytes

Dies ist eine anonyme Funktion, die das Ergebnis als Zeichenfolge zurückgibt.

(lambda(value)(setf(values a b)(floor v 1000))(concatenate 'string(format()"~v,,,v<~>"a #\M)(format nil"~@:r"b)))

Ungolfed, mit beschreibenden Variablennamen und Kommentaren:

(defun format-roman (value)
  ;; Get "value integer-divided by 1000" and "value mod 1000"
  (setf (values n_thousands remainder) (floor value 1000))
  (concatenate 'string
               ;; Pad the empty string n_thousands times, using "M" as the 
               ;; padding character
               (format () "~v,,,v<~>" n_thousands #\M)
               ;; Format the remainder using "old-style" Roman numerals, i.e. 
               ;; numerals with "IIII" instead of "IV"
               (format nil "~@:r" remainder)))

In CL ist ein Formatierer für römische Zahlen integriert. Leider funktioniert es nicht für Zahlen größer als 3999.

Shadowtalker
quelle
0

Kohle , 34 Bytes

NςA²ξFMDCLXVI«×ι÷ςφA﹪ςφςA÷φξφA÷χξξ

Ursprünglich basiert auf @ CarlosAlegos Antwort. Ein Port von @ xnors Python-Lösung ist ebenfalls 34 Byte groß:

NθA⁵ξFIVXLCD«←×ι﹪θξA÷θξθA÷χξξ»←×Mθ

Edit: Ein Port von @ xnors anderer Python-Lösung hat 33 Bytes!

NθFMDCLXVI«×ι÷θφA﹪θφθA÷φ⁺׳﹪φ³±¹φ

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Beachten Sie, dass ich ⁺׳﹪φ³±¹anstelle von verwendet habe, ⁻׳﹪φ³¦¹weil der Deverbosifier derzeit das Trennzeichen nicht einfügen kann.

Neil
quelle
1
Huh, das sieht eher griechisch als römisch aus.
Adám