我是卡伦号码吗?


25

库伦数是使用以下公式生成的序列中包含的任何数字:

C(n)=(n * 2 ^ n)+1。

你的任务:

编写一个程序或函数,该程序或函数接收输入,并根据输入是否为库伦编号来输出真/假值。

输入:

0到10 ^ 9(含)之间的非负整数。

输出:

真/假值,指示输入是否为库伦编号。

测试用例:

Input:    Output:
1   --->  truthy
3   --->  truthy
5   --->  falsy
9   --->  truthy
12  --->  falsy
25  --->  truthy

得分:

这是,因此以字节为单位的最低分数获胜。


1
n的范围是多少?特别是1是一个库伦数吗?

3
@ ais523根据OEIS,是。n似乎是从0开始的。
steenbergh

很公平。只需要知道我的果冻答案是否应该包含一个或:R:)


嗯,那票选票是怎么回事?
Gryphon-恢复莫妮卡

Answers:



16

x86_64机器码(System V ABI),28 27字节

-1个字节感谢@Cody Gray,谢谢!

恒定时间算法!

_cullen:
   0:   0f bd cf    bsrl    %edi, %ecx
   3:   0f bd c1    bsrl    %ecx, %eax
   6:   89 ca       movl    %ecx, %edx
   8:   29 c2       subl    %eax, %edx
   a:   0f bd c2    bsrl    %edx, %eax
   d:   29 c1       subl    %eax, %ecx
   f:   d3 e1       shll    %cl, %ecx
  11:   ff c1       incl    %ecx
  13:   31 c0       xorl    %eax, %eax
  15:   39 f9       cmpl    %edi, %ecx
  17:   0f 94 c0    sete    %al
  1a:   c3          retq

说明:

y为整数和x=y*2^y + 1y + log2(y) = log2(x-1)因此,我们有日志y=log2(x-1)-log2(y)。插回y的值,我们得到y=log2(x-1)-log2(log2(x-1)-log2(y))。这样做的一个更多的时间,我们得到:y=log2(x-1)-log2[log2(x-1)-log2(log2(x-1)-log2(log2(x-1)-log2(y)))]

让我们删除最后一项(大约是log2(log2(log2(log2(x)))),这应该是安全的!),并假设x-1≈x,我们得到: y≈log2(x)-log2[log2(x)-log2(log2(x))]

现在,令f(n) = floor(log2(n)),它可以手动证实y可以通过精确地检索到: y=f(x)-f[f(x)-f(f(x))]用于ÿ<26,因此X⩽10 ^ 9,如由挑战指定(1)

然后,该算法仅包含计算给定x的y,并验证x == y * 2 ^ y + 1。诀窍是,可以简单地表示为实现指令(位反向扫描),它返回第一1比特的索引Ñ,和作为。f(n)bsry*2^yy << y

详细代码:

_cullen:                                 ; int cullen(int x) {
   0:   0f bd cf    bsrl    %edi, %ecx   ;  int fx = f(x);
   3:   0f bd c1    bsrl    %ecx, %eax   ;  int ffx = f(f(x));
   6:   89 ca       movl    %ecx, %edx   
   8:   29 c2       subl    %eax, %edx   ;  int a = fx - ffx;
   a:   0f bd c2    bsrl    %edx, %eax   ;  int ffxffx = f(a);
   d:   29 c1       subl    %eax, %ecx   ;  int y = fx - ffxffx;
   f:   d3 e1       shll    %cl, %ecx    ;  int x_ = y<<y;
  11:   ff c1       incl    %ecx         ;  x_++;
  13:   31 c0       xorl    %eax, %eax
  15:   39 f9       cmpl    %edi, %ecx
  17:   0f 94 c0    sete    %al
  1a:   c3          retq                 ;  return (x_ == x);
                                         ; }

(1)实际上,这种相等性似乎适用于y到50000的值。


4
好吧,我敢肯定,这是迄今为止迄今为止最有趣的代码。+1
狮ry-恢复莫妮卡

1
异或运算eax可以消除movzbl,节省1个字节。当然,您需要在XOR之前进行XOR,cmpl这样它才不会破坏标志,但是那完全没问题,因为在那之后什么都不依赖eax。或者,您可以确定该方法仅在低8位中返回一个布尔值,从而保存所有3个字节!
科迪·格雷

@CodyGray确实,非常感谢:)
yoann

7

果冻7 6字节

Ḷæ«`i’

在线尝试!

将输入作为命令行参数。如果给定一个卡伦数C(Ñ),输出Ñ 1(这是在果冻truthy,作为一个非零整数;注意,我们已Ñ ≥0,因为输入是一个整数,和具有负库伦数Ñ从不整数) 。如果给定非库伦数字,则返回0,这在Jelly中为false。

说明

Ḷæ«`i’
Ḷ        Form a range from 0 to (the input minus 1)
 æ«      Left-shift each element in the range by 
   `       itself
    i’   Look for (the input minus 1) in the resulting array

基本上,形成一个Cullen数减一的数组,然后在其中查找输入减一。如果输入的是库伦数字,我们将找到它,否则将找不到。请注意,数组必须足够长才能到达输入,因为C(n)始终大于n


7

JavaScript(ES6),37 35字节

感谢Neil,节省了2个字节

f=(n,k,x=k<<k^1)=>x<n?f(n,-~k):x==n

演示版


x<n?f(n,k+1):x==n工作吗?
尼尔

@Neil当然可以。:-)
Arnauld

为什么当k + 1使调用栈超载时,〜k起作用?
2015年

@trlkly基本上,undefined+1===NaN但是-~undefined===1。您可以在此处了解更多信息
Arnauld


3

欧姆,8个字节

@Dº*≥Dlε

在线尝试!

           Implicit input
@          Range [1,...,Input]
 D         Duplicate
  º        2^n each element
   *       Multiply those two array
    ≥      Increment everything (now I have an array of all Cullen Numbers)
     Dl    Push array length (= get input again, can't get again implicitly or using a function because it would be a string so I'd waste a byte again)
       ε   Is input in array?


3

05AB1E,7个字节

ÝDo*¹<å

在线尝试!

说明:

ÝDo*¹<å Example input: 9. Stack: [9]
Ý       Range 0-input. Stack: [[0,1,2,3,4,5,6,7,8,9]]
 D      Duplicate. Stack: [[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9]]
  o     2** each item in the list. Stack: [[0,1,2,3,4,5,6,7,8,9], [1,2,4,8,16,32,64,128,256,512]]
   *    Multiply the two lists. Stack: [[0, 2, 8, 24, 64, 160, 384, 896, 2048, 4608]]
    ¹   Push input again. Stack: [[0, 2, 8, 24, 64, 160, 384, 896, 2048, 4608],9]
     <  Decrement. Stack: [[0, 2, 8, 24, 64, 160, 384, 896, 2048, 4608],8]
      å Is the first item of the stack in the second item? Stack: [1]
        Implicit print.

3

R53 51 46字节

pryr::f(x%in%lapply(0:x,function(y)(y*2^y+1)))

匿名函数。检查是否x在序列C(n)中为[0,x]中的n生成了n。

朱塞佩打高尔夫球的3个字节。

在线尝试!


x%in%...代替any(x==...); 会丢掉4个字节
Giuseppe

因此,如果我通过将更改为lapply来简单地检查向量,并使用它scan而不是接受函数参数,则可以得到@giuseppe的答案。感谢您将其单独发布,这样我就可以看到自己的缺失-即使我通常会迷路,我也可以通过尝试一些自己的东西来学习更多。
BLT

3

C,C ++,Java,C#,D:70个字节

由于所有这些语言之间的相似性,因此该代码适用于每种

int c(int n){for(int i=0;i<30;++i)if((1<<i)*i+1==n)return 1;return 0;}

这次我将发布优化的D版本,可以使用一些D特有的技巧。
扎卡里

建议i=30;i--;)if(i<<i==n-1)而不是i=0;i<30;++i)if((1<<i)*i+1==n)
ceilingcat '18



2

R,26个字节

a=0:26;scan()%in%(1+a*2^a)

在线尝试!

其他R回答略有不同的方法; 从中读取数据,stdin并且由于输入保证在0到10 ^ 9之间,因此我们只需要检查n0到26之间的值即可。


我不记得了scan()。辛苦了
BLT

2

APL(Dyalog),9字节

为了覆盖n = 1 的情况,它要求⎕IO←0在许多系统上都使用默认值。

⊢∊1+⍳×2*⍳

在线尝试!

 [是] n(自变量)

 的成员

1 一

+ 加

 在 ntegers 0 ...(Ñ -1)

× 次

2 二

* 的力量

 在 ntegers 0 ...(Ñ -1)


因此,“许多系统上的默认值”意味着它只是存在
扎卡里

@Zacharý是的,称⎕IO←0非标准是错误的,因为确实有很多这样的设置,而每次都不需要规范。
2015年

好。如果有机会的话,我将肯定在MY中使用该技巧(并且MY可以具有非0和非1的索引原点)。
扎卡里

@Zacharý不需要那些默认值为默认值的实际安装基础/版本吗?例如在SAX和ngn中⎕IO←0
亚当

是的,我想会的。而且MY确实有3个Iota,因此我认为无论如何都不会使用它。
扎卡里

2

Python 2,32字节

[n<<n|1for n in range(26)].count

在线尝试!

创建直到的库伦数字列表10^9,然后计算输入在其中出现的次数。感谢Vincent指出n<<n|1而不是(n<<n)+1,节省了2个字节。


您可以使用保存两个字节n<<n|1n<<n);为偶数)
文森特

失败838860801。您需要range(26),因为范围不包含在内。
mbomb007'6

@ mbomb007谢谢。我这样做已经有一段时间了,但有时仍会忘记范围是排他的。
xnor

2

D,65个字节

这是@HatsuPointerKun算法到D的端口(原始已经是D代码,但这是D特有的技巧)

T c(T)(T n){for(T i;i<30;++i)if((1<<i)*i+1==n)return 1;return 0;}

怎么样?(D特技)

D的模板系统比C ++的短,并且可以推断类型。并且D也会在声明时将其变量初始化为默认值。


1

Mathematica,30个字节

MemberQ[(r=Range@#-1)2^r+1,#]&

将非负整数作为输入并返回Trueor的纯函数False。如果输入为n,则将(r=Range@#-1)变量r设置为{0, 1, ..., n-1},然后r2^r+1根据矢量计算第一个n库伦数。MemberQ[...,#]然后检查是否n是列表的元素。



1

Excel VBA,45字节

匿名VBE立即窗口功能,可将单元[A1]和输出的输入接收到VBE立即窗口

必须在干净的模块中运行或将i,j的值重置为两次运行之间的默认值

While j<[A1]:j=(i*2 ^ i)+1:i=i+1:Wend:?j=[A1]

输入输出

在VBE立即窗口中看到的I / O

[A1]=25
While j<[A1]:j=(i*2 ^ i)+1:i=i+1:Wend:?j=[A1]
True

[A1]=1: i=0:j=0 ''# clearing module values
While j<[A1]:j=(i*2 ^ i)+1:i=i+1:Wend:?j=[A1]
True    

[A1]=5: i=0:j=0 ''# clearing module values
While j<[A1]:j=(i*2 ^ i)+1:i=i+1:Wend:?j=[A1]
False 

1

Swi-Prolog,69个字节

f(X)如果可以找到其中X = I * 2 ^ I + 1的值I,则成功。范围提示会阻止它耗尽堆栈空间,但是对于问题规范中的Cullen数字范围(最多10 ^ 9)就足够了。

:-use_module(library(clpfd)).
f(X):-I in 0..30,X#=I*2^I+1,label([I]).

例如

f(838860801).
true

1

cQuents,9个字节

$0?1+$2^$

在线尝试!

说明

$0           n is 0-indexed
  ?          Mode query. Given input n, output true/false for if n is in the sequence.
   1+$2^$    Each item in the sequence equals `1+index*2^index`

1

TI-BASIC,17个字节

max(Ans=seq(X2^X+1,X,0,25

说明

seq(X2^X+1,X,0,25 Generate a list of Cullen numbers in the range
Ans=              Compare the input to each element in the list, returning a list of 0 or 1
max(              Take the maximum of the list, which is 1 if any element matched

您可能要对此添加说明。
狮ry-恢复莫妮卡

完成,谢谢小费。
calc84maniac

这行得通,但是逐个命令的解释通常可以帮助大多数人投票。我建议对这个答案做一些类似的解释。我不知道为什么有人拒绝您的帖子。尽管这样做通常会被忽略,但是通常在发表评论时都会发表评论。
狮ry-恢复莫妮卡

别客气。我记得当我第一次加入该网站时,人们告诉了我这些类型的事情。只是传递了青睐。
狮ry-恢复莫妮卡

0

QBIC,24字节

[0,:|~a*(2^a)+1=b|_Xq}?0

说明

[0,:|           FOR a = 0 to b (input from cmd line)
~a*(2^a)+1=b    IF calculating this a results in b
|_Xq            THEN quit, printing 1
}               NEXT a
?0              We haven't quit early, so print 0 and end.

0

k,19个字节

{&1=x-{x**/x#2}'!x}

在线尝试。Truthy是与一些在它的数组:,3,0等等。Falsey是一个空数组:()!0取决于您的解释器。



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.