A bit, a nibble or byte?
Python, 39 bytes
f=lambda n:4**(n>1)*(n<16)or 2*f(n**.5)
Counts how many times one must take the square root for n
to be below 16
, with some special-casing to avoid outputs of 2.
If 2 were included, we could do
f=lambda n:n<2or 2*f(n**.5)
with True for 1.
41 bytes:
f=lambda n,i=1:i*(2**i>n)or f(n,i<<1+i%2)
Repeatedly doubles the exponent i
until 2**i>n
. Skips from i=1
to i=4
by shifting an additional bit when i
is odd.
Alt 45 bytes:
f=lambda n,i=4:4**(n>1)*(2**i>n)or 2*f(n,i*2)
J, 19 bytes
Monadic verb taking the number on the right and spitting out the container size. There are a couple of equivalent ways of writing it so I've included both.
2^2(>.+1=>.)@^.#@#:
2^s+1=s=.2>.@^.#@#:
Explained by explosion:
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
What's cool is we see two different ways of taking log base 2 in J. The first is the obvious 2^.
, which is a numerical logarithm. The second is #@#:
, which can be read as "length of base-2 representation". This is almost equivalent to one-plus-floor-of-log-base-2, except that #:0
is the one-element list 0
, which is exactly what we want. This beats 1+2<.@^.1&>.
by 8 bytes.
In use at the 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
Old, overly clever 20 byte solution.
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
Python, 53 50 49 bytes
lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]