Séquence de choix: édition des chiffres romains

20

Description du défi

Nous avons eu quelques défis concernant la séquence de recherche et de présentation . Rappel rapide:

  • La séquence commence par 1,
  • Les termes suivants de cette séquence sont générés en énumérant chaque groupe de chiffres répétitifs dans le terme précédent,

Les premiers termes sont donc:

1        "one"
11       "one one" (we look at the previous term)
21       "two ones"
1211     "one two, one one"
111221   "one one, one two, two ones"
312211   "three ones, two twos, one one"

Faisons maintenant la même chose, mais utilisons des chiffres romains à la place. Nous commençons par Iet suivons les mêmes règles (nous appliquons la règle de comptage des chiffres aux caractères à la place, nous lisons donc IVXau one one, one five, one tenlieu de one four, one tenou d'une autre manière):

I           "one"
II          "one one"
III         "two ones" = "II" + "I"
IIII        "three ones" = "III" + "I"
IVI         "four ones" = "IV" + "I"
IIIVII      "one one, one five, one one"
IIIIIVIII   "three ones, one five, two ones" = ("III" + "I") + ("I" + "V") + ("II" + "I")

Étant donné un entier positif N, soit:

  • Sortez les premiers Nchiffres de cette séquence (tout séparateur raisonnable est bien, ainsi que["I", "II", "III", ...]
  • Afficher Nle terme de cette séquence (il peut être indexé 0).

N'oubliez pas de rendre votre code aussi court que possible, car il s'agit d'un défi de !

EDIT: Je crois qu'il y a toujours une façon standard / préférée d'exprimer des entiers en chiffres romains (comme 95-> XCVau lieu de VC). Quelques convertisseurs de chiffres romains que j'ai trouvés en ligne corroborent mon opinion. En cas de doute, utilisez un convertisseur en ligne , car répertorier tous les cas de bord possibles et les règles spécifiques d'écriture des chiffres romains n'est pas le but de ce défi.

EDIT2: @PeterTaylor et @GregMartin ont fait remarquer que des chiffres inférieurs ou égaux à 5apparaître dans la séquence, de sorte que vous n'avez pas à vous soucier de l'ambiguïté des chiffres romains (numéros 1- 8sont I, II, III, IV, V, VI, VII, et VIII)

shooqie
la source
Il n'y a pas d'expression de chiffre romain unique pour chaque entier. Quels nombres pourrait-il être nécessaire d'exprimer et quelles expressions de ces nombres sont valides?
Peter Taylor
Qu'entendez-vous par «il n'y a pas d'expression unique de chiffre romain pour chaque entier»? Comme 4/ IV/ IIII? Ou 95/ XCV/ VC? Il n'y a peut-être pas toujours une façon unique d'exprimer un entier, mais je suis presque sûr qu'il y en a toujours une préférée (standard) - corrigez-moi si je me trompe.
shooqie
1
jusqu'où devons-nous aller avec nos chiffres romains?
Maltysen
Oui, ces deux cas. Dans le deuxième cas, je pense que c'est une question d'opinion qui est préférable.
Peter Taylor
9
@shooqie si ces détails n'étaient pas clarifiés, comment compareriez-vous les réponses? S'il reste certains cas marginaux à interpréter, les scores réels perdent tout leur sens car ils pourraient faire une plus grande différence que n'importe quel tour de golf que vous pourriez trouver.
Martin Ender

Réponses:

17

Perl, 49 octets

Comprend +1 pour -p

Exécuter avec l'index basé sur 0 sur STDIN, par exemple

ecce.pl <<< 14

ecce.pl:

#!/usr/bin/perl -p
s,(.)\1*,$&/$1%182 .$1,eg for($_=/$/)x$`;y;19;IV

Les formules magiques sont tellement magiques.

Normalement, j'utiliserais ($_=//)x$'pour raccourcir le contrôle de boucle d'un octet, mais le score sur ce site donne un handicap de 2 donc il finit par 1 octet de plus. Sur les anciennes perles, vous pouvez supprimer l'espace avant for. Certaines versions de perl vous obligent à ajouter une finale ;pour fermer la translittération. Mais ce qui est donné ci-dessus est le code qui fonctionne sur mon système.

Explication

Reculer de la solution au code:

Les transformations de chaîne dont nous avons besoin:

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

Chaque remplacement se termine par le caractère répété. J'obtiendrai une séquence des mêmes caractères en utilisant l'expression régulière /(.)\1*/, donc cela peut être fait en ajoutant $1. La partie avant l' ->est $&. Avec ça j'ai encore besoin:

I     -> I
II    -> II
III   -> III
IIII  -> IV
IIIII -> V

V     -> I
VV    -> II

Écrivez Icomme 1et Vcomme 9:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

9     -> 1
99    -> 11

En divisant la partie précédente ->par le chiffre répété, cela devient:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

1     -> 1
11    -> 11

Alors maintenant, l'original répété Vn'est plus une exception. Je veux donc une expression qui rend cela possible:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

Et cela peut être fait par un simple modulo 182:

1     % 182 = 1
11    % 182 = 11
111   % 182 = 111
1111  % 182 = 19
11111 % 182 = 9

(cela arrive même IIIIIIà VIdroite même si ce n'est pas nécessaire ici)

Il ne reste plus qu'à initialiser la variable de travail à 1pour l'index 0, répéter cette transformation en boucle et à la fin remplacer 1par Iet 9parV

1, 9Et 182est la combinaison seul paramètre pour lequel cette simple formule fonctionne de.

Ton Hospel
la source
2
C'est génial! :)
Lynn
10

Mathematica, 113 90 83 octets

Merci à Martin Ender pour ses suggestions qui ont réduit la longueur de plus de 25%!

Affichage des commandes de haut niveau dans Mathematica.

Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&

Une fonction pure, prenant un argument N et sortant le Nième élément de cette séquence (indexée 0), comme une liste de caractères. Étalez un peu:

Nest[
  Flatten[
    Characters @ {RomanNumeral@#,#2}& @@@
      Reverse @@@ Tally /@ Split@ #
    ]& ,
  {"I"}, #]&

L'extérieur Nestitère la fonction à quatre lignes du milieu, en commençant {"I"}, N fois. La ligne 4 divise la liste des caractères du chiffre romain entré en séries de caractères similaires, compte chaque série avec Tallyet place les décomptes avant les caractères qu'ils comptent. La ligne 3 rend les comptes en chiffres romains, puis divise ces chiffres romains en listes de caractères. La Flattencommande réduit la liste de listes entière à une liste unidimensionnelle.

Voici la version initiale:

Nest[
  "" <> Flatten[{RomanNumeral@#[[1]], #[[2]]} & /@
    (Reverse@#[[1]] & /@ 
      Tally /@
        Split@Characters@#)] &,
  "I", #] &
Greg Martin
la source
3
Grrr Mathematica;)
Beta Decay
Si vous utilisez @@@au lieu de /@vous pouvez utiliser #et #2au lieu de #[[1]]et #[[2]]. De plus, les listes de caractères sont des types de chaîne acceptables, vous pouvez donc travailler avec ceux-ci et éviter de les utiliser Characters@.
Martin Ender
@MartinEnder Aha, je savais qu'il devait y avoir un @@@raccourci de type! En ce qui concerne les listes de caractères qui sont des types de chaînes acceptables (ce qui, je pense, raccourcirait le code): y a-t-il un article sur ce site auquel vous pouvez me diriger qui décrit les normes de la communauté?
Greg Martin
1
A quelques économies: Charactersfils automatiquement , vous pouvez utiliser @, Reverse@#&est bien sûr la même chose que simple Reverse, dans ce cas , vous pouvez aussi ne pas besoin de ces parenthèses. Et la notation de préfixe (dans le cas de Flatten) n'enregistre rien si vous devez ajouter des parenthèses pour le faire fonctionner. Combinant tous ces éléments:Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&
Martin Ender
8

CJam ( 33 30 octets)

"I"{e`{(4md1$^'I*\'V*@}%e_}ri*

Démo en ligne

La clé de l'exactitude de l'implémentation est le théorème suivant:

Si la première génération est I, aucune longueur de course n'est jamais supérieure à cinq

Lemme: si la première génération est I, aucune chaîne ne contient jamais VVV. La preuve est par contradiction. Supposons qu'il existe un premier index npour lequel la ne génération contient VVV. Si cela VVVtombe en panne (a)V VValors la conversion de la génération précédente est mauvaise: elle aurait dû l'être (a+5)V. Il faut donc VV V(d), et la génération précédente contenue VVVVV, contredire le choix de n.

Supposons maintenant qu'il existe un premier index mpour lequel la me génération contient ...IIIIII.... Notez qu'il ne peut y avoir aucun chiffre autre que Iet Vdans la chaîne, car aucune génération précédente n'a eu un cycle de neuf Is ou neuf Vs. Au plus quatre des Is proviennent d'une série de Is dans la chaîne précédente, donc la section correspondante de la chaîne précédente doit être ...IIIVV...donnée ... IIII IIV .... Puisque la VVgénération in m-1ne vient pas de VVVVV(voir lemme), la seconde Vdoit être une longueur de chiffre I, donc dans la génération m-1nous avons ...IIIVVI.... Et puisque nous voulons que les Is initiaux donnent IIIIet non IVIouVI, il est précédé soit du début de la chaîne, soit d'un V.

Si nous avons (...V)?IIIVVI...en génération m-1, qu'avons-nous en génération m-2? Nous avons déjà observé que le VVgén. m-1doit être analysé comme (a)V V(I).

Supposons que nous prenions a=2: (...V)?I IIV VI...En fait, cela doit être ...VI IIV VI..., bien que cette direction Vpuisse faire partie de IV; donc dans la génération précédente, nous avons soit (...V)? IIII VV IIIII...ou (...V)? IIIII VV IIIII. Dans les deux cas, nous rencontrons des problèmes avec VVIIIII: la seconde Vdoit être une longueur de course, mais ...VI IIII...nécessite ensuite une paire suivante (longueur de course, chiffre) avec le même chiffre.

Il faut donc a=1: (...V)?II IV VI.... Puisque la génération mest la première avec une série de six Is, cela doit être le cas (...V)? II IV VI..., de sorte que la génération l' m-2est (...V)? I V IIIII.... ...VIVIIIII...est impossible: cependant on choisit d'interpréter la seconde Von se retrouve avec deux paires consécutives (run-length, digit) avec le même digit.

Par conséquent, la génération m-2doit être ^IVIIIII...analysée comme ^IV IIII I(V)...ou ^IV III II(V).... Ceux-ci donnent respectivement la génération m-3comme ^V III V ...ou ^V II VV....

Mais si nous regardons le début des chaînes commençant par la première commençant par V, nous obtenons un cycle:

    VI IV I...
    IV III IV ...
    II IV IVI ...
    IIII IV II IV ...

et donc aucune génération ne commence jamais avec VIIIVou VIIVV. Nous devons conclure qu'il n'y en a pas m.

Dissection

"I"          e# Initial generation
{            e# Loop...
  e`         e#   Run-length encode
  {          e#   Foreach [run-length char] pair...
    (        e#     Extract the run-length r
    4md1$^   e#     Get the number of Vs and the number of Is
             e#     The number of Vs is r/4 ; the number of Is is (r%4)^(r/4)
    'I*\'V*@ e#     Repeat strings the appropriate number of times and reorder
  }%
  e_         e#  Flatten to a simple string
}ri*         e# ... n times, where n is taken from stdin
Peter Taylor
la source
6

Python 3, 195 octets

Il y a beaucoup d'octets perdus sur les chiffres romains, donc il y a probablement du golf à faire là-bas.

Merci à @ El'endiaStarman, @ Sherlock9 et @Shooqie

import re
def f(x,r=""):
 for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*a
 return r
s="I"
for i in[0]*int(input()):print(s);s=re.sub(r'(.)\1*',lambda m:f(len(m.group()))+m.group()[0],s)

Ideone it!

Beta Decay
la source
Vous pouvez omettre les crochets:for v,i in(5,"V"),(4,"IV"),(1,"I")
shooqie
@shooqie Je ne savais pas que vous pouviez faire ça: D
Beta Decay
for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*aenregistre un octet.
Sherlock9
@ βετѧΛєҫαγ: De plus, vous ne semblez pas utiliser i(comme dans for i in range(...)). J'ai essayé de barboter, execmais cela s'est échappé 1dans la méthode «sub» semble perturber le code, je n'ai pas pu trouver de solution.
shooqie
@shooqie Je l'ai raccourci un peu en me débarrassant derange
Beta Decay
4

R, 110 107 Octets

as.romancombiné avec rlerend cela facile. Abus de portée et comportement de chat intégré de <<-sauvegarde quelques octets.

x="I"
replicate(scan(),{r=rle(strsplit(x,"")[[1]])
x<<-paste(rbind(paste(as.roman(r$l)),r$v),collapse="")})

Prend N depuis la console. Produit les 2 à N premiers termes de séquence (ce qui, je crois, est conforme aux spécifications ...)

 [1] "II"                                                                                                                                                                                                                                     
 [2] "III"                                                                                                                                                                                                                                    
 [3] "IIII"                                                                                                                                                                                                                                   
 [4] "IVI"                                                                                                                                                                                                                                    
 [5] "IIIVII"                                                                                                                                                                                                                                 
 [6] "IIIIIVIII"                                                                                                                                                                                                                              
 [7] "VIIVIIII"                                                                                                                                                                                                                               
 [8] "IVIIIIVIVI"                                                                                                                                                                                                                             
 [9] "IIIVIVIIVIIIVII"                                                                                                                                                                                                                        
[10] "IIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                                               
[11] "VIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                                                
[12] "IVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                                                          
[13] "IIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                                                                   
[14] "IIIIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                      
[15] "VIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                 
[16] "IVIIIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                         
[17] "IIIVIVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                            
[18] "IIIIIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                           
[19] "VIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                              
[20] "IVIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                    
[21] "IIIVIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                             
[22] "IIIIIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIIVIVIIVIIIIIVVIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                      
[23] "VIIVIIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVVIIVIIIVIIIIVVIIIVIIIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                   
[24] "IVIIIIVVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIIVIIIIVIIIIIVIVIIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                             
[25] "IIIVIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIVIIVVIIVIIIVIIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"
Vlo
la source
1

JavaScript (ES6), 107

Fonction récursive renvoyant le Nème terme basé sur 0

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

Tester

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

function update() {
  O.textContent=f(I.value)
}

update()
<input id=I value=25 type=number oninput='update()'><pre id=O></pre>

edc65
la source
1

Perl 6 , 62 octets

{("I",{S:g/(.)$0*/{<I II III IV V>[$/.chars-1]~$0}/}...*)[$_]}

Fonction anonyme qui accepte un index de base zéro.

Utilise le fait que les nombres romains supérieurs à 5 ne sont pas nécessaires, car les seuls groupes de chiffres répétitifs qui peuvent se produire sont:

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

( essayez-le en ligne )

smls
la source