Fibonacci Sexagesimals

15

Leonardo da Pisano alias Fibonacci war maßgeblich an der Einführung des hindu-arabischen Zahlensystems in Europa beteiligt. Davor arbeiteten dort Mathematiker in der Basis 60 mit römischen Ziffern.

Zum Beispiel könnte die Quadratwurzel von zwei wie folgt approximiert werden: ein und vierundzwanzig Teile von sechzig und einundfünfzig Teile von dreitausendsechshundert , und wie folgt geschrieben werden: i xxiv li , wobei die Skalierung durch den Kontext bestimmt wird. Zu dieser Zeit war „Nichts“ bekannt ( dh Null), hatte aber keine Standarddarstellung in diesem Zahlensystem.

Hätte Fibonacci diese neuen Nachkommastellen ignoriert, die er auf seinen Reisen angetroffen hatte, hätte er mit Sicherheit die Mängel des derzeitigen Systems behoben. Dieses verbesserte System nennen wir Fibonacci Sexagesimals .

Ihre Aufgabe ist es, ein Programm-, Funktions- oder Code-Snippet zu schreiben, das eine Gleitkommazahl im ASCII- oder Binärformat annimmt und in römischen Zahlen zur Basis 60 ausgibt. Die Eingabe kann eine Datei, eine Konsole, eine Befehlszeile oder ein Funktionsargument sein, und die Ausgabe kann eine Datei oder eine Konsole sein, je nachdem, was am einfachsten ist.

Die Ausgabe kann in Groß- oder Kleinschreibung erfolgen und muss die folgenden Verbesserungen enthalten:

  • Verwenden Sie n oder N , um null anzugeben. Dies bedeutet, dass ein Ort keinen Wert hat, dh „null“ (ein Problem mit dem System).
  • Verwenden Sie e oder E , um et anzugeben , das dem Sexagesimalpunkt entspricht (ein weiteres Problem mit dem System).
  • Verwenden Sie einen mittleren Punkt · oder ein Sternchen *, um Gruppen von römischen Ziffern zu trennen (ein weiteres Problem mit dem System)

Angenommen, die Eingabe ist ein Gleitkommawert mit einer Mantisse, die nicht größer als lix · lix · lix · lix · lix ist . Brüche kleiner als n · e · n · n · n · n · i können ignoriert werden. Unter der Voraussetzung, dass die Eingabe diese Einschränkungen aufweist, können maximal zehn Gruppen von römischen Ziffern mit einem e ausgegeben werden.

Zahlen, die kleiner sind als ich, müssen ein führendes n · e haben, um sicherzustellen, dass der Kontext klar ist.

Einige Beispiele: inputAusgabe

  • 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

Der Ausgang muss unnötige führende n · im Mantissenteil, isolierte e oder nachfolgende · n im Bruchteil des Ausgangs vermeiden . So sind beispielsweise n · n · n · n · i , i · e und i · e · n · n · n · n · n falsche Ausgaben für eine Eingabe von 1.

Unterschiede von plus oder minus n · e · n · n · n · n · i in der Ausgabe liegen innerhalb der Toleranzen und sind akzeptabel.

Die Eingabe ist ein zulässiger Gleitkommawert in der Sprache Ihrer Wahl. Sie kann also positive oder negative Exponenten enthalten, sofern die Eingabe nicht außerhalb des oben angegebenen Bereichs liegt.

Und schließlich römische Ziffer Einbauten sind erlaubt!


quelle
1
So sehr ich die Geschichte liebe, ist Fibonacci speziell für die Fibonacci-Sequenz reserviert, es sei denn, Sie möchten das Tag-Wiki ändern ...
Addison Crump
Tag ist für "Leonardo Fibonacci ist vor allem für die Fibonacci-Sequenz (0, 1, 1, 2, 3, 5, 8, 13, ...) bekannt."
Ich denke, diese Herausforderung sollte ein paar Informationen darüber enthalten, wie römische Ziffern funktionieren und wie sie ablaufen, um in sich geschlossen zu sein.
Liam
1
Das ist nicht die beabsichtigte Verwendung. Ich habe den Tag-Wiki-Auszug bearbeitet, um dies widerzuspiegeln.
Dennis

Antworten:

1

Python 3, 323 319 320 Bytes

Diese Antwort implementiert Fibonaccis Sexagesimale mit dem Begrenzer *und ohne Rücksicht auf Kolmogorovs Komplexität in den Listen der römischen Ziffern (zumindest für den Moment). Es wurde versucht, die Schleife whileund zu verbinden for, unter der die römischen Ziffern unter einer Schleife erzeugt werden. Diese Versuche waren jedoch noch nicht erfolgreich. Alle Golftipps und Vorschläge sind willkommen und geschätzt.

Edit: Bugfixing und Golfen.

Edit: Mehr Fehlerbehebung.

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)

Ungolfed:

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)
Sherlock9
quelle
3

C - 584 Bytes

Nicht konkurrierend (offensichtlich), sondern als 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;}

Speichern unter fs.c, Erstellen mit gcc -o fs fs.c -lmund Ausführen als ./fs <arg>.

Testfälle:

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

Größte Mantisse und Fraktion:

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

Ich verwende doubleals Arbeitstyp, daher übersteigt die größte kombinierte Mantisse und Fraktion die native Genauigkeit dieses Typs. Wenn ich es long doublestattdessen verwenden würde, könnte es damit umgehen.


quelle
int mainmuss nicht zurückkehren 0.
Zacharý
0

Haskell ( 333 322 315 Byte)

Mir ist nicht klar, ob die letzte Sexagesimalziffer bei mir gerundet werden soll oder ob das Abschneiden erlaubt ist. das schneidet ab, ich denke das könnte man bei python3 auch?

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 Bytes, dank H.PWiz ! -2 Bytes durch den Wegfall wherefür (\->)$, -5 mehr durch diese erfinden dFunktion und Golf a++"."++xzu a++'.':x.)

Ungolfed:


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

Die Methode, ganze Zahlen in römische Zahlen umzuwandeln, wurde Thomas Ahle auf StackOverflow schamlos gestohlen und nur ein wenig golfen.

CR Drost
quelle
["l","xl","x","ix","v","iv","i"]kann seinwords"l xl x ix v iv i"
H.PWiz
@ H.PWiz danke, aufgenommen!
CR Drost