Сексуальные числа Фибоначчи

15

Леонардо да Пизано, он же Фибоначчи, сыграл важную роль в распространении индуистско-арабской системы счисления в Европе. До этого там математики работали в базе шестидесяти с римскими цифрами.

Например, квадратный корень из двух может быть аппроксимирован как: одна и двадцать четыре части по шестьдесят и пятьдесят одна часть по три тысячи шестьсот и записан как: i xxiv li , с масштабированием, определяемым контекстом. В то время «ничто» было известно ( то есть ноль), но не имело стандартного представления в этой системе счисления.

Если бы Фибоначчи проигнорировал эти новомодные десятичные цифры, с которыми он столкнулся во время своих путешествий, он, несомненно, исправил бы недостатки существующей системы. Эту улучшенную систему мы назовем шестигранными числами Фибоначчи .

Ваша задача - написать программу, функцию или фрагмент кода, который принимает число с плавающей запятой в ASCII или двоичном формате и выводит его из шестидесяти римских цифр. Входными данными может быть файл, консоль, командная строка или аргумент функции, а выходные данные могут быть файловыми или консольными, в зависимости от того, что проще всего.

Выходные данные могут быть в верхнем или нижнем регистре и должны включать следующие улучшения:

  • использовать п или N , чтобы указать нуль означает место , не имеет значения, то есть «ноль» (проблема с системой)
  • используйте e или E для обозначения et, соответствующего сексуальной точке (другая проблема с системой)
  • используйте среднюю точку · или звездочку * для разделения групп римских цифр (еще одна проблема с системой)

Предположим, что ввод будет с плавающей точкой с мантиссой не больше, чем lix · lix · lix · lix · lix . Фракции, меньшие чем n · e · n · n · n · n · i, можно игнорировать. Таким образом, при условии, что ввод имеет эти ограничения, можно вывести не более десяти групп римских цифр с одним знаком e .

Числа, меньшие, чем я, должны иметь начальное n, чтобы гарантировать ясность контекста.

Некоторые примеры: inputвывод

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

Выходные данные должны избегать ненужного начального n · в части мантиссы, изолированной e или конечного · n в дробной части выхода. Так, например, n · n · n · n · i , i · e и i · e · n · n · n · n · n являются неправильными выходами для входа 1.

Различия плюс или минус n · e · n · n · n · n · i в выходных данных находятся в пределах допуска и допустимы.

Входными данными являются любые допустимые значения с плавающей запятой на выбранном вами языке, поэтому они могут включать положительные или отрицательные показатели, если входные данные не выходят за пределы указанного выше диапазона.

И , наконец, римская цифра Модульное будут разрешены!


источник
1
Как бы я ни любил историю, fibonacci зарезервирован специально для последовательности fibonacci, если только вы не хотите изменить тег wiki ...
Addison Crump
Тег для «Леонардо Фибоначчи в основном известен по последовательности Фибоначчи (0, 1, 1, 2, 3, 5, 8, 13, ...).», Так сказать, это предназначено для человека.
Я думаю, что этот вызов должен иметь немного информации о том, как работают римские цифры и процесс, просто чтобы быть автономным.
Лиам
1
Это не по назначению. Я отредактировал отрывок тега вики, чтобы отразить это.
Деннис

Ответы:

1

Python 3, 323 319 320 байт

Этот ответ реализует шестнадцатеричные числа Фибоначчи с разделителем *и без учета сложности Колмогорова в списках римских цифр (на данный момент, по крайней мере). Были сделаны попытки присоединиться whileи forцикл , при котором римские цифры генерируются под одной петле, но эти попытки пока не увенчались успехом. Любые советы и предложения по гольфу приветствуются и приветствуются.

Редактировать: Исправление ошибок и гольф.

Редактировать: Больше исправления ошибок.

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
источник
3

C - 584 байта

Не конкурирует (очевидно), но служит источником вдохновения:

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

Сохранить как fs.c, построить с gcc -o fs fs.c -lmи запустить как ./fs <arg>.

Тестовые случаи:

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

Самая большая мантисса и фракция:

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

Я использую doubleв качестве рабочего типа, так что наибольшая мантисса и фракция в совокупности превышают естественную точность этого типа. Если бы я использовал long doubleвместо этого, он мог бы справиться с этим.


источник
int mainне должен возвращаться 0.
Захари
0

Haskell ( 333 322 315 байт)

Мне неясно, должна ли округляться последняя шестнадцатеричная цифра, когда я делаю, или разрешено усечение; это усекает, я думаю, что Python3 тоже может?

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 байтов, спасибо H.PWiz ! -2 байта, исключив whereдля (\->)$, -5 больше, изобретая эту dфункцию и играя a++"."++xв гольф 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))

Метод преобразования целых чисел в римские цифры был бесстыдно украден у Томаса Але на StackOverflow и немного поиграл в гольф.

ЧР Дрост
источник
["l","xl","x","ix","v","iv","i"]может бытьwords"l xl x ix v iv i"
H.PWiz
@ H.PWiz спасибо, включены!
ЧР Дрост