Ci chciwi Rzymianie!

30

Biorąc pod uwagę ściśle dodatnią liczbę całkowitą, zwróć możliwie najkrótszą liczbę rzymską, używając tylko reguły addytywnej. Dane wyjściowe muszą składać się z zera lub więcej z każdego ze znaków MDCLXVIw tej kolejności. Dlatego liczba 14musi być podana XIIIIzamiast XIV.

Wartości liczbowe znaków to M= 1000, D= 500, C= 100, L= 50, X= 10, V= 5, I= 1.

Przykłady

3III

4 → IIII

9VIIII

42XXXXII

796DCCLXXXXVI

2017MMXVII

16807MMMMMMMMMMMMMMMMDCCCVII

Adám
źródło
1
Jesteś życzliwym pytającym, na którego pozwolenie 4 -> IIIIjest 9 -> VIIIIrównież zamiast IX?
Magic Octopus Urn
@MagicOctopusUrn VIIIIjest jedynym dozwolonym wyjściem dla 9.
Adám
@ Adám tylko wskazał, że możesz dodać to również jako przykład, ponieważ reguły dla 4 i 9 są takie same.
Magic Octopus Urn
1
Powiązane
Arnauld

Odpowiedzi:

12

Zwykły angielski , 1059 1025 678 641 451 399 bajtów

Zapisano 34 bajty, usuwając pułapkę błędów. Następnie zaoszczędzono 384 bajty, grając w golfa. Następnie zapisano 190 bajtów, łącząc operację dzielenia z operacją dołączania („z”) w nowej operacji („p”). Następnie zaoszczędzono 52 bajty, grając w golfa.

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.

Oto niezakończona wersja ostatecznego kodu plus pułapka błędu dla liczby ujemnej:

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
źródło
10
Zaraz, czy to jest język programowania?
Adám
3
@Adam - Tak. Zwykły angielski kompiluje się, uruchamia i wszystko. Kod źródłowy i IDE są dostępne na github.com/Folds/english
Jasper
1
Zagraj w golfa - w końcu jest to golf golfowy, a nie prezentacja językowa.
Sanchises
2
Więc to jest język, którego używasz, jeśli nie chcesz, aby twoja praca została zlecona na zewnątrz. Rozumiem?
corsiKa
@corsiKa - LOL! Tylko jeśli wystarczająca liczba z nas zacznie go używać (i dodawać do swoich bibliotek), że osiągnie masę krytyczną.
Jasper
5

APL (Dyalog) , 25 22 bajtów

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

Wypróbuj online!

TwiNight
źródło
Ładne i w zasadzie rozwiązanie, które miałem na myśli. Możesz jednak użyć replicate ( /) zamiast reshape ( ), dzięki czemu możesz wyciąć każdy z nich i redukcję catenate ( ¨i ,/).
Adám
Możesz także przekonwertować na ciało tradfn i wziąć input ( ) i użyć commute ( ), aby usunąć parens i compose ( ).
Adám
Dzięki, ale co masz na myśli przez swój drugi komentarz? Nie mogę wymyślić sposobu, aby to zrobić bez zwiększenia liczby bajtów
TwiNight
1
Byłby to urywek, chyba że {}∇f∇
policzysz
5

Siatkówka oka , 57 42 bajtów

Przekształca się w jednoargumentowy, a następnie łapczywie zastępuje wiązki Isz wyższymi nominałami w kolejności.

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

Wypróbuj online

Zaoszczędź 15 bajtów dzięki Martinowi

mbomb007
źródło
To bardzo sprytne.
Adám
7
O wiele krócej jest pójść w drugą stronę: tio.run/##K0otycxL/…
Martin Ender
Czy nie mógłbyś wziąć wkładu jednomyślnie używając Ijednostki?
Adám
2
@ Adám Biorąc pod uwagę, że Retina może teraz łatwo obsługiwać wprowadzanie liczb całkowitych, myślę, że jest to trochę tanie.
mbomb007
5

Python 2 , 64 bajty

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

Wypróbuj online!

Zamiast tworzyć ciąg wyjściowy od początku, łapczywie biorąc największą część, tworzy go od końca. Na przykład liczba Ijest n%5, następnie liczba Vjest n/5%2itd. Jest to konwersja mieszanej zasady z kolejnymi stosunkami naprzemiennie 5 i 2.

Oto iteracyjny odpowiednik:

Python 2 , 68 bajtów

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

Wypróbuj online!

The M„S muszą być traktowane oddzielnie, ponieważ każda liczba z nich może być obecny jako że nie ma większych cyfr. Zatem po przypisaniu innych wartości miejsca, pozostała wartość jest konwertowana na M's.

Dla porównania chciwa strategia (69 bajtów):

Python 2 , 69 bajtów

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

Wypróbuj online!

Bieżąca wartość cyfry djest dzielona przez 2 lub 5, aby utworzyć następną cyfrę. Wartość d%3powiedz nam, który: jeśli d%3==1, podziel przez 2; a jeśli d%3==2podziel przez 5.

xnor
źródło
4

Mathematica, 81 bajtów

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

Jawne użycie wartości i wyprowadzenie odpowiednich cyfr wydaje się dłuższe o jeden bajt:

Table@@@Thread@{RomanNumeral[n={1000,500,100,50,10,5,1}],#~NumberDecompose~n}<>""&
Martin Ender
źródło
1
Fajnie !:FromRomanNumeral@r
DavidC
4

Excel, 236 193 161 bajtów

43 bajty zapisane dzięki @ BradC

W tym momencie odpowiedź naprawdę należy całkowicie do @ BradC . Zapisano kolejne 32 bajty.

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

Sformatowany:

=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
źródło
Zaoszczędzisz zastępując niektóre CONCATENATEz &pomiędzy poszczególnymi elementami i QUOTIENTz INT(A/B).
BradC
2 dodatkowe oszczędności: okazuje się REPT że liczba jest już obcięta, jeśli nie jest liczbą całkowitą , dzięki czemu możesz zaoszczędzić 30 bajtów, usuwając każdy z nich INT(). Zapisz 2 więcej zastępując zarówno 1000z 1E3(choć Excel nie wydają się chce utrzymać to w ten sposób raz trafisz enter).
BradC
Tak, widziałem 1E3zachowanie. Odpowiedź zaktualizowana.
Wernisch
3

Perl 5 , 66 bajtów

65 bajtów kodu + -pflaga.

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

Wypróbuj online!

Bez zmiany liczby bajtów MDCLXVI=~/./gmożna go zastąpić M,D,C,L,X,V,I; i --$|?2:5przez $|--*3+2.

Znacznie dłużej ( 99 bajtów ) jest:

$_=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
źródło
3

CJam , 35 28 bajtów

-7 bajtów dzięki Martinowi Enderowi

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

Wypróbuj online!

Wyjaśnienie

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.
Business Cat
źródło
3

C #, 127 bajtów

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):""

Oświadczenie potrójnie czysto zakodowane przy użyciu rekurencji.

Wersja pełna / sformatowana:

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
źródło
n>0jest po prostu n.
CalculatorFeline
@CalculatorFeline Nie w C #, intnie można niejawnie rzutować na a bool.
TheLethalCoder
To niefortunne.
CalculatorFeline
@CalculatorFeline Tak, C # jest zbyt mocno wpisane, aby czasami mieć własne zalety.
TheLethalCoder
3

05AB1E , 29 26 25 bajtów

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

Wypróbuj online!

Wyjaśnienie

¸                           # 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
źródło
3

JavaScript (ES6), 81 75 69 bajtów

Zaoszczędź 6 bajtów dzięki @Neil za przeniesienie odpowiedzi @ Jörga Hülsermanna

Zaoszczędź 6 bajtów dzięki @Shaggy

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

Przypadki testowe:

Craig Ayre
źródło
1
Powinieneś być w stanie przenieść n%=xwewnątrz repeatmetody, aby zapisać kilka bajtów.
Shaggy
1
FYI port odpowiedzi PHP ma tylko 69 bajtów:n=>'MDCLXVI'.replace(/./g,(c,i)=>c.repeat(n/a,n%=a,a/=i%2?5:2),a=1e3)
Neil
Dzięki @Neil, zaktualizowałem post. Usuwa zakodowaną tablicę, do której chciałem wrócić
Craig Ayre
2

/// , 50 bajtów

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

Wypróbuj online!

Pobiera dane wejściowe jednoargumentowe, a ja (ab) używam pola stopki na TIO do wprowadzania danych, więc dane wyjściowe poprzedzone są nową linią.

Steenbergh
źródło
2

Python 3 , 100 97 96 94 93 91 90 bajtów

  • zapisane 4 + 2 bajty: użycie def ; tablica jako parametr domyślny zmniejszyła przestrzeń wcięcia; usunięto niechcianą deklarację zmiennej
  • @shooqie zapisał 1 bajt a%=skrót
  • zapisano 2 bajty: przestawiono i (a//i)usunięto nawiasy klamrowe
  • @Wondercricket zapisał 1 bajt: przenieś tablicę z parametru domyślnego do funkcji, która usunęła []kosztem jednego miejsca wcięcia, oszczędzając w ten sposób 1 bajt.
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

Wypróbuj online!

Officialaimm
źródło
1
a%=ijest bajt krótszy :)
shooqie
1
Możesz również zapisać bajt, przechowując go bjako zmienną w funkcji. To eliminuje konieczność stosowania nawiasów -b=1000,500,100,50,10,5,1
Wondercricket
2

Cubix , 69 74 80 bajtów

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

Wypróbuj 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 . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

Watch It Running

Udało mi się to jeszcze bardziej skompresować, ale nadal jest trochę przykrych, bezużytecznych, szczególnie na górnej twarzy.

  • 52"IVXLCDM"Uumieść na stosie niezbędne dzielniki i postacie. 5 i 2 zostaną wykorzystane do zmniejszenia wartości div / mod, a znaki zostaną odrzucone po użyciu.
  • UIN0/&0\&,/UU odwraca się do górnej powierzchni i rozpoczyna długą trasę, aby zdobyć dane wejściowe i wcisnąć 1000 na stos. Dokonuje się początkowego podziału i zawraca się rdo następnego fragmentu kodu. To był obszar, na którym szukałem oszczędności.
  • ,r%ws;rrpoczątek pętli divmod. dzielenie liczb całkowitych, obracaj mod wyniku, a następnie zmieniaj kolejność stosu, aby zmniejszyć wejście, dzielnik prądu i podzielić wynik.
  • 3tus przenieś obecną postać na górę i zamień ją wynikiem podziału.
  • !vsoUs(0;Uto jest pętla drukowania. podczas gdy wynik div jest większy niż 0, zamień z wyjściem postaci, zamień z powrotem, zmniejsz, wypchnij 0 i upuść. Na 0 przekieruj na stos pop (usuń wynik podziału) i wokół kostki.
  • \u;pwpsq,!@Urq;uz odrobiną przekierowania usuwa to postać ze stosu, przenosi 5 i 2 na szczyt, zamienia je i spycha z powrotem w dół. Pozostałe służą do zmniejszenia dzielnika. Zatrzymaj, jeśli zmniejszy się do 0, w przeciwnym razie przesuń 5 lub 2 na dół i ponownie wejdź w pętlę.
MickyT
źródło
1

Mathematica, 130 bajtów

(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
źródło
1

Python 2 , 109 90 bajtów

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

Wypróbuj online!

Pręt
źródło
1000może być 1e3(jeśli nie masz nic przeciwko temu, że jest to float, co nie powinno stanowić problemu)
CalculatorFeline
@CalculatorFeline zmieniłoby wynik w a floati nie można pomnożyć ciągu przez liczbę zmiennoprzecinkową: c
Rod
1

T-SQL, 164 bajty

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

Dodano podział wiersza tylko w celu odczytu.

Ta wersja jest znacznie dłuższa (230 znaków), ale wydaje się bardziej „podobna do SQL”:

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

Tworzy tabelę m ze wszystkimi odwzorowaniami wartości char, a następnie wykonuje pętle, wyszukując największą wartość <= liczbę, łącząc pasujący znak.

BradC
źródło
1

Japt , 34 bajty

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

Przetestuj online!

"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
ETHprodukcje
źródło
1

JavaScript (ES6), 65 bajtów

Funkcja rekurencyjna.

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

W jaki sposób?

Drugie rekurencyjne połączenie f(n-a)naprawdę powinno być f(n-a,a). Pominięcie drugiego parametru ai iponowne zainicjowanie (odpowiednio do 1000 i 0) za każdym razem, gdy do wyniku końcowego dołączana jest nowa cyfra rzymska. Powoduje to większą rekurencję niż jest to konieczne, ale nie zmienia wyniku funkcji i oszczędza 2 bajty.

Przypadki testowe

Arnauld
źródło
1

J , 26 23 bajtów

3 bajty zapisane dzięki Adámowi.

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

Wypróbuj online!

Podobnie do odpowiedzi APL w zasadzie to samo.

'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
źródło
Nie, że znam J, ale dlaczego #.invzamiast #:?
Adám
@Adám Ah, good point. I customarily use #.inv instead of #:, since something like 2 #: 4 is 0, whilst 2 #.inv 4 is 1 0 0
Conor O'Brien
Yeah, I do the same thing in APL. Now your solution is truly equivalent to the APL solution.
Adám
# is /; ~ is ; $ is ; & is ; #: is . The only difference is that you use infinity _ while you could use 0 like the APL answer.
Adám
@Adám 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

Takes input on STDIN.

Neil
źródło
1

Oracle SQL, 456 bytes

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)

Outputs:

mmdcccxxxxviiii

Please note the actual size of the line is 460bytes, because it includes the input number (2849).

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     
)

How it works: I calculate how many of each letter I need, by calculating the most I can get to with the higher value one (infinity for M), and then doing an integer division between the current letter's value and the result of that.

E.g. 2348, how many Cs do I need? trunc((2348-mod(2348,500))/100) = 3.

Then, I listagg that letter together 3 times (exploiting CONNECT BY to generate the 3 rows I need). Finally, I listagg everything together.

Kinda bulky, but most of it is the select from duals in the conversion table and I can't really do much about that...

Demonblack
źródło
0

Java (OpenJDK 8), 119 118 bytes

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

Try it online!

Saved a byte thanks to @TheLethalCoder

Olivier Grégoire
źródło
1
Can you declare v and i in the first for loop to save a byte?
TheLethalCoder
@TheLethalCoder Yes, most certainly. I was on a totally other idea at first that this didn't pass my internal review :p
Olivier Grégoire
0

Charcoal, 61 50 46 bytes

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

Try it online!

Explanation:

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 saved thanks to Neil, while I am still trying to figure out how to proceed with the second part of his comment.
Charlie
źródło
1
Nν is one byte shorter than ANν, ¬‹ is one byte shorter than subtracting 1, and if you use ÷ (IntDivide) instead of (Divide) then you can use φ as the outer loop condition. However, I think you can get it down to 40 bytes by looping over MDCLXVI directly instead.
Neil
@Neil of course, silly me, trying to understand why there is no "greater or equal" operator when I could use "not less". Very clever trick the use of the integer division. Now allow me some time to think about the last part of your comment...
Charlie
I improved my string loop idea and posted it as a seprate answer along with a port of @xnor's Python answer, which turned out to be the same length.
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
źródło
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);}

Same algorithm as before, just using plain c arrays instead of an std::map, partially inspired by @xnor's answer and using a string to store the letters.

HSchmale
źródło
98 bytes
ceilingcat
0

Common Lisp, 113 bytes

This is an anonymous function, returning the result as a string.

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

Ungolfed, with descriptive variable names and comments:

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

CL has built-in Roman numeral formatter. Sadly it doesn't work for numbers larger than 3999.

shadowtalker
źródło
0

Charcoal, 34 bytes

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

Originally based on @CarlosAlego's answer. A port of @xnor's Python solution is also 34 bytes:

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

Edit: A port of @xnor's other Python solution turns out to be 33 bytes!

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

Try it online! Link is to verbose version of code. Note that I've used ⁺׳﹪φ³±¹ instead of ⁻׳﹪φ³¦¹ because the deverbosifier is currently failing to insert the separator.

Neil
źródło
1
Huh, that looks more Greek than Roman.
Adám