一点点还是半字节?


45

受此挑战启发

给定范围内的整数0 <= n < 2**64,输出可容纳的最小尺寸的容器

  • 位:1
  • 半字节:4
  • 字节:8
  • 短:16
  • 整数:32
  • 长:64

测试用例:

0 -> 1
1 -> 1
2 -> 4
15 -> 4
16 -> 8
123 -> 8
260 -> 16
131313 -> 32
34359750709 -> 64

这是,因此最短的答案以字节为单位。


10
如果2输出也太容易了……
ETHproductions 2016年

1
@ETHproductions它会但可惜不是(我花了很长时间写了一个能做到这一点的算法)
Blue

我希望我理解这个问题。...等等,它想要的只是包含数字所需的位数,舍入到下一个基本结构?
z0rberg's

2
谢谢!我写评论并编辑得太晚时才意识到。我想我需要一只橡皮鸭来跟...说话
z0rberg's

2
@Daniel这里的答案对另一个问题采取了完全不同的方法。当我说“灵感来自”时,它并不意味着“重复”。对于这个问题,没有任何答案可以轻易修改为有效
Blue

Answers:


3

05AB1E,10个字节

bg.²îD1Q+o

说明

bg         Push the length of the binary representation of input without leading zeros
  .²î      Push x = ceil(log2(length))
     D1Q+  Add 1 if x == 1 or add 0 otherwise
         o Push pow(2,x) and implicitly display it

在线尝试!


22

Python,39个字节

f=lambda n:4**(n>1)*(n<16)or 2*f(n**.5)

计数一个必须多少次取平方根n成低于16,用一些特殊套管的2避免输出。

如果包括2个,我们可以做

f=lambda n:n<2or 2*f(n**.5)

与True for 1。


41个字节:

f=lambda n,i=1:i*(2**i>n)or f(n,i<<1+i%2)

重复将指数翻倍i直到2**i>n。当奇数时i=1i=4通过将另外的一位移位来从跳过i

Alt 45个字节:

f=lambda n,i=4:4**(n>1)*(2**i>n)or 2*f(n,i*2)

7
它永远不会令我感到惊奇,您如何才能为一个问题提出这么多解决方案。基本上,作为一名程序员,我学会了找到问题的解决方案并使用它,直到它起作用为止。猜猜我还有很多关于高尔夫的知识!尊重。
ElPedro

@xnor,1当0或1的平方根始终为1时,您的第一个答案如何输出(中的无限递归or 2*f(n**.5))?
dfernan '16

2
@dfernan我相信or仅当之前的部分评估为虚假(零)时,才会评估后面的部分。对于n = 0,对于n = 1,结果n>1False,在数字表达式中被视为零,而结果n<16True,在数字表达式中被视为1。4**(n>1)*(n<16)1
也是

1
@trichoplax,是的。感谢您的解释。
dfernan '16

12

J,19个字节

一元动词,取右边的数字,吐出容器的大小。有两种等效的编写方式,因此我将两者都包括在内。

2^2(>.+1=>.)@^.#@#:
2^s+1=s=.2>.@^.#@#:

爆炸解释:

2^2(>.+1=>.)@^.#@#: NB. takes one argument on the right...
                 #: NB. write it in binary
               #@   NB. length (i.e. how many bits did that take?)
  2          ^.     NB. log base 2 of that
   (>.     )@       NB. ceiling
      +1=>.         NB. +1 if needed (since no container is two bits wide)
2^                  NB. base 2 exponential

很棒的是,我们看到用J取对数2的两种不同方法。第一种是显而易见的2^.,它是数值对数。第二个是#@#:,可以理解为“ base-2表示形式的长度”。这几乎等于一加层日志基数2,除了那#:0是一个元素列表0,这正是我们想要的。这跳动1+2<.@^.1&>.了8个字节。

在REPL中使用:

   f =: 2^2(>.+1=>.)@^.#@#:
   f 131313
32
   f 34359750709
64
   (,.f"0) 0 1 2 15 16 123 260
  0  1
  1  1
  2  4
 15  4
 16  8
123  8
260 16

过于聪明的20字节旧解决方案。

2&^.(>.+1=>.&.)@#@#: NB. takes one argument on the right...
                #@#: NB. how many bits
2&^.                 NB. log base 2 of that
     >.              NB. ceiling
       +1=>.         NB. +1 if needed (since no container is two bits wide)
    (       &.)      NB. undo log base 2

9

Python,53 50 49字节

lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]

1
lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]是短一个字节
蓝色

正要发布类似的内容。+1
ElPedro '16

8

Mathematica,44 39 38字节

感谢@orlp提供5个字节,@ MartinEnder提供1个字节。

FirstCase[{1,4,8,16,32,64},x_/;2^x>#]&

查找列表中的第一个元素,{1, 4, 8, 16, 32, 64}使2 ^ number大于输入。


8

,19字节

(a<2**_FI2**,7RM2i)

在线尝试!

这个怎么运作

                     a is 1st cmdline arg, i is 0 (implicit)
         2**,7       Construct powers of 2 from 0 to 6 [1 2 4 8 16 32 64]
              RM2    Remove 2
       FI            Filter for elements for which:
 a<2**_                a is less than 2 to that element
(                i)  Get 0th item of resulting list and autoprint

7

JavaScript(ES7),35个字节

n=>[1,4,8,16,32,64].find(b=>2**b>n)

2
递归版本,例如f=(n,b=1)=>2**b>n&&b-2?b:f(n,b*2)应稍短一些。
Arnauld

6

Mathematica,46 43 38字节

感谢JungHwan Min和Martin Ender节省了3个字节! 感谢ngenisis节省了5个字节!

2^⌈Log2@BitLength@#⌉/.{2->4,0->1}&

使用非负整数作为输入并返回正整数的未命名函数。BitLength@#计算输入中的位数,然后2^⌈Log2@...⌉计算2的最小乘方,该乘方至少与位数相同。最后,请/.{2->4,0->1}注意在特殊情况下,在位和半字节之间没有“ niblit”,并且还解决了奇怪输入的答案0


2
使用BitLength@#代替来节省3个字节⌊1+Log2@#⌋。然后1您可以替换0,而不是替换,节省另外2个字节,您将被并列为第一。
ngenisis

1
实际上,可以完全使用BitLength。看到我的回答
ngenisis

4

朱莉娅,40个字节

n->filter(x->n<big(2)^x,[1;2.^(2:6)])[1]

这是一个匿名函数,它将生成一个2的幂(从2到0)的数组(不包括2),并将其过滤为仅那些元素x,使得2 x大于输入。第一个这样的要素就是答案。不幸的是,这需要将2提升为a BigInt以避免x = 64 上的溢出。

这实际上与orlp的Python答案非常相似,尽管在构想此方法之前我没有看到它。

在线尝试!



4

Haskell,31个字节

f n=[2^i|i<-0:[2..],2^2^i>n]!!0

32字节alt:

f n|n<2=1|n<16=4|1>0=2*f(sqrt n)

2

Java,143个字节。

int f(long a){a=Long.toBinaryString(a).length();if(a<2)return 1;if(a<5)return 4;if(a<9)return 8;if(a<17)return 16;if(a<33)return 32;return 64;}

1
我知道我可以将其缩短,当我在计算机上时也可以这样做。
帕维尔

2
保存50个字节: return a<2?1:a<5?4:a<9?8:a<17?16:a<33?32:64;
Mindwin

我知道@Mindwin,但我正在旅行,暂时无法使用计算机。我会解决的。
帕维尔

分数使它成为... 爱的字节吗?
Engineer Toast

2

Haskell,43个字节

f x=head$filter((>x).(2^))$[1,4,8,16,32,64]

2

Ruby,39个36字节

->n{2**[0,*2..6].find{|p|2**2**p>n}}

感谢GB帮助高尔夫


也应该没有括号地工作。同样,列表可以是0,2,3,4,5,6并使用1 << 2 ** p。
GB

...,因为这样您就可以使用0,* 2..6。
GB

2

Java 8,65 55字节

这是一个lambda表达式,它接受a long并返回int。以前从未在Java中打过高尔夫球,因此应该很容易击败:

x->{int i=1;while(Math.pow(2,i)<=x)i<<=1+i%2;return i;}

在线尝试!


对于47个字节,我们可以有:

x->{int i=1;while(1L<<i<=x)i<<=1+i%2;return i;}

但是,1L<<i返回值大于32时会溢出,因此对于最终的测试用例将失败。


1
这将返回4当测试16时,它应该返回8.你也仍然可以高尔夫这个解决方案由各地去掉括号i<<=1+i%2;因为如果没有{}S,while循环将执行下一行
Kritixi LITHOS

@KritixiLithos应该现在修复-抱歉,我的Java生锈了……
FlipTack

2

Mathematica,30个字节

2^(f=BitLength)[f@#-1]/. 2->4&

说明:

N被这套非负整数。在和上定义两个函数N,如下所示:BitLengthNextPower

BitLength(n) := min {x in N : 2^x - 1 >= n}
NextPower(n) := 2^(min {x in N : 2^x >= n})

该解决方案实质上是在NextPower(BitLength(n))给定整数的情况下进行计算的n >= 0。对于n > 0,我们可以看到NextPower(n) = 2^BitLength(n-1),所以NextPower(BitLength(n)) = 2^BitLength(BitLength(n)-1)

现在BitLength内置的Mathematica 同意我给的定义n >= 0。对于n < 0BitLength[n] == BitLength[BitNot[n]] == BitLength[-1-n],所以BitLength[-1] == BitLength[0] == 0。因此,我们得到所期望的答案1n==0

由于我们直接跳到从位到细,大家要更换的答案24


1
构造好!(可惜的是空间是必需的。)
格雷格·马丁

2

bash,49字节 48字节

for((y=1;$[y==2|$1>=1<<y];$[y*=2])){ :;};echo $y

要么

for((y=1;$[y==2|$1>=1<<y];)){ y=$[y*2];};echo $y

保存在脚本中,然后将要测试的数字作为参数传递。

编辑:替换|| 与|一起使用,因为参数始终为0或1。

注意:这适用于最大为bash版本可以处理的最大正整数的整数。如果有时间,我将对其进行修改以在使用32位带符号算术的bash版本中达到2 ^ 64-1。

同时,这是一个64字节的解决方案,适用于任意大数(在任何bash版本中):

for((x=`dc<<<2o$1n|wc -c`;$[x==2||x&(x-1)];$[x++])){ :;};echo $x

2

堆叠,34 30字节

@n 1 2 6|>2\^,:n 2 log>keep 0#

要么

{!1 2 6|>2\^,:n 2 log>keep 0#}

第一个在TOS上接受输入,而在TOS上保留输出;第二个是功能。在这里尝试!

说明

@n 1 2 6|>2\^,:n 2 log>keep 0#
@n                               set TOS to `n`
   1 2 6|>2\^,                   equiv. [1, ...2 ** range(2, 6)]
              :                  duplicate it
               n                 push `n`
                 2 log           log base-2
                      >          element-wise `>`
                       keep      keep only truthy values
                            0#   yield the first element

这是在repl上工作的示例:

> 8    (* input *)
(8)
> @n 1 2 6|>2\^,:n 2 log>keep 0#    (* function *)
(4)
>    (* output *)
(4)

测试用例

> {!1 2 6|>2\^,:n 2 log>keep 0#} @:f
()
> (0 1 2 15 16 123 260 131313 34359750709) $f map
((1 1 4 4 8 8 16 32 64))
> 

或者,作为一个完整程序:

{!1 2 6|>2\^,:n 2 log>keep 0#} @:f

(0 1 2 15 16 123 260 131313 34359750709) $f map

out

2

拍子45字节

(findf(λ(x)(>(expt 2 x)m))'(1 4 8 16 32 64))

取消高尔夫:

(define (f m)
  (findf (λ (x) (> (expt 2 x) m))          ; find first function
         '(1 4 8 16 32 64)))

其他版本:

(define (f1 m)
  (for/last ((i '(1 4 8 16 32 64))         ; using for loop, taking last item
             #:final (> (expt 2 i) m))     ; no further loops if this is true
    i))

并使用字符串长度:

(define (f2 m)
  (for/last
      ((i '(1 4 8 16 32 64))
       #:final (<= (string-length
                    (number->string m 2))  ; convert number to binary string
                   i))
    i))

测试:

(f 0)
(f 1)
(f 2)
(f 15)
(f 16)
(f 123)
(f 260)
(f 131313)
(f 34359750709)

输出:

1
1
4
4
8
8
16
32
64

1

八度,40 36 31 29字节

简单的匿名功能。假定输入值为整数-请参见最后的警告。

@(a)(b=2.^[0 2:6])(a<2.^b)(1)

该代码的工作方式如下:

  • 首先,创建一个允许的位长数组(1,4,8,16,32,64)并将其保存到b

  • 接下来,我们a通过与每个容器的最大大小进行比较来找到存储输入数字所需的位数,b以查看它们足够大。

  • 然后,我们使用结果索引向量再次从中提取容器大小b

  • 最后,我们将结果数组中的第一个元素作为可能的最小容器。

您可以在这里在线尝试。

只需运行以下代码,然后执行ans(x)


唯一需要注意的是,默认情况下,常量使用双精度,这意味着它只能使用小于2 ^ 64的双精度浮点数可表示的最大值。

可以通过确保提供给函数的数字为整数而不是双精度数来解决此问题。这可以通过调用例如用函数来实现:ans(uint64(x))


1

PHP,49 46 44字节

echo(2**ceil(log(log(1+$argn,2),2))-2?:2)+2;

像这样运行:

echo 16 | php -R 'echo(2**ceil(log(log(1+$argv[1],2),2))-2?:2)+2;';echo

说明

echo                       # Output the result of the expression
  (
    2**                    # 2 to the power
      ceil(log(            # The ceiling of the power of 2 of bitsize
        log(1+$argn,2),    # Number of bits needed
        2
      ))
      - 2 ?:               # Subtract 2 (will be added back again)
      2;                   # If that results in 0, result in 2 (+2=4).
  ) + 2                    # Add 2.

调整

  • 通过取消$r=分配节省了3个字节
  • 通过使用节省2个字节-R,使$argn可用

1

CJam,18个字节

2ri2b,2mLm]_({)}|#

在线尝试!

说明

2                   Push 2
 ri                 Read an integer from input
   2b,              Get the length of its binary representation
      2mLm]         Take the ceiling of the base-2 log of the length
           _(       Duplicate it and decrement it
             {)}|   Pop the top element, if it's 0, increment the next element
                     Effectively, if ceil(log2(input)) was 1, it's incremented to 2,
                     otherwise it stays the same.
                 #  Raise 2 to that power

0

C,71 52字节

i;f(long long n){for(i=1;n>>i;i*=2);return i-2?i:4;}

(1<<15)+1由于的签名行为,输入或不会中断此输入long long吗?您真正想要的类型是uint64_t,与!相比,#include <stdint.h>仍然是失败者unsigned long long!标头是c中打高尔夫球的祸根。
dmckee '16

@dmckee我猜它可能会破坏它,但是它似乎至少在我的计算机上可以工作。还没有找到一个行不通的例子。我考虑过使用unsigned long longor uint64_t,但是因为它似乎可以使用,long long所以我选择了使用它。
Steadybox

0

QBIC,27个字节

:~a<2|_Xq]{~a<2^t|_Xt\t=t*2

说明

:        Get cmd line parameter N, call it 'a'
~a<2     IF 'a' is 0 or 1 (edge case)
|_Xq]    THEN quit, printing 1 ('q' is auto-initialised to 1). ']' is END-IF
{        DO - infinite loop
    2^t  't' is our current number of bits, QBIC sets t=4 at the start of the program.
         2^t gives the maximum number storable in t bytes.
 ~a<     IF the input fits within that number,
|_Xt     THEN quit printing this 't'
\t=t*2   ELSE jump to the next bracket (which are spaced a factor 2 apart, from 4 up)
         DO-loop is auto-closed by QBIC.

0

Pyke,13个字节

7Zm@2-#2R^<)h

在这里尝试!

7Zm@          -   [set_bit(0, i) for i in range(7)] <- create powers of 2
    2-        -  ^.remove(2)
      #    )h - filter(^, V)[0]
       2R^    -   2 ** i
          <   -  input < ^

0

PHP,43字节

for(;1<<2**$i++<=$argn;);echo 2**$i-=$i!=2;

用运行echo <number> | php -R '<code>'

循环$i直到2**(2**$i)大于输入。(调整:<<而不是**消除括号)
。循环之后,$ i太高;因此在计算输出之前它会递减
-但不是$i==2

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.