バイナリカウントダウンの長さ


18

無限からカウントダウンに触発

負でない整数を指定するとN、0に到達するまでにかかる次のステップの繰り返し回数を出力します。

  1. 変換Nバイナリに(4812390 -> 10010010110111001100110
  2. 各ビットを反転(10010010110111001100110 -> 01101101001000110011001
  3. 先行ゼロのトリム(01101101001000110011001 -> 1101101001000110011001
  4. 10進数に戻す(1101101001000110011001 -> 3576217

ルール

  • 入力と出力は、明確で一貫性のある任意の形式にすることができます
  • 入力は、言語のネイティブで表現可能な整数範囲内にあります(言語が任意の大きな整数をサポートしている場合、制限はありません)

テストケース

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

このシーケンスは、OEISではA005811です。


6
ステップ3はまったく
役に立ち

@ edc65アルゴリズムのレイアウト方法に応じて、ステップ3またはステップ4を実行できるようです
ブライアンJ

@ edc65たぶんあなたには役に立たないでしょう。単純な逆演算子は、先頭のゼロをトリミングしません。~(~a) == a
ポケ

@Poke Bitwise NOTは、先行ゼロ(および任意の精度の整数を持つ言語では無限の量)を含むバイナリ表現のすべてのビットを反転ます。これは、手順2と同等ではありません
デニス

@Poke単純な逆演算は、ステップ1..4。の適用とは異なります。これらの手順を適用する場合、手順2は(示されているように)フリップしても先頭の0が変更されないため、手順3は役に立ちません。ステップ2は、場合ない大手1Sにつながる0に変更し、obviuoslyあなたは一流削除する必要が1秒を、ないリーディングステップ3で0
edc65

回答:


14

ゼリー6 4 バイト

^HBS

オンラインでお試しください!または、すべてのテストケースを確認します

バックグラウンド

してみましょうnは非負の整数です。

仕様で説明されているプロセスのステップ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であり、1ビット左にシフトしていることに注意してください。

nn:2の XORをとると、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でテストします。

バックグラウンド

してみましょうnは非負の整数です。

仕様で説明されているプロセスのステップ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であり、1ビット左にシフトしていることに注意してください。

nn:2の XORをとると、1(MSB)を取得し、隣接する異なる数字のペアごとに1を追加します。したがって、グループの数は、n⊻n:2の設定ビットの数に等しくなります。


9

Python 2、29バイト

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

バイナリ展開で0から1までの交互の数をカウントし、先頭の1を交互としてカウントします。これは、最後の2桁が異なるかどうかを確認してから、最後の桁を削除して数値に再帰します。最後の2桁はn%4、1または2の場合はまったく異なります-n%4/2


6

JavaScript(ES6)、26バイト

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

0と1の間の遷移をカウントすることにより機能します。最大31ビットまでしか機能しません。53ビットをサポートする29バイト:

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

5

Haskell、34バイト

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

「0 = 0」と言うのが好きです:)
AlexR



3

Java 7、112108100 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。それとは別に素晴らしい答えです!
ケビンCruijssen

うーん... @NeilのJavaScriptの回答からのポートは短いですが:int c(int i){return i>0?((i^(i>>=1))%2+c(i):0;}47バイト)。ただし、現在の回答もそのまま残しておきます。これはより独創的であり、他のユーザーからのポートはオリジナルとは完全に反対だからです。:)
ケビンクルーイッセン

3

J、14バイト

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

nの2進数で実行回数をカウントします。n = 0の場合は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

CJam11 10バイト

1バイト節約してくれた@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&(論理AND)は1バイトを節約します\g*
デニス

@デニスありがとう!CJamの論理ANDがどのように機能するかは便利です。見当がつかなかった
ルイスメンドー

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

tlおよびibを1バイトの名前に変更すると、2バイト節約できます。
メゴ

できた 提案をありがとう。
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

Vim、62 59バイト

DJMcMayhemのおかげで-3バイト

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*は1バイトよりも短いため:s/^0\+、「評価」レジスタにいる間はpr<S-tab>'%b',<C-r>")、オートコンプリートを行うことができます。(4バイトを保存)
DJMcMayhem

ああ、オートコンプリートのヒントをありがとう!:s/^0*空の行と一致するため使用できません。空の行を空にして再帰マクロをエスケープするには失敗する必要があります。
ヨルダン

1

ルビー、26バイト

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

xnorのPythonの答えに触発されました。


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バイトの追加が必要な(および通知を行う)入力のための特別なケースが必要です。


a)o通知を回避する代わりに、1より大きい数字を使用します。b)-Fフラグの$argn代わりに、の代わりに3バイトを保存できます$argv[1]。c)/1+|0+/正規表現で十分です。
タイタス


0

オクターブ、47バイト

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

OEISエントリによると、この課題の解決策として求めている値は、指定された整数のグレイコードのs の数に等しくなり1ます。

ウィキペディアによると、グレーコードはx ^(x >> 1)として計算できるため、上記の関数ではグレーコードを計算し、バイナリ文字列に変換して、その文字列の桁数を数えます1


0

Java 7、64バイト

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

私はこれがより良い答えの1つのポートによってbeatられる可能性があることを知っていますが、チャットでそれを思い付きました、そして私はその後それを投稿することはできませポケがそれについて何かを言っ :)


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

すべてのテストケースで機能します(「unsigned」または「最後のテストケース」という単語を含めたくない場合)。


0

Bash、57バイト

パッケージ:Core Utililities、grep、sed、vim(for xxd

番号がバイナリ形式で与えられていると仮定します。どんな長さでもかまいません:)

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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.