İkili Geri Sayım Uzunluğu


18

esinlenerek sonsuzdan geri sayım

Negatif olmayan bir tamsayı verildiğinde N, 0'a ulaşmak için gereken aşağıdaki adımların tekrar sayısını girin:

  1. Nİkili biçime dönüştür ( 4812390 -> 10010010110111001100110)
  2. Her biti çevirin ( 10010010110111001100110 -> 01101101001000110011001)
  3. Baştaki sıfırları kırp ( 01101101001000110011001 -> 1101101001000110011001)
  4. Ondalık biçime dön ( 1101101001000110011001 -> 3576217)

kurallar

  • Giriş ve çıkış herhangi bir kesin ve tutarlı biçimde olabilir
  • Giriş, diliniz için yerel temsil edilebilir tamsayı aralığında olacaktır (diliniz keyfi olarak büyük tam sayıları destekliyorsa, sınır yoktur)

Test Durumları

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

Bu dizi OEIS'de A005811'dir .


6
Adım 3 hiç
işe yaramıyor

@ edc65 Algoritmanızın nasıl düzenlendiğine bağlı olarak 3. veya 4. adımı uygulayabileceğiniz anlaşılıyor
Brian J

@ edc65 Belki sizin için bir yararı yoktur. Basit bir ters operatör sizin için sıfırları kırpmaz. ~(~a) == a
Poke

@Poke Bitwise NOT , önde gelen sıfırlar (ve rastgele hassas tamsayıları olan dillerde sonsuz sayıda) dahil olmak üzere ikili gösterimin tüm bitlerini tersine çevirir . Bu adım 2 ile eşdeğer değildir
Dennis

@Poke Basit bir ters işlem, 1..4 adımlarının uygulanmasından farklıdır. Bu adımları uygulamak istiyorsanız, 3. adımın hiçbir faydası yoktur, çünkü 2. adımdaki kapak (gösterildiği gibi) önde gelen 0'ları değiştirmez. 2. adım ise gelmez lider 1'ler için bir 0 değiştirebilir ve ardından obviuosly sen lider kaldırmak zorunda 1'leri değil lider 3. adımda 0sn
edc65

Yanıtlar:


14

Jöle , 6 4 bayt

^HBS

Çevrimiçi deneyin! veya tüm test senaryolarını doğrulayın .

Arka fon

Let , n , negatif olmayan bir tam sayı olması.

Adım 2 ve spec tarif edilen prosesin 3 alternatif olarak, tüm gelen kaldırma olarak ifade edilebilir 1 'in, geri kalan bitleri geçiş.

Bu, her bir yinelemede tam olarak bir bitişik ve eşit ikili basamak grubunu kaldıracağımız anlamına gelir, bu nedenle n'nin İkili Geri Sayım Uzunluğu , bu grupların yalnızca , n . Bu zorluğun amaçları için, 0'ı rakam içermiyor olarak düşünün .

İçin n = 8675309 , süreç görünüyor ikili aşağıdaki şekilde.

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

Bu grupları saymak yerine (kenar durumu 0 için başarısız olur ) aşağıdakileri yaparız.

n ve n: 2 aşağıdaki ikili gösterimleri vardır.

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

N: 2 olduğuna dikkat edin 'in ikili gösterimi basitçe n s', sola bir bit kaydırılmakta.

XOR n ve n: 2 olursa , 1 (MSB) ve ek 1 elde edeceğiz farklı komşu basamak çifti için. Böylece grup sayısı n ⊻ n: 2'de ayarlanan bit sayısına eşittir .

Nasıl çalışır

^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
İnanılmaz! Tamamen farklı bir akıl yürütme
edc65

9

Python 2, 30 bayt

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

Ideone üzerinde test edin .

Arka fon

Let , n , negatif olmayan bir tam sayı olması.

Adım 2 ve spec tarif edilen prosesin 3 alternatif olarak, tüm gelen kaldırma olarak ifade edilebilir 1 'in, geri kalan bitleri geçiş.

İkili sayım uzunluğu bu nedenle, her tekrarında bitişik ve eşit ikili basamak tam olarak bir grubunu çıkarmak gerekir, bu araçlar n ikili gösterimi bu grupların sadece bir sayıdır , n . Bu zorluğun amaçları için, 0'ı rakam içermiyor olarak düşünün .

İçin n = 8675309 , süreç görünüyor ikili aşağıdaki şekilde.

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

Bu grupları saymak yerine (kenar durumu 0 için başarısız olur ) aşağıdakileri yaparız.

n ve n: 2'nin aşağıdaki ikili gösterimleri vardır.

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

Not, n = 2'nin 'in ikili gösterimi basitçe n s', sola bir bit kaydırılmakta.

Biz, XOR ise n ve n = 2 , bir elde edeceğiz 1 (MSB) ve ilave bir 1 farklı komşu basamak çifti için. Böylece grup sayısı n ⊻ n: 2'de ayarlanan bit sayısına eşittir .


9

Python 2, 29 bayt

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

İkili genişletmede 0 ile 1 arasındaki alternatiflerin sayısını sayar ve baştaki 1'i alternatif olarak sayar. Bunu, son iki ikili basamağın farklı olup olmadığını kontrol ederek, son basamağın çıkarıldığı sayıya yineleyerek yapar. Son iki basamak n%4, 1 veya 2 ise tam olarak farklıdır -n%4/2;


6

JavaScript (ES6), 26 bayt

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

0 ile 1 arasındaki geçişleri sayarak çalışır. Yalnızca 31 bite kadar çalışır. 53 biti desteklemek için 29 bayt:

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

5

Haskell, 34 bayt

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

Ben "0 = 0" diyor nasıl seviyorum :)
AlexR


3

CJam , 14 bayt

ri0{2b:!2bj)}j

Çevrimiçi deneyin!

ri      e# read integer
0       e# value for terminal case
{       e# recursive function
  2b    e#   create binary representation with no leading zeros
  :!    e#   flip bits
  2b    e#   convert binary back to integer
  j     e#   recursive call
  )     e#   increment from 0 on the way up
}j      e# end

Temelde diğer soruya verdiğim cevabın çalınması


3

Java 7,112108100 90 73 bayt

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);}

Temel fikir

 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/2kısaltılabilir j/=2. Bunun dışında harika bir cevap!
Kevin Cruijssen

Hmm .. @Neil'in JavaScript yanıtından bir bağlantı noktası daha kısa olsa da: int c(int i){return i>0?((i^(i>>=1))%2+c(i):0;}( 47 bayt ). Yine de mevcut cevabınızı bırakıyorum, çünkü daha orijinal ve diğer kullanıcıların portları orijinalin tam tersidir. :)
Kevin Cruijssen

3

J, 14 bayt

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

Özel durum n = 0 için 0 döndürülürken, n'nin ikili basamaklarındaki çalışma sayısını sayar .

kullanım

   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

açıklama

**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 bayt

@Dennis'e bir bayt kaydettiği için teşekkürler!

ri_2be`,e&

Çevrimiçi deneyin!

açıklama

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&(mantıksal AND) bir bayt kaydeder \g*.
Dennis

@Dennis Teşekkürler! CJam'ın mantıksal VE nasıl çalıştığı kullanışlı, hiçbir fikrim yoktu
Luis Mendo

2

Raket 349 bayt

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

Ungolfed:

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

Test yapmak:

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

Çıktı:

0
1
6
3
8
1
10
11
14
28
32

tlVe ib1 baytlık adları değiştirerek 2 bayt kaydedebilirsiniz .
Mego

Bitti. Önerin için teşekkürler.
rnso

2

MATL , 7 bayt

BY'nwa*

Çevrimiçi deneyin!

açıklama

          % 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

Vim, 62 59 bayt

DJMcMayhem sayesinde -3 bayt

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

Yazdırılamayan karakterler sağlam olan xxd çıktısı:

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

Çevrimiçi deneyin!

açıklama

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
Güzel! Bazı ipuçları: :s/^0*bir bayt daha kısadır :s/^0\+ve "eval" kaydındayken sadece pr<S-tab>'%b',<C-r>")otomatik tamamlama için yapabilirsiniz . (4 bayt kaydeder)
DJMcMayhem

Otomatik tamamlama ipucu için teşekkürler! Kullanamıyorum :s/^0*çünkü boş bir çizgiyle eşleşiyor ve yinelemeli makrodan kaçmak için boş bir çizginin başarısız olması gerekiyor.
Ürdün

1

Ruby, 26 bayt

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

Xnor'ın Python cevabından ilham aldı.


0

PHP, 64 bayt

geri sayım çözümüme dayanarak

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

1karakter ksürelerini yazdırır k, yineleme sayısı nerede .


Tam sayı çıktısı için +4 bayt: (boş çıktı için 0)

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

0

JavaScript (ES6), 44

Özyinelemeli işlev

Javascript pozitif tam sayı, 31 bit ile sınırlıdır:

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

53 anlamlı bit'e kadar çift hassasiyetli sayıyı yönetme - 59 bayt:

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

Başka bir şekilde: 53 bit, 43 bayt yöneten özyinelemesiz işlev @Dennis tarafından şaşırtıcı algoritmayı kullanarak :

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

0

PHP, 51 bayt

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

1 veya 0 çalışma sayısını saymak için bir normal ifade kullanır. Ne yazık ki, bu girdi 0için 3 ek bayt gerektiren özel bir durum gerekir (ve bir uyarı verir).


a) Uyarıyı oönlemek için > 1 rakamı kullanın . b) -FBayrağı $argnyerine 3 bayt kaydedebilirsiniz $argv[1]. c) /1+|0+/normal ifade için yeterli olmalıdır.
Titus

0

Java 7, 71 bayt

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

Bunun Geobits'in splitçözümü ile dövüldüğünü biliyorum (ki sonunda yayınlanacak) ama yazmak hala eğlenceliydi


0

Oktav, 47 bayt

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

OEIS girişine göre, bu zorluğun çözümü olarak aradığımız değer de sayısına eşit1 , verilen tamsayı için Gray kodundaki s .

Wikipedia bana Gray kodunun x ^ (x >> 1) olarak hesaplanabileceğini söylüyor, bu yüzden yukarıdaki fonksiyonda Gray kodunu bu şekilde hesaplıyorum, bir ikili dizeye dönüştürüyorum ve bu dizenin kaç basamağını sayıyorum 1.


0

Java 7, 64 bayt

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

Bunun daha iyi cevaplar birinin bir port tarafından dövüldü olabilir biliyorum, ama sohbet onunla geldi ve ben olamaz değil sonra post it Poke bu konuda bir şey söyledi :)


0

C, 76 Bayt

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;}

Tüm test senaryoları için çalışır (imzasız veya son test senaryosu kelimesini dahil etmek istemediğim kadar) ...


0

Bash, 57 bayt

Paketler: Core Utililities, grep, sed, vim (için xxd)

Sayının ikili biçimde verildiğini varsayın. Herhangi bir uzunluk kabul edilebilir :)

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


0

Tcl , 119 bayt

proc D n i\ 0 {
while \$n {set n [regsub ^0+(?=.) [string map {0 1 1 0} [format %b $n]] ""]
incr i
scan $n %b n}
set i}

Çevrimiçi deneyin!

Hala zevkime göre çok rahat

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.