斐波那契的六进制


15

莱昂纳多·达·皮萨诺 Leonardo da Pisano)名斐波那契 Fibonacci)在将印度-阿拉伯数字系统引入欧洲方面发挥了作用。在此之前,那里的数学家使用罗马数字以60为底数。

例如,两个的平方根可以近似为:一和二十四分之六十和五十一分之三千六百六十,写为:i xxiv li,其缩放比例取决于上下文。当时,“虚无”是已知的(零),但在此数字系统中没有标准表示形式。

如果斐波那契忽略了他在旅途中遇到的这些新的十进制数字,他肯定会解决当前系统中的缺陷。这个改进的系统称为斐波那契(Fibonacci)的sexagesimals

您的任务是编写一个程序,函数或代码片段,该片段采用ASCII或二进制格式的浮点数,并以60个基数罗马数字输出。输入可以是文件,控制台,命令行或函数参数,输出可以是文件或控制台,以最简单的为准。

输出可以是大写或小写,并且必须包括以下改进:

  • 使用nN表示值,表示某个地点没有值, “零”(系统存在问题)
  • 使用ëë以指示对应于所述六十进制点(与系统的另一个问题)
  • 使用中间的点·或星号*分隔罗马数字组(但系统还有另一个问题)

假设输入将是浮点数,尾数不大于lix·lix·lix·lix·lix。小于n·e·n·n·n·n·i的分数可以忽略。因此,如果输入具有这些限制,则最多可以输出十组带有一个e的罗马数字。

小于i的数字必须以n开头,以确保上下文清晰。

一些示例:input输出

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

输出必须避免在输出的尾数部分中不必要的前导,孤立的e或末尾的n。因此,例如,n·n·n·n·ii·ei·e·n·n·n·n·n是输入的不正确输出1

输出中正负n·e·n·n·n·n·i的差在允许范围内且可以接受。

输入是您选择的语言中的任何合法浮点,因此只要输入不超出上述指定范围,就可以包含正或负指数。

最后,罗马数字内置插件不允许的!


1
就我所钟爱的历史而言,斐波那契是专门为斐波那契序列保留的,除非您想更改标签Wiki ...
Addison Crump

标签是“ Leonardo Fibonacci最著名的斐波那契数列(0、1、1、2、3、5、8、13,...)。”,因此可以说这是给这个人的意思。

我认为这个挑战应该有一些关于罗马数字如何工作以及所涉及的过程的信息,这是自成一体的。
利亚姆

1
那不是预期的用途。我已经编辑了标签维基摘录来反映这一点。
丹尼斯

Answers:


1

Python 3中,323个 319 320字节

此答案使用定界符实现了斐波那契的六进制,*并且不考虑罗马数字列表中的Kolmogorov复杂性(至少现在是这样)。尝试加入whileand 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)

取消高尔夫:

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字节

不竞争(很明显),但可以作为启发:

#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.5个字节a++'.':x。)

取消高尔夫:


-- 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上Thomas Ahle偷偷偷走的,只是打了一点高尔夫球。


["l","xl","x","ix","v","iv","i"]可以words"l xl x ix v iv i"
-H.PWiz

@ H.PWiz,谢谢!
CR Drost
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.