Двійкова довжина зворотного відліку


18

натхненний відлік від нескінченності

Враховуючи невід'ємне ціле число N, виведіть кількість повторень наступних кроків, необхідних для досягнення 0:

  1. Перетворити Nу бінарний ( 4812390 -> 10010010110111001100110)
  2. Переверніть кожен біт ( 10010010110111001100110 -> 01101101001000110011001)
  3. Обрізання провідних нулів ( 01101101001000110011001 -> 1101101001000110011001)
  4. Перетворити назад у десятковий ( 1101101001000110011001 -> 3576217)

Правила

  • Введення та вихід можуть бути у будь-якому однозначному, послідовному форматі
  • Вхід буде знаходитись в натурному цілому діапазоні для вашої мови (якщо ваша мова підтримує довільно великі цілі числа, немає обмежень)

Випробування

0 -> 0
1 -> 1
42 -> 6
97 -> 3
170 -> 8
255 -> 1
682 -> 10
8675309 -> 11
4812390 -> 14
178956970 -> 28
2863311530 -> 32

Ця послідовність є A005811 в OEIS.


6
Крок 3 взагалі не
корисний

@ edc65 Здається, ви могли б зробити або крок 3, або крок 4, залежно від того, як складений ваш алгоритм
Брайан Дж

@ edc65 Можливо, для вас це не приносить користі. Простий зворотний оператор не обробляє для вас провідні нулі. ~(~a) == a
Поки

@ Poke Bitwise НЕ інвертує всі біти двійкового подання, включаючи провідні нулі (і нескінченну їх кількість в мовах з довільними цілими числами точності). Це не рівноцінно кроку 2.
Денніс

@ Poke Проста обернена операція відрізняється від застосування кроків 1..4. Якщо ви хочете застосувати ці кроки, крок 3 не принесе користі, оскільки перегортання на кроці 2 (як показано на малюнку) не змінює провідні 0. Якщо крок 2 робить зміна провідних 0s провідних 1s, то obviuosly ви повинні видалити провідні 1s на кроці 3, не ведуть 0s
edc65

Відповіді:


14

Желе , 6 4 байти

^HBS

Спробуйте в Інтернеті!або перевірити всі тестові випадки .

Фон

Нехай н - невід'ємне ціле число.

Етапи 2 і 3 процесу, описаного в специфікації, альтернативно можна констатувати як видалення всіх провідних 1 -х та перемикання решти бітів.

Це означає, що ми видалимо рівно одну групу суміжних і рівних двійкових цифр у кожній ітерації, тому двійкова довжина зворотного відліку n - це лише кількість цих груп у двійковому поданні n . Для цілей цього виклику подумайте 0 не має цифр.

Для n = 8675309 процес виглядає у двійковій формі так.

100001000101111111101101
 11110111010000000010010
     1000101111111101101
      111010000000010010
         101111111101101
          10000000010010
           1111111101101
                   10010
                    1101
                      10
                       1
                       0

Замість того, щоб рахувати ці групи (що не вдасться до кращого випадку 0 ), ми робимо наступне.

n і n: 2 мають такі бінарні подання.

n   = 8675309 = 100001000101111111101101_2
n:2 = 4337654 =  10000100010111111110110_2

Зауважимо, що двійкове подання n: 2 просто n 's, зміщене на один бік вліво.

Якщо ми XOR n і n: 2 , отримаємо 1 (MSB) і додатковий 1 для кожної пари різних суміжних цифр. Кількість груп, таким чином, дорівнює кількості встановлених бітів у n ⊻ n: 2 .

Як це працює

^HBS  Main link. Argument: n

 H    Halve; yield n:2.
^     XOR n with n:2.
  B   Convert the result to binary.
   S  Compute the sum of the resulting binary digits.

1
Дивовижний! Зовсім інше міркування
edc65

9

Python 2, 30 байт

lambda n:bin(n^n/2).count('1')

Перевірте це на Ideone .

Фон

Нехай н - невід'ємне ціле число.

Етапи 2 і 3 процесу, описаного в специфікації, альтернативно можна констатувати як видалення всіх провідних 1 -х та перемикання решти бітів.

Це означає, що ми видалимо рівно одну групу суміжних і рівних двійкових цифр у кожній ітерації, тому двійкова довжина зворотного відліку n - це лише кількість цих груп у двійковому поданні n . Для цілей цього виклику подумайте 0 не має цифр.

Для n = 8675309 процес виглядає у двійковій формі так.

100001000101111111101101
 11110111010000000010010
     1000101111111101101
      111010000000010010
         101111111101101
          10000000010010
           1111111101101
                   10010
                    1101
                      10
                       1
                       0

Замість підрахунку цих груп (що не вдасться до кращого випадку 0 ), ми робимо наступне.

n і n: 2 мають такі бінарні подання.

n   = 8675309 = 100001000101111111101101_2
n:2 = 4337654 =  10000100010111111110110_2

Зауважимо, що двійкове представлення n: 2 просто n 's, зміщене на один бік вліво.

Якщо ми XOR n і n: 2 , отримаємо 1 (MSB) і додатковий 1 для кожної пари різних суміжних цифр. Кількість груп, таким чином, дорівнює кількості встановлених бітів у n ⊻ n: 2 .


9

Python 2, 29 байт

f=lambda n:n and-n%4/2+f(n/2)

Підраховує кількість чергувань між 0 і 1 у бінарному розширенні, рахуючи провідне 1 як чергування. Це робиться, перевіряючи, чи відрізняються останні дві двійкові цифри, а потім повторно повторюється на число з видаленою останньою цифрою. Останні дві цифри відрізняються точно, якщо n%4є 1 або 2, що можна перевірити як -n%4/2.


6

JavaScript (ES6), 26 байт

f=n=>n&&(n^(n>>=1))%2+f(n)

Працює підрахунком переходів між 0 і 1. Працює до 31 біт. 29 байт для підтримки 53 біта:

f=n=>1<=n&&(n%2^n/2%2)+f(n/2)

5

Хаскелл, 34 байти

b 0=0
b n|x<-b$div n 2=x+mod(x+n)2

Мені подобається, як там написано "0 = 0" :)
AlexR



3

Java 7,112 108 100 90 73 байти

int c(int i){int l=1,j=i;for(;(j=j/2)>0;l*=2);return i<1?0:1+c(2*l-1-i);}

Основна ідея

 Lets take an no 10110(21)
 then you do set all bits in no 21 and you will get 11111
 and after that you would subtract the original number from 11111.
 You will get 01001 and loop it until you will get 0

j=j/2можна скоротити до j/=2. Крім цього чудова відповідь!
Кевін Кройсейсен

Хм .. порт від JavaScript на @Neil відповідь коротший: int c(int i){return i>0?((i^(i>>=1))%2+c(i):0;}( 47 байт ). Я б все-таки залишив вашу теперішню відповідь, оскільки вона оригінальніша, а порти інших користувачів - це повна протилежність оригіналу. :)
Кевін Кройсейсен

3

J, 14 байт

**1+/@,2~:/\#:

Підраховує кількість прогонів у двійкових цифрах n, при цьому спеціальний регістр повертає 0 при n = 0.

Використання

   f =: **1+/@,2~:/\#:
   (,.f"0) 0 1 42 97 170 255 682 8675309 4812390 178956970 2863311530
         0  0
         1  1
        42  6
        97  3
       170  8
       255  1
       682 10
   8675309 11
   4812390 14
 178956970 28
2863311530 32

Пояснення

**1+/@,2~:/\#:  Input: integer n
            #:  Get the binary digits of n
       2   \    For each overlapping sublist of size 2
        ~:/       Reduce by not-equals
  1   ,         Prepend a 1
   +/@          Reduce by addition
*               Sign(n), returns 0 for n = 0 else 1
 *              Multiply with the previous sum and return

3

CJam , 11 10 байт

Дякуємо @Dennis за збереження одного байта!

ri_2be`,e&

Спробуйте в Інтернеті!

Пояснення

ri            #e Read as integer
              #e STACK: 97
  _           #e Duplicate
              #e STACK: 97, 97
   2b         #e Convert to binary
              #e STACK: 97, [1 1 0 0 0 0 1]
     e`       #e Run-length encoding
              #e STACK: 97, [[2 1] [4 0] [1 1]]
       ,      #e Length
              #e STACK: 97, 3
        e&    #e Return first value if 0, or else the second value
              #e STACK: 3

1
e&(логічно І) зберігає байт на \g*.
Денніс

@Dennis Дякую! Це зручно, як працює логічний AND CJam, я не мав уявлення
Луїс Мендо

2

Ракетка 349 байт

(define(h s)(apply string(map(λ(x)(if(eq? x #\0)#\1 #\0))(string->list s))))(define(g s)(let*
((l(string-length s))(k(for/list((i s)(n l)#:final(not(equal? i #\0)))n)))(substring s(last k))))
(define(f n)(if(= 0 n)0(begin(let loop((n n)(c 1))(define m(string->number(string-append "#b"
(g(h(number->string n 2))))))(if(> m 0)(loop m(add1 c))c))))

Безумовно:

(define (invertBinary s)
  (apply string
         (map
          (λ(x)(if(eq? x #\0)#\1 #\0))
          (string->list s))))

(define (trimLeading0s s)
  (let* ((l (string-length s))
         (k (for/list ((i s)
                       (n l)
                       #:final (not(equal? i #\0)))
              n)))
    (substring s (last k))))

(define (f n)
  (if (= 0 n) 0
      (begin
        (let loop ((n n)
                   (c 1))
          (define m 
            (string->number
             (string-append
              "#b"
              (trimLeading0s
               (invertBinary
                (number->string n 2))))))

          (if (> m 0)
              (loop m (add1 c))
              c)))))

Тестування:

(f 0)
(f 1)
(f 42)
(f 97)
(f 170)
(f 255)
(f 682)
(f 8675309)
(f 4812390)
(f 178956970)
(f 2863311530)

Вихід:

0
1
6
3
8
1
10
11
14
28
32

Ви можете зберегти 2 байти, змінивши tlі ibоднобайтні імена.
Мего

Зроблено. Дякую за пропозицію.
rnso

2

MATL , 7 байт

BY'nwa*

Спробуйте в Інтернеті!

Пояснення

          % Implicit input, for example 97
          % STACK: 97
B         % Convert to binary
          % STACK: [1 1 0 0 0 0 1]
 Y'       % Run-length encoding
          % STACK: [1 0 1], [2 4 1]
   n      % Number of elements
          % STACK: [1 0 1], 3
    w     % Swap
          % STACK: 3, [1 0 1]
     a    % Any: gives 1 if any element is nonzero
          % STACK: 3, 1
      *   % Multiply
          % STACK: 3
          % Implicit display

2

Вим, 62 59 байт

-3 байти завдяки DJMcMayhem

C0
<C-r>=pri<Tab>'%b',<C-r>")
<Esc>0qqC<C-r>=tr(@",'01','10')
<Esc>:s/^0\+
k<C-a>j@qq@q

Ось вихід xxd з неушкодженими недрукованими символами:

0000000: 4330 0d12 3d70 7269 0927 2562 272c 1222  C0..=pri.'%b',."
0000010: 290d 1b30 7171 4312 3d74 7228 4022 2c27  )..0qqC.=tr(@",'
0000020: 3031 272c 2731 3027 290d 1b3a 732f 5e30  01','10')..:s/^0
0000030: 5c2b 0d6b 016a 4071 7140 71              \+.k.j@qq@q

Спробуйте в Інтернеті!

Пояснення

C                                   " Delete the number (it goes in @")
0<CR>                               " Print 0 (our counter) and a carriage return
<C-r>=pri<Tab>'%b',<C-r>")<CR><Esc> " Use `printf()` to insert the number as base 2
0qq                                 " Return to column 0, start recording a macro
  C<C-r>=tr(@",'01','10')<CR><Esc>  "   Replace 0s with 1s and vice versa
  :s/^0\+<CR>                       "   Delete leading 0s
  k<C-a>                            "   Increment the number on the line above
  j                                 "   Return to the previous line
  @q                                "   Invoke macro recursively
q@q                                 " Stop recording and invoke macro

1
Приємно! Деякі поради: :s/^0*на один байт коротше :s/^0\+, і поки ви перебуваєте в регістрі "eval", ви можете просто зробити pr<S-tab>'%b',<C-r>")для автозаповнення. (Зберігає 4 байти)
DJMcMayhem

О, дякую за автоматично заповнену пораду! Я не можу використовувати, :s/^0*оскільки він відповідає порожньому рядку, і мені потрібно, щоб він не зміг порожній рядок, щоб уникнути рекурсивного макросу.
Йордан

1

Рубін, 26 байт

f=->n{n<1?0:-n%4/2+f[n/2]}

Надихнув відповідь Pynor на xnor.


0

PHP, 64 байти

на основі мого рішення відліку

for($n=$argv[1];$n;print 1)$n=bindec(strtr(decbin($n),"01",10));

друкує 1символи kразів, де kкількість ітерацій.


+4 байти для цілого виводу: (порожній вихід для 0)

for($n=$argv[1];$n;$i++)$n=bindec(strtr(decbin($n),"01",10));echo$i;

0

JavaScript (ES6), 44

Рекурсивна функція

Обмежено до натурального числа javascript, 31 біт:

f=(a,s=0)=>a?f((-1>>>Math.clz32(a))-a,s+1):s

Управління подвійною точністю до 53 значущих біт - 59 байт:

F=(a,s=0)=>a?F('0b'+a.toString(2).replace(/./g,1)-a,s+1):s

Іншим способом: використовуючи дивовижний алгоритм @Dennis, нерекурсивна функція управління 53 бітами, 43 байти:

a=>a&&a.toString(2).match(/(.)\1*/g).length

0

PHP, 51 байт

<?=preg_match_all('/(1+|0+)/',decbin($argv[1])?:o);

Використовує регулярний вираз для підрахунку кількості запусків 1 або 0. На жаль, для введення цього потрібен окремий випадок, для 0якого потрібні 3 додаткові байти (і дає повідомлення).


а) Використовуйте цифру> 1 замість, oщоб уникнути повідомлення. б) Ви можете зберегти 3 байти за допомогою -Fпрапора і $argnзамість $argv[1]. в) /1+|0+/має вистачити для регулярного виразка.
Тіт

0

Java 7, 71 байт

int b(Long a){return a==0?0:1+b(~a&-1L>>>64-a.toString(a,2).length());}

Я знаю , що це побита Geobits ' splitрішення (яке в кінцевому підсумку буде розміщено) , але це було ще цікаво писати


0

Октава, 47 байт

@(x)(sum(dec2bin(bitxor(x,idivide(x,2)))=='1'))

Відповідно до запису OEIS, значення, яке ми шукаємо як рішення цього завдання, також дорівнює кількості 1s у коді Грея для заданого цілого числа.

Вікіпедія повідомляє мені, що сірий код можна обчислити як x ^ (x >> 1), тому в наведеній вище функції я обчислюю код Grey як такий, перетворюю його у двійковий рядок і підраховую, скільки цифр цієї рядки 1.


0

Java 7, 64 байти

long g(Long n){return n.toString(n,2).split("0+").length*2-n%2;}

Я знаю, що це може бути переможене портом однієї з кращих відповідей, але я придумав це в чаті, і я не можу його публікувати після того, як Поке щось сказав про це :)


0

C, 76 байт

unsigned n,m,i;f(x){for(i=0;x;x^=m-1,i++)for(n=x,m=2;n>>=1;m<<=1);return i;}

Працює для всіх тестових випадків (стільки, скільки я не хочу включати слово без підпису або останній тестовий випадок) ...


0

Баш, 57 байт

Пакети: Основні утиліти, grep, sed, vim (for xxd)

Припустимо, число вказане у двійковому форматі. Будь-яка довжина прийнятна :)

xxd -b -c1|cut -d" " -f2|sed s/^0*//|grep -o .|uniq|wc -l


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.