Ces Romains gourmands!


30

Étant donné un entier strictement positif, renvoyez le chiffre romain le plus court possible en utilisant uniquement la règle additive. La sortie doit comprendre zéro ou plus de chacun des caractères MDCLXVIdans cet ordre. Le nombre 14doit donc donner XIIIIplutôt que XIV.

Les valeurs numériques des caractères sont M= 1000, D= 500, C= 100, L= 50, X= 10, V= 5, I= 1.

Exemples

3III

4 → IIII

9VIIII

42XXXXII

796DCCLXXXXVI

2017MMXVII

16807MMMMMMMMMMMMMMMMDCCCVII


1
Vous êtes un interlocuteur bienveillant pour permettre 4 -> IIIIest 9 -> VIIIIaussi bien au lieu de IX?
Magic Octopus Urn


@MagicOctopusUrn VIIIIest la seule sortie autorisée pour 9.
Adam

@ Adám faisait juste remarquer que vous souhaitiez peut-être aussi l'ajouter à titre d'exemple car les règles pour 4 et 9 sont les mêmes.
Magic Octopus Urn

Réponses:


12

Anglais ordinaire , 1059 1025 678 641 451 399 octets

Enregistré 34 octets en supprimant une interruption d'erreur. Puis sauvé 384 octets en jouant au golf. Vous avez ensuite enregistré 190 octets en combinant l'opération de division avec l'opération d'ajout ("z") dans une nouvelle opération ("p"). Puis sauvé 52 octets en jouant au golf.

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.

Voici la version non golfée du code final, plus un piège d'erreur pour un nombre négatif:

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.

10
Attendez, est-ce un langage de programmation?
Adám

3
@Adam - Oui. Un anglais simple se compile, s'exécute et tout. Le code source et l'IDE sont disponibles sur github.com/Folds/english
Jasper

1
Mais faites-le au golf - après tout, c'est du golf de code, pas une vitrine linguistique.
Sanchises

2
C'est donc la langue que vous utilisez si vous ne voulez pas que votre travail soit externalisé, je suppose?
corsiKa

@corsiKa - LOL! Ce n'est que si nous sommes suffisamment nombreux à commencer à l'utiliser (et à l'ajouter à ses bibliothèques) qu'il atteint la masse critique.
Jasper

5

APL (Dyalog) , 25 22 octets

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

Essayez-le en ligne!


Sympa, et en gros la solution que j'avais en tête. Cependant, vous pouvez utiliser replicate ( /) au lieu de reshape ( ) afin de pouvoir supprimer chacun et la réduction caténate ( ¨et ,/).
Adám

En outre, vous pouvez convertir en corps tradfn et prendre input ( ) et utiliser commute ( ) pour supprimer les parens et composer ( ).
Adám

Merci, mais que voulez-vous dire par votre deuxième commentaire? Je ne peux pas penser à un moyen de le faire sans augmenter le nombre d'octets
TwiNight


1
Ce serait un extrait sauf si vous comptez la {}ou ∇f∇entourant la fonction
TwiNight

5

Rétine , 57 42 octets

Convertit en unaire, puis remplace goulûment les grappes de Is par les dénominations supérieures dans l'ordre.

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

Essayez-le en ligne

15 octets enregistrés grâce à Martin


C'est très intelligent.
Adám

7
C'est beaucoup plus court pour aller dans l'autre sens: tio.run/##K0otycxL/…
Martin Ender

Ne pourriez-vous pas saisir des entrées en unaire en utilisant Icomme unité?
2017

2
@ Adám Étant donné que Retina peut désormais gérer facilement des entrées entières, je pense que c'est un peu bon marché de le faire.
mbomb007

5

Python 2 , 64 octets

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

Essayez-le en ligne!

Plutôt que de créer la chaîne de sortie depuis le début en prenant avidement la plus grande partie, cela la crée depuis la fin. Par exemple, le nombre de Iest n%5, puis le nombre de Vest n/5%2, et ainsi de suite. Il s'agit d'une conversion de base mixte avec des rapports successifs de 5 et 2 alternés.

Voici un équivalent itératif:

Python 2 , 68 octets

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

Essayez-le en ligne!

Les Mfichiers doivent être traités séparément car un certain nombre d'entre eux peuvent être présents car il n'y a pas de chiffre plus grand. Ainsi, une fois les autres valeurs de lieu affectées, la valeur restante est convertie en M's.

A titre de comparaison, une stratégie gourmande (69 octets):

Python 2 , 69 octets

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

Essayez-le en ligne!

La valeur numérique actuelle dest divisée par 2 ou 5 pour produire le chiffre suivant. La valeur de d%3nous dire lequel: si d%3==1, diviser par 2; et si d%3==2, divisez par 5.


4

Mathematica, 81 octets

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

Utiliser explicitement les valeurs et dériver les chiffres correspondants semble être un octet de plus:

Table@@@Thread@{RomanNumeral[n={1000,500,100,50,10,5,1}],#~NumberDecompose~n}<>""&

1
Nice !:FromRomanNumeral@r
DavidC

4

Excel, 236 193 161 octets

43 octets enregistrés grâce à @ BradC

À ce stade, la réponse appartient vraiment totalement à @ BradC . Encore 32 octets enregistrés.

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

Formaté:

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

Vous en économiserez en remplaçant CONCATENATEpar &entre chaque élément et QUOTIENTpar INT(A/B).
BradC

2 économies supplémentaires: il s'avère que le nombre estREPT déjà tronqué s'il n'est pas un entier , vous pouvez donc économiser 30 octets supplémentaires en les supprimant chacun INT(). Économisez 2 de plus en remplaçant les deux 1000par 1E3(bien qu'Excel ne semble pas vouloir le conserver de cette façon une fois que vous appuyez sur Entrée).
BradC

Ouais, j'ai vu le 1E3comportement. Réponse mise à jour.
Wernisch

3

Perl 5 , 66 octets

65 octets de code + -pindicateur.

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

Essayez-le en ligne!

Sans changer le nombre d'octets, MDCLXVI=~/./gpeut être remplacé par M,D,C,L,X,V,I; et --$|?2:5par $|--*3+2.

Beaucoup plus long ( 99 octets ), il y a:

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

3

CJam , 35 28 octets

-7 octets grâce à Martin Ender

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

Essayez-le en ligne!

Explication

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.

3

C #, 127 octets

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

Une instruction ternaire purement codée utilisant la récursivité.

Version complète / formatée:

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

n>0est juste n.
CalculatorFeline

@CalculatorFeline Pas en C #, un intne peut pas être implicitement converti en a bool.
TheLethalCoder

C'est malheureux.
CalculatorFeline

@CalculatorFeline Oui, C # est trop fortement tapé pour son bien parfois.
TheLethalCoder

3

05AB1E , 29 26 25 octets

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

Essayez-le en ligne!

Explication

¸                           # 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

3

JavaScript (ES6), 81 75 69 octets

6 octets enregistrés grâce à @Neil pour le portage de la réponse de @ Jörg Hülsermann

6 octets enregistrés grâce à @Shaggy

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

Cas de test:


1
Vous devriez pouvoir déplacer le n%=xdans la repeatméthode pour économiser quelques octets.
Shaggy

1
Pour info un port de la réponse PHP n'est que de 69 octets:n=>'MDCLXVI'.replace(/./g,(c,i)=>c.repeat(n/a,n%=a,a/=i%2?5:2),a=1e3)
Neil

Merci @Neil, j'ai mis à jour le message. Supprime le tableau codé en dur que je voulais revoir
Craig Ayre

2

/// , 50 octets

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

Essayez-le en ligne!

Prend l'entrée en unaire, et j'utilise (ab) le champ de pied de page sur TIO pour l'entrée afin que la sortie soit précédée d'une nouvelle ligne.


2

Python 3 , 100 97 96 94 93 91 90 octets

  • 4 + 2 octets enregistrés: utilisation de def ; tableau comme paramètre par défaut réduit un espace d'indentation; déclaration de variable indésirable supprimée
  • @shooqie a enregistré un a%=raccourci de 1 octet
  • enregistré 2 octets: réarrangé et les accolades ont (a//i)été supprimés
  • @Wondercricket a sauvé 1 octet: déplacez le tableau du paramètre par défaut à l'intérieur de la fonction qui a été supprimée []au prix d'un espace d'indentation, économisant ainsi 1 octet.
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

Essayez-le en ligne!


1
a%=iest un octet plus court :)
shooqie

1
Vous pouvez également enregistrer un octet en le stockant en btant que variable dans la fonction. Cela supprime la nécessité des supports -b=1000,500,100,50,10,5,1
Wondercricket

2

Cubix , 69 74 80 octets

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

Essayez-le en ligne!

        / . 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 . . . . . . . . . . .
        . . . .
        . . . .
        . . . .
        . . . .

Regardez-le courir

J'ai réussi à le compresser un peu plus, mais il y a encore quelques no-op embêtants, surtout sur la face supérieure.

  • 52"IVXLCDM"Umettez les diviseurs et les caractères nécessaires sur la pile. Les 5 et 2 seront utilisés pour réduire la valeur div / mod et les caractères seront supprimés après utilisation.
  • UIN0/&0\&,/Ufait demi-tour sur la face supérieure et commence une longue tournée pour obtenir l'entrée et pousser 1000 sur la pile. Une première division est effectuée et un demi-tour sur rle prochain extrait de code. C'est un domaine que je cherchais à faire des économies.
  • ,r%ws;rrdébut de la boucle divmod. diviser l'entier, faire pivoter le résultat loin du mod, puis réorganiser le haut de la pile pour réduire l'entrée, le diviseur actuel et diviser le résultat.
  • 3tus amenez le personnage actuel en haut et échangez-le avec le résultat de division.
  • !vsoUs(0;Uc'est la boucle d'impression. tandis que le résultat div est supérieur à 0, permutez avec la sortie de caractères, permutez en arrière, décrémentez, poussez un 0 et déposez-le. Sur 0, redirigez sur la pile pop (supprimez le résultat de la division) et autour du cube.
  • \u;pwpsq,!@Urq;uavec un peu de redirection, cela supprime le personnage de la pile, ramène les 5 et 2 en haut, les échange et les repousse vers le bas. Le reste est utilisé pour réduire le diviseur. Arrêtez-le s'il se réduit à 0, sinon poussez le 5 ou le 2 vers le bas et rentrez dans la boucle.

1

Mathematica, 130 octets

(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}]})&

1

Python 2 , 109 90 octets

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

Essayez-le en ligne!


1000peut être 1e3(si cela ne vous dérange pas que ce soit un flotteur qui ne devrait pas être un problème)
CalculatorFeline

@CalculatorFeline cela transformerait le résultat en un float, et vous ne pouvez pas multiplier une chaîne par un flottant: 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

Line breaks added for readability only.

This version is a lot longer (230 characters), but feels much more "SQL-like":

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

Makes a table m with all the char-value mappings, and then loops through finding the largest value <= the number, concatenating the matching character.


1

Japt, 34 bytes

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

Test it 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

1

JavaScript (ES6), 65 bytes

A recursive function.

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

How?

The second recursive call f(n-a) really should be f(n-a,a). By omitting the 2nd parameter, a and i are reinitialized (to 1000 and 0 respectively) each time a new Roman digit is appended to the final result. This causes more recursion than needed but doesn't alter the outcome of the function and saves 2 bytes.

Test cases


1

J, 26 23 bytes

3 bytes saved thanks to Adám.

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

Try it online!

Similar to the APL answer basically the same thing.

'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

Not that I know J, but why #.inv instead of #:?
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.


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...


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


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.

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

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.



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.


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.


1
Huh, that looks more Greek than Roman.
Adám
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.