Sexagesimals Fibonacci

15

Leonardo da Pisano alias Fibonacci berperan penting dalam membawa sistem angka Hindu-Arab ke Eropa. Sebelum itu, matematikawan di sana bekerja di basis enam puluh dengan angka Romawi.

Sebagai contoh, akar kuadrat dari dua dapat diperkirakan sebagai: satu dan dua puluh empat bagian dari enam puluh dan lima puluh satu bagian dari tiga ribu enam ratus , dan ditulis sebagai: i xxiv li , dengan penskalaan ditentukan oleh konteks. Pada saat itu, "ketiadaan" diketahui ( yaitu nol), tetapi tidak memiliki representasi standar dalam sistem angka ini.

Seandainya Fibonacci mengabaikan angka desimal yang baru saja dia temui selama perjalanannya, dia pasti akan mengatasi kekurangan dalam sistem saat ini. Sistem yang lebih baik ini kita sebut seksagesimal Fibonacci .

Tugas Anda adalah menulis potongan program, fungsi, atau kode yang mengambil angka floating point dalam ASCII atau format biner dan menghasilkan enam puluh angka Romawi dasar. Input dapat berupa file, konsol, baris perintah atau argumen fungsi dan output dapat berupa file atau konsol, mana yang paling mudah.

Outputnya bisa huruf besar atau kecil, dan harus mencakup perbaikan ini:

  • gunakan n atau N untuk menunjukkan nol yang berarti suatu tempat tidak memiliki nilai, yaitu "nol" (masalah dengan sistem)
  • gunakan e atau E untuk menunjukkan et yang sesuai dengan titik seksagesimal (masalah lain dengan sistem)
  • gunakan titik tengah · atau tanda bintang * untuk memisahkan kelompok angka Romawi (masalah lain dengan sistem)

Asumsikan input adalah floating point dengan mantissa tidak lebih besar dari lix · lix · lix · lix · lix . Pecahan kurang dari n · e · n · n · n · n · saya dapat diabaikan. Jadi, asalkan input memiliki batasan ini, paling banyak sepuluh kelompok angka Romawi dengan satu e dapat dihasilkan.

Angka kurang dari saya harus memiliki n · e terkemuka untuk memastikan konteksnya jelas.

Beberapa contoh: inputoutput

  • 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

Keluaran harus menghindari pengarah n · yang tidak perlu pada bagian mantissa, mengisolasi e , atau mengeklik · n pada bagian fraksional dari keluaran. Jadi misalnya, n · n · n · n · i , i · e , dan saya · e · n · n · n · n · n · n adalah output yang salah untuk input 1.

Perbedaan plus atau minus n · e · n · n · n · n · i dalam output berada dalam toleransi dan dapat diterima.

Input adalah sembarang titik apung dalam bahasa pilihan Anda, jadi dapat menyertakan eksponen positif atau negatif selama input tidak berada di luar kisaran yang ditentukan di atas.

Dan akhirnya, angka Romawi built-in yang diperbolehkan!


sumber
1
Seperti saya suka sejarah, fibonacci dicadangkan khusus untuk urutan fibonacci, kecuali jika Anda ingin mengubah tag wiki ...
Addison Crump
Tag adalah untuk "Leonardo Fibonacci sebagian besar dikenal untuk urutan fibonacci (0, 1, 1, 2, 3, 5, 8, 13, ...).", Jadi bisa dikatakan itu dimaksudkan untuk orang tersebut.
Saya pikir tantangan ini harus memiliki sedikit info tentang bagaimana angka romawi bekerja dan proses yang terlibat, hanya untuk menjadi mandiri.
Liam
1
Itu bukan tujuan penggunaannya. Saya telah mengedit kutipan tag wiki untuk mencerminkan ini.
Dennis

Jawaban:

1

Python 3, 323 319 320 byte

Jawaban ini menerapkan seksagesimal Fibonacci dengan pembatas *dan tanpa memperhatikan kompleksitas Kolmogorov dalam daftar angka Romawi (untuk saat ini, setidaknya). Upaya dilakukan untuk bergabung dengan whiledan forloop di mana angka-angka Romawi dihasilkan di bawah satu loop, tetapi upaya-upaya tersebut belum berhasil. Setiap tips dan saran bermain golf disambut dan dihargai.

Sunting: Memperbaiki bug dan bermain golf.

Edit: Lebih banyak perbaikan bug.

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)

Tidak Disatukan:

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
sumber
3

C - 584 byte

Non-bersaing (jelas), tetapi berfungsi sebagai inspirasi:

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

Simpan sebagai fs.c, bangun dengan gcc -o fs fs.c -lm, dan jalankan sebagai ./fs <arg>.

Kasus uji:

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

Mantera dan fraksi terbesar:

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

Saya menggunakan doublesebagai tipe kerja, jadi mantissa dan fraksi gabungan terbesar melebihi akurasi asli dari tipe itu. Jika saya menggunakan long doubleitu bisa menanganinya.


sumber
int maintidak harus kembali 0.
Zacharý
0

Haskell ( 333 322 315 bytes)

Saya tidak jelas apakah digit sexagesimal terakhir seharusnya dibulatkan ketika saya lakukan atau apakah pemotongan diizinkan; ini memotong, saya pikir yang Python3 mungkin juga?

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, berkat H.PWiz ! -2 byte dengan menghilangkan whereuntuk (\->)$, -5 lainnya menciptakan ini dfungsi dan golf a++"."++xuntuk a++'.':x.)

Tidak Disatukan:


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

Metode mengkonversi bilangan bulat ke angka romawi dicuri tanpa malu-malu dari Thomas Ahle di StackOverflow dan hanya bermain golf sedikit.

CR Drost
sumber
["l","xl","x","ix","v","iv","i"]bisawords"l xl x ix v iv i"
H.PWiz
@ H.PWiz terima kasih, dimasukkan!
CR Drost