Les sexagésimaux de Fibonacci


15

Leonardo da Pisano alias Fibonacci a joué un rôle déterminant dans l'introduction du système numérique hindou-arabe en Europe. Avant cela, les mathématiciens y travaillaient en base soixante avec des chiffres romains.

Par exemple, la racine carrée de deux peut être approximée comme suit: une et vingt-quatre parties de soixante et cinquante et une parties de trois mille six cents , et écrite comme: i xxiv li , avec la mise à l'échelle déterminée par le contexte. À l'époque, le «néant» était connu ( c.-à-d. Zéro), mais n'avait aucune représentation standard dans ce système numérique.

Si Fibonacci avait ignoré ces nouveaux chiffres décimaux qu'il avait rencontrés au cours de ses voyages, il aurait sûrement corrigé les lacunes du système actuel. Ce système amélioré, nous l'appellerons les sexagésimaux de Fibonacci .

Votre tâche consiste à écrire un programme, une fonction ou un extrait de code qui prend un nombre à virgule flottante au format ASCII ou binaire et qui sort en base soixante chiffres romains. L'entrée peut être un fichier, une console, une ligne de commande ou un argument de fonction et la sortie peut être un fichier ou une console, selon ce qui est le plus simple.

La sortie peut être en majuscules ou en minuscules et doit inclure les améliorations suivantes:

  • utilisez n ou N pour indiquer une signification nulle, un lieu n'a aucune valeur, c'est-à - dire «zéro» (un problème avec le système)
  • utilisez e ou E pour indiquer et correspondant au point sexagésimal (autre problème avec le système)
  • utiliser un point central · ou un astérisque * pour séparer les groupes de chiffres romains (encore un autre problème avec le système)

Supposons que l'entrée sera en virgule flottante avec une mantisse non supérieure à lix · lix · lix · lix · lix . Les fractions inférieures à n · e · n · n · n · n · i peuvent être ignorées. Donc, à condition que l'entrée ait ces restrictions, au plus dix groupes de chiffres romains avec un e peuvent être sortis.

Les nombres inférieurs à i doivent être précédés d'un n · e pour garantir que le contexte est clair.

Quelques exemples: inputsortie

  • 0n
  • 1i
  • 60i · n
  • 0.1n · e · vi
  • 3600i · n · n
  • 10.5x · e · xxx
  • 16777215i · xvii · xl · xx · xv
  • 3.1415926536iii · e · viii · xxix · xliv · n · xlvii

La sortie doit éviter les n · de tête inutiles dans la partie mantisse, les e isolés ou les traînants · n dans la partie fractionnaire de la sortie. Ainsi, par exemple, n · n · n · n · i , i · e et i · e · n · n · n · n · n sont des sorties incorrectes pour une entrée de 1.

Les différences de plus ou moins n · e · n · n · n · n · i dans la sortie sont dans les tolérances et acceptables.

L'entrée est une virgule flottante légale dans la langue de votre choix, elle peut donc inclure des exposants positifs ou négatifs tant que l'entrée ne sort pas de la plage spécifiée ci-dessus.

Et enfin, les inserts en chiffres romains sont autorisés!


1
Autant que j'aime l'histoire, fibonacci est réservé spécifiquement à la séquence fibonacci, à moins que vous ne souhaitiez changer le tag wiki ...
Addison Crump

Tag est pour "Leonardo Fibonacci est surtout connu pour la séquence fibonacci (0, 1, 1, 2, 3, 5, 8, 13, ...).", Dirait donc qu'il est destiné à la personne.

Je pense que ce défi devrait avoir un peu d'informations sur le fonctionnement des chiffres romains et le processus impliqué, juste pour être autonome.
Liam

1
Ce n'est pas l'usage prévu. J'ai édité l'extrait wiki du tag pour refléter cela.
Dennis

Réponses:


1

Python 3, 323 319 320 octets

Cette réponse implémente les sexagésimaux de Fibonacci avec le délimiteur *et sans égard à la complexité de Kolmogorov dans les listes de chiffres romains (pour le moment du moins). Des tentatives ont été faites pour joindre la boucle whileet forsous laquelle les chiffres romains sont générés sous une boucle, mais ces tentatives n'ont pas encore rencontré le succès. Tous les conseils et suggestions de golf sont les bienvenus et appréciés.

Edit: correction de bugs et golf.

Edit: Plus de correction de bugs.

def f(x):
 v=divmod;f=x%1;n=int(x);d=",I,II,III,IV,V,VI,VII,VIII,IX".split(",");t=",X,XX,XXX,XL,L".split(",");z=["N"];a=f>0;s=z*0**n+["E"]*a
 while n:n,m=v(n,60);j,k=v(m,10);s=[z,[t[j]+d[k]]][m>0]+s
 for i in range(5*a):m,f=v(f*60,1);j,k=v(int(m),10);s+=[z,[t[j]+d[k]]][m>0]
 while s[-1:]==z*a:s.pop()
 return"*".join(s)

Non golfé:

def f(x):
    integ = int(x)
    frac = x % 1
    units=",I,II,III,IV,V,VI,VII,VIII,IX".split(",")
    tens=",X,XX,XXX,XL,L".split(",")
    zero = ["N"]
    output = []
    a = frac != 0
    if integ == 0:
        output += z
    if a:
        output += ["E"]
    while integ > 0:
        integ, digit = divmod(integ, 60)
        j, k = divmod(int(digit), 10)
        if digit:
            output += [tens[j], units[k]]
        else:
            output += zero
    for i in range(5*a):
        digit, frac = divmod(frac*60, 1)
        j, k = divmod(int(digit), 10)
        if digit:
            output += [tens[j], units[k]]
        else:
            output += zero
    while output[-1:] == zero * a:
        output.pop()
    return "*".join(output)

3

C - 584 octets

Non compétitif (évidemment), mais pour servir d'inspiration:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
char*f(int z){static char r[8];char*l[]={"","I","II","III","IV","V","VI","VII","VIII","IX"},*h[]={"","X","XX","XXX","XL","L"};if(!z)return"N";sprintf(r,"%s%s",h[z/10],l[z%10]);return r;}int main(int c,char**v){char*s="";int i,j,z[10],k=60;long x;double d,y;y=modf(atof(v[1]),&d);x=d;for(i=4;i>=0;i--){z[i]=x%k;x/=k;}for(i=5;i<=9;i++){z[i]=(y*=k);y-=z[i];}for(i=0;!z[i]&&i<4;i++);for(;i<5;i++){printf("%s%s",s,f(z[i]));s="*";}for(j=9;!z[j]&&j>=i;j--);if(i<=j)printf("*E");for(;i<=j;i++)printf("*%s",f(z[i]));printf("\n");return 0;}

Enregistrez sous fs.c, créez avec gcc -o fs fs.c -lmet exécutez sous ./fs <arg>.

Cas de test:

$ ./fs 0
N
$ ./fs 1
I
$ ./fs 60
I*N
$ ./fs 0.1
N*E*VI
$ ./fs 3600
I*N*N
$ ./fs 10.5
X*E*XXX
$ ./fs 16777215
I*XVII*XL*XX*XV
$ ./fs 3.1415926536
III*E*VIII*XXIX*XLIV*N*XLVII

Plus grande mantisse et fraction:

$ ./fs 777599999
LIX*LIX*LIX*LIX*LIX
$ ./fs 0.999999998713992
N*E*LIX*LIX*LIX*LIX*LIX

J'utilise doublecomme type de travail, donc la plus grande mantisse et fraction combinée dépasse la précision native de ce type. Si j'utilisais à la long doubleplace, il pourrait le gérer.


int mainn'a pas à revenir 0.
Zacharý

0

Haskell ( 333 322 315 octets)

Je ne sais pas si le dernier chiffre sexagésimal est censé être arrondi lorsque je le fais ou si la troncature est autorisée; cela tronque, je pense que celui de Python3 pourrait aussi?

d n f 0=n;d n f x=f x
x!n=60*(x-fromInteger n)
f 0=[];f x=(\n->n:f(x!n))$floor x
l 0=[];l x=(\(d,m)->l d++[m])$divMod x 60
v=[50,40,10,9,5,4,1]
n&i|n==0=""|n>=v!!i=words"l xl x ix v iv i"!!i++(n-v!!i)&i|True=n&(i+1)
q=foldl1(\a x->a++'.':x).map(d"n"(&0))
p x=(\n->d"n"(q.l)n++d""((".e."++).q.take 5.f)(x!n))$floor x

(-9 octets, merci H.PWiz ! -2 octets en éliminant wherepour (\->)$, -5 de plus en inventant cette dfonction et en jouant a++"."++xau golf a++'.':x.)

Non golfé:


-- this function gets called `d` for default
onZero :: (Eq n, Num n) => z -> (n -> z) -> n -> z
onZero def f x 
 | x == 0    = def
 | otherwise = f x 

-- this function gets called `f`
fracPart :: RealFrac a => a -> [Integer]
fracPart x
  | x == 0    = [] 
  | otherwise = n : fracPart (60 * (x - fromInteger n))
    where n = floor x

-- this function gets called `l`
leadPart :: Integral n => n -> [Integer]
leadPart x
  | x == 0    = [] 
  | otherwise = leadPart div ++ [ mod ]
    where (div, mod) = x `divMod` 60

-- these get called `v`
romanValues :: [Integer]
romanValues = [50, 40, 10, 9, 5, 4, 1]

-- these get inlined with `words`, and correspond to the values above
romanLetters :: [String]
romanLetters = ["l", "xl", "x", "ix", "v", "iv", "i"]

-- this becomes (&)
romanNumeralLoop :: Integer -> Int -> String
romanNumeralLoop n i
 | n == 0                  = "" 
 | n >= (romanValues !! i) = (romanLetters !! i) ++ romanNumeralLoop (n - (romanValues !! i)) i
 | otherwise               = romanNumeralLoop n (i + 1)

-- this becomes `q`
concatRomanWithDots :: [Integer] -> String
concatRomanWithDots numbers = concatWithDots (map toRoman numbers)
  where 
    toRoman = onZero "n" (\x -> romanNumeralLoop x 0)
    concatWithDots = foldl1 concatDot
    concatDot acc item = acc ++ "." ++ item

-- this becomes `p`
solve x = onZero "n" elseRomanizeLeadPart n ++ onZero "" elseRomanizeFracPart f
  where
    n = floor x
    f = 60 * (x - fromInteger n) 
    elseRomanizeLeadPart l = concatRomanWithDots (leadPart l)
    elseRomanizeFracPart f = ".e." ++ concatRomanWithDots (take 5 (fracPart f))

La méthode de conversion des entiers en chiffres romains a été volée sans vergogne à Thomas Ahle sur StackOverflow et vient de jouer un peu au golf .


["l","xl","x","ix","v","iv","i"]peut êtrewords"l xl x ix v iv i"
H.PWiz

@ H.PWiz merci, incorporé!
CR Drost
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.