Немного, клев или байт?


45

Вдохновленный этим вызовом

Учитывая целое число в диапазоне 0 <= n < 2**64, выведите контейнер минимального размера, в который он может поместиться

  • бит: 1
  • клев: 4
  • байт: 8
  • коротко: 16
  • int: 32
  • длинный: 64

Testcases:

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

Это , поэтому выигрывает самый короткий ответ в байтах.


10
Это было бы значительно проще, если бы 2был выход ...
ETHproductions

1
@ETHproductions Было бы, но, увы, это не так (мне потребовалось много времени, чтобы написать алгоритм, который это сделал)
Blue

Я хотел бы понять проблему. ... подождите, все, что нужно, это количество бит, необходимое для хранения числа, округленного до следующей фундаментальной структуры?
Z0rberg's

2
Спасибо! Я понял это, когда написал комментарий и отредактировал его слишком поздно. Я думаю, мне нужна резиновая утка, чтобы поговорить ...
z0rberg

2
@ Даниэль ответы здесь принимают совершенно другой подход к другому вопросу. Когда я говорю «вдохновленный», это не означает «дубликат». Ни один ответ не может быть тривиально изменен, чтобы быть действительным для этого вопроса
Blue

Ответы:


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 для 1.


41 байт:

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

Неоднократно удваивает показатель степени iдо 2**i>n. Переходит от i=1к i=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))?
Дфернан

2
@dfernan Я полагаю, что часть после orоценивается, только если часть до оценивается как нечто ложное (ноль). Для n = 0 и для n = 1 n>1оценивается как False, что рассматривается как ноль в числовом выражении, и n<16оценивается как True, что рассматривается как единица в числовом выражении. Так 4**(n>1)*(n<16)что 1.
Трихоплакс

1
@ trichoplax, это правильно. Спасибо за объяснение.
Дфернан

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

Круто, что мы видим два разных способа получения логарифмической базы 2 в J. Первый - очевидный 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]на один байт короче
Blue

Собирался опубликовать что-то подобное. +1
ElPedro

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 ^ больше, чем вход.


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)должна быть немного короче.
Арно

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}заботится о специальном случае, когда между битом и nybble нет «ниблита», а также исправляет ответ для странного ввода 0.


2
Сохраните 3 байта, используя BitLength@#вместо ⌊1+Log2@#⌋. Тогда вместо того , чтобы заменить с 1вами можно заменить 0, экономя еще 2 байта , и вы привязаны к первому.
ngenisis

1
Это на самом деле может быть сделано полностью с BitLength. Смотрите мой ответ
ngenisis

4

Юлия, 40 байт

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

Это анонимная функция, которая генерирует массив степеней 2 от 0 до 6, исключая 2, и фильтрует его только по тем элементам x , что 2 x больше, чем вход. Первый такой элемент - это ответ. К сожалению, это требует повышения 2 до a, BigIntчтобы избежать переполнения при x = 64.

На самом деле это очень похоже на Python-ответ orlp, хотя я не видел его до того, как придумал этот подход.

Попробуйте онлайн!


4

Perl 6 , 30 байт

{first 1+<*>$_,1,4,8,16,32,64}

+<является оператором сдвига левого бита в Perl 6, который многие другие языки называют <<.


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

@ Миндвин Я знаю, но я путешествую и некоторое время не буду иметь доступ к компьютеру. Я обойду это.
Павел

Счет делает это ... любовным байтом ?
Инженер Тост


2

Рубин, 39 36 байт

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

Спасибо ГБ за помощь в гольфе


Также должно работать без скобок. Также список может быть 0,2,3,4,5,6 с использованием 1 << 2 ** с.
GB

... потому что тогда вы можете использовать 0, * 2..6.
GB

2

Java 8, 65 55 байт

Это лямбда-выражение, которое принимает 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
устарела

2

Mathematica, 30 байт

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

Объяснение:

Позвольте Nбыть набор неотрицательных целых чисел. Определите две функции N, BitLengthи NextPowerследующим образом:

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 < 0, BitLength[n] == BitLength[BitNot[n]] == BitLength[-1-n]так BitLength[-1] == BitLength[0] == 0. Таким образом, мы получаем желаемый ответ 1для n==0.

Так как мы сразу перейти от бита к клеву, мы должны заменить ответы 2с 4.


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. Если у меня будет время, я изменю его так, чтобы он работал до 2 ^ 64-1 в версиях bash, в которых используется 32-разрядная знаковая арифметика.

А пока вот 64-байтовое решение, которое работает для произвольно больших чисел (в любой версии bash):

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

2

Stacked, 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))

Ungolfed:

(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.

Tweaks

  • Сэкономили 3 байта, избавившись от $r= назначения
  • Сохранено 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

@ dmckee Я думаю, что это может сломать его, но, похоже, оно работает, по крайней мере, на моем компьютере. Не нашел пример, который бы не работал. Я думал об использовании unsigned long longили 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

PHP, 43 байта

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

Бежать с echo <number> | php -R '<code>' .

зацикливается $iдо тех пор, пока не 2**(2**$i)станет больше, чем ввод. (Твик: <<вместо того, **чтобы исключать парены)
После цикла, $ i слишком велик; поэтому он получает декремент перед вычислением результата
- но не для $i==2.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.