Quand à Rome, comptez comme les Romains?

20

Contexte

Ce challenge est inspiré de ce site internet, qui a publié le schéma suivant:

entrez la description de l'image ici

Ce diagramme nous montre que l'expression du chiffre romain la plus longue sous 250 est celle de 188, ce qui nécessite 9 chiffres pour s'exprimer.

Défi

Les symboles standards utilisés pour exprimer chiffres les plus romains sont les suivantes: { I, V, X, L, C, D, M}, où les valeurs numériques de caractères sont M= 1000, D= 500, C= 100, L= 50, X= 10, V= 5, I= 1.

Dans ce défi, votre objectif est de, étant donné un entier positif n , calculer le nombre de représentations de chiffres romains valides qui peuvent être composées en concaténant n des symboles standard.

Ensuite, votre programme doit sortir le résultat de ce calcul!

Entrée : Un entier positif n .

Sortie : Le nombre d'expressions de chiffres romains valides de longueur n .

Règles pour les expressions numériques romaines

Les chiffres romains n'avaient à l'origine qu'un appariement "additif", ce qui signifie que les chiffres étaient toujours écrits dans l'ordre décroissant, et la somme des valeurs de tous les chiffres était la valeur du nombre.

Plus tard, l'appariement soustractif, l'utilisation de placer un plus petit chiffre devant un plus grand afin de soustraire le plus petit du plus grand, est devenu monnaie courante pour raccourcir les expressions du chiffre romain. Paires soustractive ne peuvent être enchaînées, comme dans l'expression non valide suivante: IXL.

Voici les règles modernes pour l'appariement additif et soustractif.

  1. Un seul I, X et C peut être utilisé comme premier chiffre dans une partie d'une paire soustractive.
  2. Je ne peux être placé avant V ou X que dans une paire soustractive.
  3. X ne peut être placé avant L ou C dans une paire soustractive.
  4. C ne peut être placé avant D ou M dans une paire soustractive.
  5. À l'exception des paires soustractives, les chiffres doivent être dans l'ordre décroissant (ce qui signifie que si vous supprimez le chiffre de tête de chaque paire soustractive, les chiffres seront dans l'ordre décroissant).
  6. M, C et X ne peuvent pas être égalés ou dépassés par des dénominations plus petites.
  7. D, L et V ne peuvent chacun apparaître qu'une seule fois.
  8. Seul M peut être répété 4 fois ou plus.

Notes complémentaires

  • Nous n'utiliserons pas la notation à barres ; nous ajouterons simplement plus de M pour exprimer n'importe quel nombre.

  • Ce sont les seules règles que nous suivrons pour nos chiffres romains. Cela signifie que les expressions étranges, telles que IVI, seront également considérées comme valides dans notre système.

  • Souvenez-vous également que nous ne comptons pas le nombre de nombres qui ont des expressions de longueur n , car certains nombres ont plusieurs expressions. Au lieu de cela, nous comptons uniquement le nombre d'expressions valides.

Cas de test

17

231

3105

J'ai vérifié ce qui précède à la main, alors assurez-vous de vérifier les cas de test et d'ajouter plus si vous le pouvez!

Critères gagnants

Il s'agit d'un défi de , alors amusez-vous! Je n'accepterai que des solutions qui peuvent gérer au moins les entrées de 1 à 9. Plus est bonus!

Éditer

Comme demandé par les commentateurs, trouvez ci-dessous, ou sur ce lien pastebin, les 105 combos que j'ai comptés pour n = 3

III IVI IXI IXV IXX VII XII XIV XIX XVI XXI XXV XXX XLI XLV XLX XCI XCV XCX XCL XCC LII LIV LIX LVI LXI LXV LXX CII CIV CIX CVI CXI CXV CXX CXL CXC CLI CLV CLX CCI CCV CCX CCL CCC CDI CDV CDX CDL CDC CMI CMV CMX CML CMC CMD CMM DII DIV DIX DVI DXI DXV DXX DXL DXC DLI DLV DLX DCI DCV DCX DCL DCC MII MIV MIX MVI MXI MXV MXX MXL MXC MLI MLV MLX MCI MCV MCX MCL MCC MCD MCM MDI MDV MDX MDL MDC MMI MMI MMX MML MMC MMD MMM

Modifier 2:

Utilisez le code non golfé suivant , gracieuseté de Jonathan Allan pour vérifier vos résultats.

Modifier 3:

Je m'excuse pour toutes les erreurs de ce défi. Je ferai en sorte de faire un meilleur travail la prochaine fois!

Don mille
la source
Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
Mego

Réponses:

3

Rétine , 111 octets

~(`.+
*$(CM)CDXCXCXCXLIXIXIXIVII
.(.)
.+¶$$&$¶$$&$1$¶$$&$&¶L`.{0,$+}\b¶D`¶
¶$
¶.+¶$$&$¶$$&I¶L`[A-Z]{$+}\b¶D`¶.+

Essayez-le en ligne! Ceci est une réécriture complète car j'ai mal compris la règle 1. pour signifier que vous ne pouvez utiliser qu'un seul soustractif I, Xet C. Explication: La première partie du script développe l'entrée en une chaîne de CMpaires suivie des autres paires soustractives possibles. Chaque paire est facultative et le premier caractère de chaque paire est également facultatif au sein de la paire. La troisième étape étend ensuite la liste des paires en une liste de commandes Retina qui prennent l'entrée et créent trois copies avec l'option du deuxième ou des deux caractères de la paire, puis rognent et dédupliquent les résultats. L'étape finale ajoute ensuite du code pour effectuer les tâches finales: d'abord étendre l'entrée pour éventuellement ajouter une finaleI, puis de filtrer les résultats de la mauvaise longueur, puis de dédupliquer les résultats, et enfin de compter les résultats. Le script Retina résultant est ensuite évalué.

Remarque: En théorie, 15 octets pourraient être enregistrés à la fin de la 4e ligne, mais cela rend le script trop lent pour être démontré sur TIO, même pour n=1.

Neil
la source
@JonathanAllan Ah, alors vous incluez plusieurs paires soustractives avec le même chiffre de tête, ce qui est faux.
Neil
2
@JonathanAllan Nouvelle réécriture, coïncidence pour le même nombre d'octets exact!
Neil
5

Python 2 , 177 168 162 octets

import re,itertools as q
f=lambda n:sum(None!=re.match("^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$",(''.join(m)))for m in q.product('MDCLXVI',repeat=n))

Essayez-le en ligne!

Je suis assez nouveau, aidez-moi à jouer au golf! Ceci vérifie les chiffres romains réels, le regex doit être ajusté pour tenir compte des cas impairs tels queIVI

-9 octets grâce à @Dead Possum!

-6 octets grâce à @ovs

Easton Bornemeier
la source
Oui, je pense que le cas n = 3 pourrait être faux dans l'exemple. ^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
J'obtenais à l'
171 octets
Dead Possum
1
@JonathanAllan J'ai passé environ deux jours à me renseigner sur Math stackexchange pour essayer de m'assurer que ces règles avaient du sens. Je suppose que je n'en ai pas fait assez :(
Don Thousand
1
@RushabhMehta Ceci est un défi très bien formaté et amusant à programmer, ne vous sentez pas mal à propos d'une nuance malheureuse dans les moindres détails de la définition des chiffres romains. C'est votre défi, spécifiez-le comme bon vous semble. c'est réalisable dans l'autre sens, juste plus difficile
Easton Bornemeier
1
Cela ne semble pas donner la bonne réponse pour 3. 93au lieu de105
Jo King
3

JavaScript (ES7), 133 octets

Edit : corrigé pour correspondre aux résultats renvoyés par le code de Jonathan Allan , qui a été donné comme implémentation de référence par l'OP.


n=>[...Array(m=k=7**n)].reduce(s=>s+/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test((--k+m).toString(7).replace(/0[62]|2[34]|4[51]/g,s=>s[1])),0)

Essayez-le en ligne!

Comment?

N1

[...Array(m = k = 7 ** n)].reduce(s => … (--k + m).toString(7) …, 0)

Désormais, chaque chiffre sera interprété comme un symbole de chiffre romain:

0je,1M,2X,3L,4C,5,6V

2) Nous remplaçons toutes les paires soustractives valides du formulaire ABpar B:

.replace(/0[62]|2[34]|4[51]/g, s => s[1]))  // in the code
.replace(/I[VX]|X[LC]|C[DM]/g, s => s[1]))  // with Roman symbols

Exemples:

  • XLIXIV devient LXV
  • XIIVdevient XIV, laissant un Iqui fera échouer le prochain test
  • ICreste inchangé, ce qui laisse également un invalide Ien place

3) Nous vérifions que les symboles restants sont dans le bon ordre et n'apparaissent pas plus de fois qu'ils ne sont autorisés à:

/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test(…)  // in the code
/^M*D?C{0,3}L?X{0,3}V?I{0,3}$/.test(…)  // with Roman symbols
Arnauld
la source
Sainte vache, je ne m'attendais pas à ce que cela se fasse en moins de 200 octets dans des langues non ésotériques! Voulez-vous expliquer comment cela fonctionne?
Don Thousand
Cependant, j'ai remarqué que cela ne fonctionne pas pour * n *> 4 sur TIO, ce qui est quelque peu regrettable.
Don Thousand
@RushabhMehta J'ai ajouté une version non récursive pour tester des valeurs plus élevées. J'ajouterai une explication quand j'aurai fini de jouer au golf.
Arnauld
0

C, 150 123 octets

Je n'ai pas lu la description assez attentivement, donc cela produit le nombre de chiffres romains standard (où les expressions comme IVIne sont pas comptées). Depuis que j'y ai mis un peu d'effort, j'ai pensé que je partagerais quand même.

#define F(X) for(X=10;X--;)
x[]={0,1,2,3,2,1,2,3,4,2};f(i,o,a,b,c){for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];return o;}

Original (150 octets):

#define F(X) for(X=10;X--;)
i,o,a,b,c,x[]={0,1,2,3,2,1,2,3,4,2};main(){scanf("%i",&i);for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];printf("%i\n",o);}
Curtis Bechtel
la source
1
Vous n'êtes autorisé qu'à publier des soumissions valides.
Okx
@CurtisBechtel Vous pouvez garder la solution ici, je suppose, mais j'essaierais de la modifier pour satisfaire les règles du défi.
Don Thousand
1
Je pense que vous pouvez supprimer l'espace entre F(X)etfor(X=10;X--;)
Zacharý