将数字从Zeckendorf表示形式转换为十进制


18

关于Zeckendorf表示形式/基本斐波那契数

这是一个以斐波那契数为基础的数字系统。数字由0和1组成,每个1表示该数字包含相应的斐波那契数,而0表示不包含。

例如,让我们将所有<= 10的自然数转换为基本斐波那契数。

  • 1将成为1,因为它是1的总和,这是一个斐波那契数,

  • 2将变为10,因为它是2的总和,这是一个斐波那契数,并且不需要1,因为我们已经实现了所需的总和。

  • 3将变为100,因为它是3的总和,这是一个斐波那契数,它不需要2或1,因为我们已经实现了所需的总和。

  • 4将成为101,因为它是[3,1]的和,两者均为斐波那契数。
  • 5将成为1000,因为它是5的总和,这是一个斐波纳契数,我们不需要任何其他数。
  • 6是1001,因为它是斐波那契数5和1的总和。
  • 7是1010,因为它是斐波那契数5和2的总和。
  • 8将成为10000,因为它是斐波那契数。
  • 9将成为10001,因为它是斐波那契数8和1的总和。
  • 10将成为10010,因为它是斐波那契数8和2的总和。

让我们将一个随机的基本斐波那契数10101001010转换为十进制:首先,我们编写相应的斐波那契数。然后,我们计算1以下数字的总和。

 1   0   1   0   1   0   0   1   0   1   0
 144 89  55  34  21  13  8   5   3   2   1  -> 144+55+21+5+2 = 227.

阅读有关基本斐波那契数字的更多信息:link,它还有一个将正整数转换为基本斐波那契数字的工具。您可以尝试一下。

现在的问题:

您的任务是在Zeckendorf表示形式中获取一个数字,然后输出其十进制值。

输入是一个仅包含0和1的字符串(尽管您可以根据需要使用任何输入方式)。

以十进制输出一个数字。

测试用例:(格式为输入->输出)

 1001 -> 6
 100101000 -> 73
 1000000000 -> 89
 1001000000100100010 -> 8432
 1010000010001000100001010000 -> 723452

这是代码高尔夫球,因此最短的答案以字节为单位。

注意:输入将不包含任何前导0或连续1。


我们可以将输入作为位列表吗?
小麦巫师

像这样,将输入的ascii编码后再将其转换为二进制或类似的东西?
风车饼干

4
我们可以按LSB优先顺序输入吗?
Mego


1
@Mego是的,您可以
风车饼干

Answers:


19

出租车1987年1927字节

-60个字节,因为意识到换行符是可选的。

Go to Post Office:w 1 l 1 r 1 l.Pickup a passenger going to Chop Suey.Go to Chop Suey:n 1 r 1 l 4 r 1 l.[B]Switch to plan C if no one is waiting.Pickup a passenger going to Cyclone.Go to Cyclone:n 1 l 3 l.Pickup a passenger going to Narrow Path Park.Pickup a passenger going to Sunny Skies Park.Go to Zoom Zoom:n.Go to Sunny Skies Park:w 2 l.Go to Narrow Path Park:n 1 r 1 r 1 l 1 r.Go to Chop Suey:e 1 r 1 l 1 r.Switch to plan B.[C]1 is waiting at Starchild Numerology.1 is waiting at Starchild Numerology.Go to Starchild Numerology:n 1 l 3 l 3 l 2 r.Pickup a passenger going to Addition Alley.Pickup a passenger going to Cyclone.Go to Cyclone:w 1 r 4 l.[D]Pickup a passenger going to Addition Alley.Pickup a passenger going to Cyclone.Go to Addition Alley:n 2 r 1 r.Go to Cyclone:n 1 l 1 l.Pickup a passenger going to Multiplication Station.Go to Zoom Zoom:n.Go to Narrow Path Park:w 1 l 1 l 1 r.Switch to plan E if no one is waiting.Pickup a passenger going to The Babelfishery.Go to The Babelfishery:e 1 r.Pickup a passenger going to Multiplication Station.Go to Multiplication Station:n 1 r 2 l.Pickup a passenger going to Joyless Park.Go to Joyless Park:n 2 l 1 r 1 r.Go to Addition Alley:w 1 r 2 l 1 l.Pickup a passenger going to Cyclone.Go to Cyclone:n 1 l 1 l.Pickup a passenger going to Addition Alley.Switch to plan D.[E]Go to Addition Alley:w 1 l 1 r 1 l.Pickup a passenger going to Riverview Bridge.Go to Riverview Bridge:n 1 r.Go to Joyless Park:e 1 r 2 l.Pickup a passenger going to Addition Alley.[F]Switch to plan G if no one is waiting.Pickup a passenger going to Addition Alley.Go to Fueler Up:w 1 l.Go to Addition Alley:n 3 l 1 l.Pickup a passenger going to Addition Alley.Go to Joyless Park:n 1 r 1 r 2 l.Switch to plan F.[G]Go to Addition Alley:w 1 r 2 l 1 l.Pickup a passenger going to The Babelfishery.Go to The Babelfishery:n 1 r 1 r.Pickup a passenger going to Post Office.Go to Post Office:n 1 l 1 r.

在线尝试!

由于我最后没有返回出租汽车车库,老板解雇了我,因此退出时出现错误。


Joyless Park似乎是一个不错的去处
aloisdg说莫尼卡

好吧,它的字符数少于Sunny Skies Park
JosiahRyanW

11

Perl 6的28的23个字节

{[+] (1,2,*+*...*)Z*$_}

在线尝试!

匿名代码块,按LSB顺序获取1s和0s 的列表并返回数字。

说明:

{                     }   # Anonymous codeblock
 [+]                      # The sum of
     (1,2,*+*...*)        # The infinite Fibonacci sequence starting from 1,2
                  Z*      # Zip multiplied by
                    $_    # The input list in LSB form



4

Haskell,38个字节

f=1:scanl(+)2f
sum.zipWith(*)f.reverse

在线尝试!

将输入作为1和0的列表。

说明


f=1:scanl(+)2f

在变量中除第一个外,列出斐波那契数的列表f

sum.zipWith(*)f.reverse

取输入列表reverse,将每个条目乘以中的相应条目f,然后sum得到结果。

Haskell,30个字节

f=1:scanl(+)2f
sum.zipWith(*)f

在线尝试!

如果我们首先输入最低有效位,则不需要,reverse因此可以节省8个字节。


4

Python 2,43个字节

a=b=0
for x in input():b+=a+x;a=b-a
print b

在线尝试!

将输入作为列表。该更新是的较短版本a,b=b+x,a+b+x,就像a,b=b,a+b您忽略了Fibonacci更新一样x


Python 2,45个字节

f=lambda n,a=1,b=1:n and n%10*b+f(n/10,b,a+b)

在线尝试!

将输入作为十进制数字。


3

Pyth,13个字节

其中大多数(8个字节)仅生成斐波那契数。

s*V_m=+Z|~YZ1

尝试使用此测试套件!

说明:

s*V_m=+Z|~YZ1QQ     Autofill variables
    m=+Z|~YZ1Q      Generate the first length(input) Fibonacci numbers as follows:
       Z             Start with Z=0
         ~YZ         And Y=[] (update it to Y=Z, return old Y)
        |   1        if Y is [], then replace with 1
      +              Sum Z and Y
     =               Replace Z with sum
    m                Repeat process
             Q       once for each element of the input
   _                Reverse the order of the Fibonacci numbers
 *V                 Vectorize multiplication
s                   Sum


3

J24 14字节

#.~2+&%&1~#-#\

在线尝试!

深入研究了使用斐波那契混合基数的24字节版本。

怎么运行的

#.~2+&%&1~#-#\  Example input: y=1 0 0 1 0
          #-#\  Length minus 1-based indices; 4 3 2 1 0
   2     ~      Starting from 2, run the following (4,3,2,1,0) times:
    +&%&1         Given y, compute 1 + 1 / y
                The result is 13/8 8/5 5/3 3/2 2
#.~             Mixed base conversion of y into base above; 2+8=10

J,21字节

1#.|.*[:+/@(!~#-])\#\

在线尝试!

Galen Ivanov的25字节解决方案的改进版。

使用帕斯卡三角形的对角线总和,它等于二项式系数的总和:

Fñ=一世=0ññ-一世C一世

怎么运行的

1#.|.*[:+/@(!~#-])\#\
                       Example input: 1 0 0 1 0
                   #\  Generate 1-based index; 1 2 3 4 5
      [:          \    For each prefix of above... (ex. 1 2 3)
              #-]        Subtract each element from the length (ex. 2 1 0)
           (!~   )       Compute binomial coefficient (ex. 3C0 + 2C1 + 1C2)
        +/@              Sum
                       The result is Fibonacci numbers; 1 2 3 5 8
   |.*                 Multiply with mirrored self; 0 2 0 0 8
1#.                    Sum; 10

J,24个字节

3 :'y#.~|.(1+%)^:(<#y)2'

在线尝试!

单子词显式动词。生成代表Fibonacci基准的混合基准,然后将其输入基准转换#.

怎么运行的

y#.~|.(1+%)^:(<#y)2  Explicit verb, input: y = Fibonacci digit array, n = length of y
      (1+%)          x -> 1 + 1/x
           ^:(<#y)2  Apply the above 0..n-1 times to 2
                     The result looks like 2/1, 3/2, 5/3, 8/5, 13/8, ...
    |.               Reverse
                     Now, if it is fed into #. on the left, the digit values become
                     ...(8/5 * 5/3 * 3/2 * 2/1), (5/3 * 3/2 * 2/1), (3/2 * 2/1), 2/1, 1
                     which is ... 8 5 3 2 1 (Yes, it's Fibonacci.)
y#.~                 Convert y to a number using Fibonacci base

备择方案

J,27个字节

}.@(+#{.3#{.)^:(<:@#)@(,&0)

在线尝试!

这个想法:

 1  0  0  1  0  1
-1 +1 +1
------------------
    1  1  1  0  1
   -1 +1 +1
------------------
       2  2  0  1
      -2 +2 +2
------------------
          4  2  1
         -4 +4 +4
------------------
             6  5
            -6 +6 +6 <- Add an imaginary digit that has value 1
---------------------
               11  6
              -11+11
---------------------
                  17 <- the answer

J,30个字节

0.5<.@+(%:5)%~(-:>:%:5)#.,&0 0

在线尝试!

这是花了最大的力气建造的。使用带舍入技巧的闭式表达式。在表达式中,第0个和第1个值分别为0和1,因此实际的数字幂必须以2开头。

0.5<.@+(%:5)%~(-:>:%:5)#.,&0 0  Tacit verb.
                         ,&0 0  Add two zeroes at the end
              (-:>:%:5)#.       Convert to a number using base phi (golden ratio)
       (%:5)%~                  Divide by sqrt(5)
0.5<.@+                         Round to nearest integer

尽管误差(((1-sqrt(5))/2)^n项)可能会累积,但永远不会超过0.5,因此舍入技巧会达到无穷大。数学上:

最高|Ë[R[RØ[R|=1个51个1个-522ñ=1个501个-52ñ=5-1个25<1个2


不错的解决方案!我很高兴看到一个明确的动词击败了默认解决方案。
加伦·伊万诺夫

我试图找到一个较短的默认解决方案,但没有成功。现在25个字节。我用的是帕斯卡的三角形。
加伦·伊万诺夫

@GalenIvanov一年后重新审视挑战,我得到了一个新的,超短的默认解决方案:)
Bubbler

那很棒!我将在稍后详细介绍。
Galen Ivanov

2

MathGolf8 6个字节

{î)f*+

在线尝试!

说明

{        Start block (foreach in this case)
 î)      Push loop index (1-based) and increment by 1
   f     Get fibonacci number of that index
    *    Multiply with the array value (0 or 1)
     +   Add top two elements of stack. This implicitly pops the loop index the first iteration, which makes the addition become 0+a, where a is the top of the stack.

由于JoKing节省了1个字节,由于LSB排序节省了另一个字节。


LSB顺序确实是允许的。另外,-1个字节
Jo King

@JoKing当然,上周我什至实现了隐式加法...很好,现在MathGolf排名并列第一!
maxb

2

05AB1E11 9 8字节

vyiNÌÅfO

在线尝试!

说明:

v             : For each character in input string (implicit) in LSB order
  yi          : If the current character is truthy (1)
    NÌ        : Add 2 to the current index
       ÅfO    : Add the fibonacci of this number to the stack
  • -2个字节:感谢@KevinCruijssen指出了缩短此代码的小方法!
  • -1个字节:感谢@JonathanAllan指出输入的LSB顺序!

1
您可以删除Θ1在05AB1E中已经是真实的。:)也2+可以Ì
凯文·克鲁伊森

1
我们可以采用Little-endian形式的输入(即,取反),这应该节省一个字节(或两个?)。
乔纳森·艾伦




1

Stax,6 个字节

çéC◘0â

运行并调试

:1F^|5+           #Full program, unpacked, implicit input as array    
:1                #Get indicies of truthy
  F               #Use rest of program to loop through elements
   ^              #Increment current element
    |5+           #Get n-th fib and Add

非常简单。LSB订购。



1

C(gcc),63个字节

将输入作为的数组10的长度以及数组的长度。该解决方案是一个相当简单的向后循环。

f(_,l,a,b,t)int*_;{a=b=1;for(t=0;l--;b=(a+=b)-b)t+=a*_[l];_=t;}

在线尝试!



0

视网膜0.8.2,23字节

0?
;
+`1;(1*);
;1$1;1
1

在线尝试!链接包括更快的测试用例。说明:

0?
;

在各处插入分隔符并删除任何零。例如,1001变为;1;;;1;

+`1;(1*);
;1$1;1

在接下来的两个位置中,将每个位置重复替换1为a 1,因为它们的值之和等于original的值11因此,s迁移并累积,直到它们到达最后两个位置为止(由于新添加的分隔符),这两个位置现在都已经具有值了1

1

计算1s。




0

实际上,8个字节

;r⌐@░♂FΣ

在线尝试!

输入以LSB优先顺序作为位列表。

说明:

;r⌐@░♂FΣ
;r        range(0, len(input))
  ⌐       add 2 to every element in range (range(2, len(input)+2))
   @░     filter: take values in range that correspond to 1s in input
     ♂F   Fibonacci number at index of each element in list (Actually uses the F(0)=F(1)=1 definition, which is why we needed to add 2 earlier)
       Σ  sum

0

Powershell,68个字节

param($s)$b=1
$s[$s.Length..0]|%{$a,$b=$b,($a+$b)
$x+=($_-48)*$b}
$x

测试脚本:

$f = {
param($s)$b=1
$s[$s.Length..0]|%{$a,$b=$b,($a+$b)
$x+=($_-48)*$b}
$x
}

@(
    ,("1001", 6)
    ,("100101000", 73)
    ,("1000000000", 89)
    ,("1001000000100100010", 8432)
    ,("1010000010001000100001010000", 723452)
) | % {
    $s,$e = $_
    $r = &$f $s
    "$($r-eq$e): $r"
}

输出:

True: 6
True: 73
True: 89
True: 8432
True: 723452

0

Java(OpenJDK 8),65字节

对于Java的回答,这非常小,我对此感到满意。将输入作为LSB优先的整数数组。

d->{int s=0,f=1,h=1;for(int i:d){s+=i>0?f:0;f=h+(h=f);}return s;}

在线尝试!

不打高尔夫球

d->{                        // Lambda function that takes array of ints
    int s=0,f=1,h=1;        // Initialise sum and fibonacci vars
    for(int i:d){           // Loop through each input integer
        s+=i>0?f:0;         // If it's 1 add current fibonacci number to sum
        f=h+(h=f);          // Increase fibonacci number 
    }return s;              // return sum
}

0

Z80Golf,34个字节

00000000: dde1 f1b7 2819 fe30 2812 4504 aff5 3cf5  ....(..0(.E...<.
00000010: d1f1 82d5 f510 f9c1 f17c 8067 2c18 e3dd  .........|.g,...
00000020: e5c9                                     ..

输入1001的示例在线尝试!

输入100101000的示例-在线尝试!

部件:

zeck:		; input=push on stack in MSB order (eg top is LSB) output=reg h
pop ix		; save return addr in ix
f:
pop af		; get next digit
or a
jr z, return	; if current digit==0, return
cp 0x30
jr z, skip	; if current digit=='0' (e.g. not '1'), skip loop
ld b, l		; find fib of counter
fib:
	inc b	; 1-indexing for func to work
	xor a	; set a to 0 (1st fibo num)
	push af
	inc a	; set a to 1 (2nd fibo num)
	push af
	fib_loop:
		pop de
		pop af
		add d
		push de
		push af
		djnz fib_loop
pop bc		; get the fibo num just calculated
pop af		; pop just to reset stack frame
ld a, h
add b		; add current fibo number to sum
ld h, a
skip:
inc l		; increment counter reg
jr f		; repeat loop
return:
push ix		; push the return addr to ret to it
ret
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.