您的基数为1-2-3-Tribonacci的二进制数为基数的基数


19

背景

1-2-3-Tribonacci序列

想象一下,您可以通过将标准迭代公式替换为以下内容来制作斐波那契数列:

Tribonacci

基本上,不是将最后两个求和以获得下一个,而是将最后三个求和。这是1-2-3-Tribonacci序列的基础。

布朗的准则

布朗的准则状态,您可以将任何整数值表示为序列成员的总和,条件是:

  1. x sub n等于1

  2. 对于所有n大于1,x sub n小于2 x sub n-1

这对挑战意味着什么

您可以将任何正整数描述为由以下初始条件形成的1-2-3-Tribonacci序列的成员之和:

初始状态

对于此序列中的每个值,这被称为项之间的比率永远不会大于2(该比率的平均值约为1.839)。

如何在此数字表示系统中编写

假设您使用小尾数表示法。像这样排列序列的成员:

1  2  3  6 11 20 37 68

然后,将您要表示的数字表示出来(对于我们的测试,假设是63),然后找到给定的1-2-3-Tribonacci的值总和为63 (首先使用最大值!)。如果数字是总和的一部分,则在其下放一个1,否则不放0。

1  2  3  6 11 20 37 68
0  0  0  1  0  1  1  0

您可以对任何给定的整数执行此操作-只需先确认您使用低于给定输入的最大值即可!

定义(最终)

编写程序或函数,以给定n介于1和您的语言最大值之间的正整数输入(以任何标准基数编写)来执行以下操作:

  1. 将值转换为定义的1-2-3-Tribonacci的数字表示形式。
  2. 使用这种类似于二进制的表示形式,并像对待二进制一样读取它。这意味着数字保持不变,但是它们的含义改变了。
  3. 将此二进制数字转换为原始数字的基数。
  4. 输出或返回此新号码。

但是,只要输出有效,就不需要执行以下步骤。如果您神奇地找到了一些更短的公式(在数学上是等效的),请随时使用。

例子

令函数f为定义所描述的函数,并[]表示所采取的步骤(为小端,尽管无关紧要)(您无需遵循此过程,这只是描述的过程):

>>> f(1)
[1]
[1]
[1]
1

>>> f(5)
[5]
[0, 1, 1]
[6]
6

>>> f(63)
[63]
[0, 0, 0, 1, 0, 1, 1]
[104]
104

我可以提交一个单独的程序,虽然时间不短,但可以更快地解决问题?log(log(n))+ n时间,而不是log(n)+ n时间。去第N次幂矩阵。
fəˈnɛtɪk

@LliwTelracs我无法阻止您发布解决方案。只需使该解决方案方法尽可能针对您的知识即可,以确保您仍在正确的领域中竞争。
艾迪生·克伦普

好吧,至少不会这样做。这个矩阵的快速幂是可笑冗长
fənɛtɪk

2
@LliwTelracs也许只是将其作为附录添加到您现有的帖子中。
乔纳森·艾伦

对于那些无法显示图像的人来说,您的挑战是难以理解的。
Mindwin '17年

Answers:


7

Javascript 117111字节

感谢@theonlygusti帮助高尔夫球减少了5个字节

x=>{r=0;a=[1,2,3];i=1;while(a[++i]<x)a[i+1]=a[i]+a[i-1]+a[i-2];for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}return r}

怎么运行的

首先,该函数生成所有tribonacci数,直到找到比输入大的数

a=[1,2,3];i=1;for(;a[++i]<x;)a[i+1]=a[i]+a[i-1]+a[i-2];

接下来,它反向搜索数字列表。如果数字小于输入,则将2 ^(该数字的索引)添加到返回值,并将输入减少该数字。

for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}

最后,它返回结果。

在线尝试


1
怎么样a[++i]<x里面的情况,以节省一个字节?
theonlygusti

1
另外,您也可以替换x>0x。保存另外2个字节。
theonlygusti

那是一个很好的算法。oo
Addison Crump

7

Python 2中110个 102字节

-3个字节,感谢Rod(将boolean i转换为int的巧妙技巧,+i因此repr `+i`可以工作)

n=input()
x=[3,2,1]
r=''
while x[0]<n:x=[sum(x[:3])]+x
for v in x:i=n>=v;n-=v*i;r+=`+i`
print int(r,2)

在线尝试!


1
您可以替换'01'[i]`+i`
Rod

i是布尔值而不是整数。编辑-哦+i,整洁。
乔纳森·艾伦

3
@Rod Python 2技巧中的技巧吗?
艾迪生·克伦普

@VoteToClose我认为不是
Rod

7

JavaScript(ES6),97 93字节

在这里,我们使用reduce()递归函数。我们假设输出为31位(这是JS可以轻松用于按位操作的最大无符号数量)。

n=>[...Array(x=31)].reduce(p=>(c=(F=k=>k<4?k:F(--k)+F(--k)+F(--k))(x--))>n?p:(n-=c,p|1<<x),0)

在性能方面,这显然不是很有效。

对于好奇:

  • 呼叫次数之间的比率 F()N + 1reduce()次迭代与N次迭代迅速收敛到Tribonacci常数(≈1.83929)。因此,输出中每个额外的位花费的时间大约是前一个时间的两倍。
  • 用31位, F()函数被称为有效的124百万次。

测试

注意:这可能需要1或2秒才能完成。


哇,这比我使用浏览器时落后。xD
Addison Crump

@VoteToClose性能明智,这是非常低效的。:-)测试代码不应滞后太长时间。在我的盒子上,我在Firefox中的运行时间约为600毫秒,在Chrome中为900毫秒。你这边慢很多吗?
Arnauld

像5秒 xD
艾迪生·克伦普

@VoteToClose现在应该快一点。第32次迭代毫无意义,因此我将输出限制为无符号的31位整数。
Arnauld

6

Mathematica,78 74字节

Fold[#+##&,#~NumberDecompose~Reverse@LinearRecurrence[{1,1,1},{1,2,3},#]]&

LinearRecurrence[{1,1,1},{1,2,3},#]生成长度为输入的1-2-3 tribonacci数字列表。({1,1,1}表示前三个项的总和,而{1,2,3}它们是初始值。)然后#~NumberDecompose~找到最贪婪的方式将输入写为列表元素的总和(这是将货币金额分解为的倍数的同一函数)。例如可用的货币)。最后,Fold[#+##&,...]将结果二进制列表转换为(基数为10)的整数。

先前提交的内容:

Fold[#+##&,#~NumberDecompose~Reverse@Array[If[#<4,#,Tr[#0/@(#-Range@3)]]&,#]]&

通常情况下(尽管不是上面的情况),此高尔夫球版本在输入大于20左右时速度非常慢,因为它会生成(使用非优化的递归)一系列长度为输入的部落列表。用#更合理的边界替换最终Round[2Log@#+1]结果会带来更好的性能。


哇 Mathematica没有123Tribonacci[]内置功能?
palsch

1
尽管事实证明使用内置功能确实有所帮助,但不完全正确。
格雷格·马丁

5

Haskell,95个字节

(a!b)c=a:(b!c)(a+b+c)
e#(r,c)|c-e<0=(2*r,c)|1<2=(2*r+1,c-e)
f n=fst$foldr(#)(0,n)$take n$(1!2)3

用法示例:f 63-> 104在线尝试!

工作原理:!构建1-2-3-Tribonacci序列。鉴于123作为启动参数,我们把第一个n序列的元素。然后,我们从右边的功能折叠#其减去下一个元素e,从n并将在返回值位r,如果e需要或让位未设置。设置该位将加倍,r而将1其设置为未设置则将其加倍。


4

果冻,31 个字节

S=³
3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ

在线尝试!

我几乎可以肯定,在Jelly中有一种更短的方法可以实现这一目标。

怎么样?

S=³ - Link 1, compare sum to input: list
S   - sum
  ³ - 3rd command line argument which is 1st program argument.
 =  - equal?

3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ - Main link: n
3RU                         - range(3) upended -> [3,2,1]
   µ    µ   µ¿              - while
         <³                 - less than input (vectorises)
           Ạ                - all?
    ḣ3S;                    -     head(3), sum, and concatenate
                                  [3,2,1] -> [6,3,2,1] -> [11,6,3,2,1] -> ...
              µ             - monadic chain separation, call the result x
               ŒP           - power set of x - e.g. for [6,3,2,1] -> [[],[6],[3],[2],[1],[6,3],[6,2],[6,1],[3,2],[3,1],[2,1],[6,3,2],[6,3,1],[6,2,1],[3,2,1],[6,3,2,1]]
                  Ðf        - filter keep
                 Ç          -     last link (1) as a monad (those that sum to the input)
                    Ṁ       - maximum (e.g. an input of 63 would yield [[37,20,6],[37,20,3,2,1]], the maximum of which is [37,20,6], the one with the largest numbers used)
                         µ  - monadic chain separation (to have x as the right argument below)
                     e@Ѐ   - exists in with reversed arguments mapped over x (e.g. [37,20,6] with x = [68,37,20,11,6,3,2,1] yields [0,1,1,0,1,0,0,0])
                          Ḅ - convert from binary to integer.        

4

Perl 6的93个 91字节

-2个字节归功于b2gills

{my@f=1,2,3,*+*+*...*>$^n;sum @f».&{$_~~any first *.sum==$n,@f.combinations}Z*(2 X**^∞)}

怎么运行的

  • 首先,它会生成1-2-3-Tribonacci序列,直到第一个比输入大的元素为止:

    my @f = 1, 2, 3, *+*+* ... * > $^n;
  • 基于此,它找到序列的子集,该子集加到输入中:

    first *.sum==$n, @f.combinations
  • 基于此,它构造一个布尔值列表,指定该序列的每个元素是否为求和的一部分:

    @f».&{$_~~any ...}
  • 最后,它将True = 1,False = 0值的列表解释为以2为底的值,并将其返回为(以10为底)的数字:

    sum ... Z* (2 X** ^∞)

1
您可以使用*>$^n和缩短它.sum==$nmy以及之间也不需要空间@f
Brad Gilbert b2gills'2

3

JavaScript(ES6),61 60字节

n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)

计算1-2-3-Tribonacci数,直到达到原始数,然后在递归展开时,尝试依次减去每个数,将结果加倍。

编辑:由于@Arnauld,节省了1个字节。


哇!非常好。可以n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)节省一个字节吗?
Arnauld

@Arnauld我一直在寻找使用的东西,n<x||但这![]只是个天才。
尼尔

2

分批,151名 148 145字节

@set/ar=0,n=%1
@call:c 3 2 1
@echo %r%
@exit/b
:c
@set/as=%1+%2+%3
@if %n% gtr %3 call:c %s% %*
@set/ar*=2
@if %n% geq %3 set/an-=%3,r+=1

我的JavaScript回答的端口。编辑:通过以相反的顺序传递我的子例程参数节省了3个字节,通过@在每行上使用单个s代替了另外3个字节@echo off


2

果冻19 18 17字节

Ḣx3+
BÇL¡2ị
²Ç€»ċ

在线尝试!

背景

与其尝试将整数转换为1,2,3-Tribonacci基,然后从二进制转换为整数,我们要做相反的事情:将整数转换为二进制,然后从1,2,3-Trionacci基转换为整数,然后返回匹配输入的最高的。这很容易实现。

我们将举例说明输入63的过程,特别是测试104的步骤。在二进制中,从最高有效位到最低有效位,104等于

 1  1  0  1  0  0  0
37 20 11  6  3  2  1

其中第二行代表这些数字的位置值。

我们可以将1,2,3-Tribonacci序列向右扩展,观察到添加的数字符合相同的递归公式。对于三位数,这给出了

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

现在,要计算基本1,2,3-Tribonacci数的值,我们可以使用递归公式。由于每个数字都是其右边三个数字的总和(在上表中),因此我们可以删除第一个数字并将其添加到其余数组的前三个数字中。经过7步(等于104的二进制数),我们很少剩下3位数字。

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

    2  1  2  0  0  0  0  0  0
   20 11  6  3  2  1  0  1  0

       3  4  2  0  0  0  0  0
      11  6  3  2  1  0  1  0

          7  5  3  0  0  0  0
          6  3  2  1  0  1  0

            12 10  7  0  0  0
             3  2  1  0  1  0

               22 19 12  0  0
                2  1  0  1  0

                  41 34 22  0
                   1  0  1  0

                     75 63 41
                      0  1  0

现在,由于第一个和最后一个剩余数字均具有位置值0,因此结果是中间数字,即63

怎么运行的

²Ç€»ċ   Main link. Argument: n

²       Yield n². Since 1.839² = 3.381921 > 2, the range [1, ..., n²] will contain
        the answer. Better bounds, at the cost of additional bytes are possible.
 Ç€     Map the the second helper link over [1, ..., n²].
   »    Take the maximum of n and each result.
    ċ   Count the occurrences of n.


BÇL¡2ị  Second helper link. Left argument: k. Right argument: n

B       Convert k to binary. Let's call the result A.
  L     Length; count the number of binary digits. Let's call the result l.
 Ç ¡    Apply the first helper link l times to A.
    2ị  Retrieve the second element.


Ḣ×3+    First helper link. Argument: A (array)

Ḣ       Head; pop and yield the first element of A.
 x3     Repeat it thrice.
   +    Add the result, component by component, to the beheaded A.

2

果冻(叉子),17 16字节

ḣ3S;µ¡
3RṚdzæFṪḄ

感谢@Dennis甚至没有运行它就打高尔夫球,节省了1个字节。

这依赖于Jelly的分支,令人失望的是,我仍然在致力于实现高效的Frobenius解决原子。对于那些感兴趣的人,我想与Mathematica的速度FrobeniusSolve相提并论,幸运的是对他们的方法有所解释相提并论在Daniel Lichtblau的论文《进行改变并找到代表:平衡背包》中进行了。

说明

ḣ3S;µ¡  Helper link. Input: a list
    µ   Create monadic chain
ḣ3        Take the first 3 items
  S       Sum
   ;      Prepend to the list
     ¡  Repeat it n (initial argument from main) times

3RṚdzæFṪḄ  Main link. Input: integer n
3          The constant 3
 R         Range. Makes [1, 2, 3]
  Ṛ        Reverse. Makes [3, 2, 1]
   Ç       Call the helper link on that list.
           Generates the first (n+3) 123-Tribonacci values in reverse
    ³      Get n
     æF    Frobenius solve for n using the first n 123-Tribonacci values in reverse
       Ṫ   Tail. Take the last value. The results of Frobenius solve are ordered
           where the last result uses the least
        Ḅ  Unbinary. Convert digits from base 2 to base 10

3
您知道当您使用super-esolangs的分支时,您将深入研究代码高尔夫球。
艾迪生·克朗普

ḣ3S;µ¡¶3RṚdzæFṪḄ工作吗?我没有安装您的前叉,因此无法测试。
丹尼斯,

@Dennis这是从stdin输入而不是参数,对吗?我在使用参数时遇到麻烦,只是意识到它以另一种方式起作用。
英里

不,那应该仍然是争论。³引用第一个参数。
丹尼斯

@Dennis Nvm,它确实通过参数工作,jelly.py在最后一次提交后,我还有其他一些东西。
英里

1

直流110个 102字节

?se1sa2sb3sc_1sf[laddSdlbdsalcdsb++sclf1+sfle>y]dsyx0sk[lk2lf^+skler-se]sr[Lddle!<rlf1-dsf0!>z]dszxlkp

好吧,好像伟大的头脑确实会思考一样。显然,我想出的算法可以克服dc@LliwTelrac的答案中所使用的算法。有趣。

在线尝试!



1

bash + BSD实用程序(OS X等),53个字节

jot $[2#$1**4]|egrep -v '[2-9]|11(1|$)'|sed $[2#$1]!d

bash + GNU实用程序(也可在BSD下运行),59字节

seq -f2o%.fp $[2#$1**2]|dc|egrep -v '11(1|$)'|sed $[2#$1]!d

以上两者的输入和输出均为二进制。


在TIO上试用GNU版本。 (链接到的示例演示了111111的输入(二进制为63)和1101000的输出(二进制为104)。)

我不认为TIO提供了BSD选项,但是如果您有Mac,则可以在那里尝试使用它们。(59字节的程序是比53字节节目更快。)


不幸的是,seq不能简单地将其替换为BSD解决方案jot,因为seq对于高于999999是不同的。(这对于32左右的输入来说是一个问题,因为32 ^ 4>1000000。)

您可以将jot上面的替换seq -f%.f为GNU实用程序,但是对于相同的59个字节,您可以使用上面的GNU解决方案,这要快得多。

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.