Трохи, кусання чи байт?


45

Натхненний цим викликом

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

  • біт: 1
  • гризти: 4
  • байт: 8
  • короткий: 16
  • int: 32
  • довгий: 64

Тести:

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

2
Дякую! Я зрозумів це, коли написав коментар і відредагував його занадто пізно. Я думаю, мені потрібна гумова качка, щоб поговорити ...
z0rberg

2
@Daniel відповіді тут застосовують зовсім інший підхід до іншого питання. Коли я кажу "натхненний", це не означає "дублікат". Жодна відповідь не може бути тривіально модифікована, щоб бути дійсною для цього питання
Блакитний

Відповіді:



22

Пітон, 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))?
dfernan

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

1
@trichoplax, це правильно. Дякую за пояснення.
dfernan

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 у Дж. Перший очевидний 2^., що є числовим логарифмом. Друге - #@#:це може бути прочитано як "довжина подання бази-2". Це майже еквівалентно одному-плюс-підлоги-log-base-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

8

Математика, 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

Математика, 46 43 38 байт

Дякуємо JungHwan Min та Мартіну Ендеру за збереження 3-х байт! Завдяки ngenisis за велику 5-байтну економію!

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

Безіменна функція, що приймає як вхідне невід’ємне ціле число і повертає додатне ціле число. BitLength@#обчислює кількість бітів на вході, а потім 2^⌈Log2@...⌉обчислює найменшу потужність 2, що принаймні така велика, як кількість біт. Нарешті, /.{2->4,0->1}піклується про особливий випадок, щоб між бітом і nybble не було "niblit", а також фіксує відповідь на дивне введення 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 х більше, ніж на вході. Перший такий елемент - відповідь. На жаль, це вимагає просування 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-байтний альт:

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 ** p.
ГБ

... тому що тоді ви могли використовувати 0, * 2..6.
ГБ

2

Java 8, 65 55 байт

Це лямбда-вираз, який приймає 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, поки цикл виконає лише наступний рядок
Kritixi Lithos

@KritixiLithos слід виправити зараз - вибачте, моя Java пішла
іржавою

2

Математика, 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

Складено, 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

Ось приклад роботи над відбитком :

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

Налаштування

  • Збережено 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! Заголовки - це поле для гольфу в с.
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.