バイナリ展開の個別の空でないサブシーケンスの数


19

サブシーケンスとは、任意の数の文字を削除することで別のシーケンスから取得できるシーケンスです。明確な空でない部分配列100されています010010100。別個の空でない部分配列で1010あり01000110110101001011101010

正の整数を与え、そのプログラムまたは機能書き込みNのバイナリ膨張の異なる非空のサブシーケンスの数を返しnは

例:since 4100バイナリであり、上記の5つの異なる空ではないサブシーケンスがあることがわかりましたf(4) = 5n = 1から始まり、シーケンスが始まります。

1, 3, 2, 5, 6, 5, 3, 7, 10, 11, 9, 8, 9, 7, 4, 9, 14, 17, 15, 16, 19, 17, 12

ただし、プログラムは、最新のマシンで1秒未満でn <2 50で動作する必要があります。いくつかの大きな例:

f(1099511627775) = 40
f(1099511627776) = 81
f(911188917558917) = 728765543
f(109260951837875) = 447464738
f(43765644099) = 5941674

4
時間制限に同意しません。
-ATaco

1
特にプロットを見た後、これは本当によく聞こえた。結局のところは、私は非常に密接に関連したシーケンスに見えた今年の初め、私は明確な進数、バイナリではない文字列の数を数えて(私が先頭にゼロを割り引いて)サブ配列を撮るとき、あなたが得ます。私はそれをサンドボックス化しさえしましたが、Math.SE投稿の同等性のために、それはいくつかのStern-Brocotチャレンジのだまされたものでした。ただし、シーケンスのプロットは少し良くなっています(つまり、より混oticとしています)。:)
マーティンエンダー

5
@ATaco時間制限には十分な理由があります。効率的なアルゴリズムがあり、興味深く、しかもゴルフに適しています。時間制限がない場合、ほぼすべての回答が、可能なすべてのサブシーケンスをブルートフォースするだけで、非常に迅速に機能しなくなると感じています。ある意味では、彼らは無回答です。
-orlp

回答:


10

Pythonの395バイト 83バイト

[Mr.XCoderのおかげで12バイト:)]

def f(x):
 v=[2,1];c=1
 for i in bin(x)[3:]:k=int(i);c+=v[k];v[1-k]+=v[k]
 return c

オンラインでお試しください!

アルゴリズムに関する注意。アルゴリズムは、指定された位置tのビットによって指定された一意のサブシーケンスの増分を計算します。最初のビットの増分は常に1です。その後、アルゴリズムはビットシーケンスs(t)を実行し、増分v [s(t)]を追加します。各ステップで、s(t)の補数の増分v [1-s(t)]がv [1] + v [0]に更新されます。最終的な数値は、すべての増分の合計です。

O(log2(n))で実行する必要があります。ここで、nは入力番号です。



8

JavaScript(ES6)、53 51バイト

f=(n,r=~(a=[]))=>n<1?~r:f(n/2,r*2-~~a[n&=1],a[n]=r)

テストケース

書式設定およびコメント化

f = (                      // f is a recursive function taking:
  n,                       //   n = integer
  r = ~(                   //   r = last result, initially set to -1
    a = []                 //   and using a[] = last results for 0 and 1,
  )                        //   implicitly initialized to [0, 0]
) =>                       //
  n < 1 ?                  // if n is less than 1:
    ~r                     //   we're done: return -(r + 1)
  :                        // else:
    f(                     //   do a recursive call with:
      n / 2,               //     n / 2
      r * 2 - ~~a[n &= 1], //     updated result = r * 2 - last result for this binary digit
      a[n] = r             //     update last result for this binary digit
    )                      //   end of recursive call

非再帰バージョン、63バイト

@ThePirateBayのおかげで3バイト節約

s=>[...s.toString(2)].map(l=c=>l[p=r,r=r*2-~~l[c],c]=p,r=1)|r-1

テストケース


内部関数(の最初の引数map)をl空の配列の代わりにフラグ変数に割り当てることで、3バイト節約できると思います。

@ThePirateBayいいね。ありがとう!
アーナルド


6

ゼリー、10バイト

B3;BSṛ¦/’S

これは、@ NofPのアルゴリズムに対する@xnorの改良を使用しています

オンラインでお試しください!

バックグラウンド

してみましょう1、...、N有限バイナリシーケンスです。負でない整数k≤nごとに、空であるか、1で終わる一意のサブシーケンス(a 1、...、a kの数としてo kを定義し、一意のサブシーケンスの数としてz kを定義します空または0で終了します

空のシーケンスの唯一のサブシーケンスは空のシーケンスであるため、o 0 = z 0 = 1です。

各インデックスkについて、(a 1、...、a kのサブシーケンスの総数はo k + z k -1です1を引くと、o kz kの両方が空のシーケンスをカウントするという事実を説明します)。したがって、空でないサブシーケンスの総数はo k + z k -2です。チャレンジは、o n + z n -2の計算を要求します。

k> 0の場合は常に、o kおよびz kを再帰的に計算できます。次の2つの場合があります。

  • a k = 1

    Z K = Z K-1以降、1、...、K-1 及び1、...、K-1、1)と同じサブその端部を有し0

    それぞれについて、O K - 1の空でない部分配列1、...、Kにその端部1、我々は末尾除去することができる1はのいずれかを得るために、O K-1 + Z K-1 - 1サブシーケンス(a 1、...、a k-1。逆に、付加1後者の各々にO 、K-1 + Z K-1 - 1件のいずれかにおける配列の結果O K 1 -元の配列。したがって、o k -1 = oK-1 + Z K-1 - 1 O 、K = O 、K-1 + Z K-1

  • a k = 0

    前のケースと同様に、再帰式o k = o k-1およびz k = z k-1 + o k-1を取得します。

使い方

B3;BSṛ¦/’S  Main link. Argument: n (positive integer)

B           Binary; convert n to base 2.
 3;         Prepend a 3.
   B        Binary; convert all integers in the resulting array to base 2, mapping
            0 to [0], 1 to [1], and the prepended 3 to [1, 1].
       /    Reduce the resulting array by the quicklink to the left, which will be 
            called with left argument [x, y] (integer pair) and right argument [j] 
            (either [0] or [1]).
      ¦     Sparse application.
    S           Compute the sum (x + y) and...
     ṛ          for each index in the right argument (i.e., for j)...
            replace the element of [x, y] at that index with (x + y).
       ’    Decrement both integers in the resulting pair.
        S   Take the sum.

ちょっとデニス、アルゴリズムが機能する理由について簡単な説明を追加していただけますか?
ジョナ

説明を追加しました。
デニス

4

05AB1E、12バイト

0¸sbvDO>yǝ}O

オンラインでお試しください!説明:としては、他の回答が指摘、バイナリストリングのサブシーケンスの数a..y01端は、バイナリストリングの数と同じであることa..yに端番号ことながら、0バイナリのためのサブシーケンスの総数であります文字列a..y(それぞれ0接尾辞が付きます)と0それ自体に1つ。他の回答とは異なり、空のサブシーケンスは含めません。これにより、初期状態を構成するバイトが保存されます。

0¸s             Push [0] under the input
   b            Convert the input to binary
    v     }     Loop over the digits
     D          Duplicate the array
      O         Take the sum
       >        Increment
        yǝ      Replace the index corresponding to the binary digit
           O    Take the sum of the final array

1

Java 8、97バイト

n->f(n,1,1)long f(long n,long a,long b){return n>0?f(n/2,a+Math.floorMod(~n,2)*b,n%2*a+b):a+b-2;}

@xnorのPython 2回答のポート。これは、@ NofPのPython 3回答の改善です。

ここで試してみてください。


-tagが存在するのは良いことかもしれません。最初にすべてのサブシーケンスをブルートフォースするために次のものがあったからです

import java.util.*;n->p(n.toString(n,2)).size()-1;Set p(String s){Set r=new HashSet();r.add("");if(s.isEmpty())return r;Set q=p(s.substring(1));r.addAll(q);for(Object o:q)r.add(""+s.charAt(0)+o);return r;}

ここで試してみてください。

これも機能しましたが、最後の3つのテストケースでは時間がかかりすぎました。言うまでもなく、もっと長い(208 204バイト)。


1

6502マシンコード(C64)、321バイト

00 C0 20 FD AE A2 00 9D 4F C1 E8 20 73 00 90 F7 9D 4F C1 A0 FF C8 B9 4F C1 D0
FA A2 15 CA 88 30 0A B9 4F C1 29 0F 9D 4F C1 10 F2 A9 00 9D 4F C1 CA 10 F8 A9
00 A0 07 99 64 C1 88 10 FA A0 40 A2 6C 18 BD E4 C0 90 02 09 10 4A 9D E4 C0 E8
10 F2 A2 07 7E 64 C1 CA 10 FA 88 F0 13 A2 13 BD 50 C1 C9 08 30 05 E9 03 9D 50
C1 CA 10 F1 30 D1 A2 0F A9 00 9D 3F C1 CA D0 FA A9 01 8D 3F C1 8D 47 C1 A2 08
CA BD 64 C1 F0 FA A0 09 1E 64 C1 88 90 FA B0 0A CA 30 28 A0 08 1E 64 C1 90 04
A9 47 B0 02 A9 4F 8D AF C0 86 FE A2 F8 18 BD 47 C0 7D 4F C0 9D 47 C0 E8 D0 F4
A6 FE 88 D0 DC F0 D5 A2 F8 BD 47 C0 7D 4F C0 9D 6C C0 E8 D0 F4 AD 64 C1 E9 01
8D 64 C1 A2 F9 BD 6C C0 E9 00 9D 6C C0 E8 D0 F5 A0 15 A9 00 99 4E C1 88 D0 FA
A0 40 A2 13 BD 50 C1 C9 05 30 05 69 02 9D 50 C1 CA 10 F1 0E 64 C1 A2 F9 3E 6C
C0 E8 D0 FA A2 13 BD 50 C1 2A C9 10 29 0F 9D 50 C1 CA 10 F2 88 D0 D1 E0 14 F0
06 E8 BD 4F C1 F0 F6 09 30 99 4F C1 C8 E8 E0 15 F0 05 BD 4F C1 90 F0 A9 00 99
4F C1 A9 4F A0 C1 4C 1E AB

オンラインデモ

エラーチェック付きオンラインデモ(346バイト)

使用法: sys49152,[n]などsys49152,911188917558917

時間制限とテストケースには、64ビット数で計算するソリューションが必要なので、C64が「最新のマシン」として適格であることを証明する時間です;)

もちろん、これにはかなりのコードが必要です。OSは16ビット以上の整数には何も提供しません。ここのラメな部分:それは、NofPのアルゴリズム応答の(もう少し修正された)さらに別の実装です。xnorの改良版。アイデアをありがとう;)


説明

以下は、アルゴリズムを実行する関連部分のコメント付き逆アセンブリリストです。

.C:c06c  A2 0F       LDX #$0F           ; 15 bytes to clear
.C:c06e  A9 00       LDA #$00
.C:c070   .clearloop:
.C:c070  9D 3F C1    STA .num_a,X
.C:c073  CA          DEX
.C:c074  D0 FA       BNE .clearloop
.C:c076  A9 01       LDA #$01           ; initialize num_a and num_b
.C:c078  8D 3F C1    STA .num_a         ; to 1
.C:c07b  8D 47 C1    STA .num_b
.C:c07e  A2 08       LDX #$08           ; 8 bytes of input to check,
.C:c080   .findmsb:                     ; start at most significant
.C:c080  CA          DEX
.C:c081  BD 64 C1    LDA .nc_num,X
.C:c084  F0 FA       BEQ .findmsb       ; repeat until non-0 byte found
.C:c086  A0 09       LDY #$09           ; 8 bits to check (+1 for pre dec)
.C:c088   .findbit:
.C:c088  1E 64 C1    ASL .nc_num,X      ; shift left, highest bit to carry
.C:c08b  88          DEY
.C:c08c  90 FA       BCC .findbit       ; bit was zero -> repeat
.C:c08e  B0 0A       BCS .loopentry     ; jump into calculation loop
.C:c090   .mainloop:
.C:c090  CA          DEX                ; next byte
.C:c091  30 28       BMI .done          ; index -1? -> done calculating
.C:c093  A0 08       LDY #$08           ; 8 bits to check
.C:c095   .bitloop:
.C:c095  1E 64 C1    ASL .nc_num,X      ; shift left, highest bit to carry
.C:c098  90 04       BCC .tgt_b         ; if 0, store addition result in num_b
.C:c09a   .loopentry:
.C:c09a  A9 47       LDA #$47
.C:c09c  B0 02       BCS .tgt_a         ; ... else store in num_a ...
.C:c09e   .tgt_b:
.C:c09e  A9 4F       LDA #$4F
.C:c0a0   .tgt_a:
.C:c0a0  8D AF C0    STA $C0AF          ; ... using self-modification.
.C:c0a3  86 FE       STX $FE            ; save byte index
.C:c0a5  A2 F8       LDX #$F8           ; index for adding
.C:c0a7  18          CLC
.C:c0a8   .addloop:
.C:c0a8  BD 47 C0    LDA $C047,X        ; load byte from num_a
.C:c0ab  7D 4F C0    ADC $C04F,X        ; add byte from num_b
.C:c0ae  9D 47 C0    STA $C047,X        ; store to num_a or num_b
.C:c0b1  E8          INX                ; next index
.C:c0b2  D0 F4       BNE .addloop       ; done if index overflown
.C:c0b4  A6 FE       LDX $FE            ; restore byte index
.C:c0b6  88          DEY                ; decrement bit index
.C:c0b7  D0 DC       BNE .bitloop       ; bits left in current byte -> repeat
.C:c0b9  F0 D5       BEQ .mainloop      ; else repeat main loop
.C:c0bb   .done:
.C:c0bb  A2 F8       LDX #$F8           ; index for adding
.C:c0bd   .addloop2:
.C:c0bd  BD 47 C0    LDA $C047,X        ; load byte from num_a
.C:c0c0  7D 4F C0    ADC $C04F,X        ; add byte from num_b
.C:c0c3  9D 6C C0    STA $C06C,X        ; store to nc_num (result)
.C:c0c6  E8          INX                ; next index
.C:c0c7  D0 F4       BNE .addloop2      ; done if index overflown
.C:c0c9  AD 64 C1    LDA .nc_num        ; load least significant result byte
.C:c0cc  E9 01       SBC #$01           ; subtract 2 (1 + negated carry)
.C:c0ce  8D 64 C1    STA .nc_num        ; store least significant result byte
.C:c0d1  A2 F9       LDX #$F9           ; index for subtract
.C:c0d3   .subloop:
.C:c0d3  BD 6C C0    LDA $C06C,X        ; subtract 0 from all other bytes
.C:c0d6  E9 00       SBC #$00           ; for handling carry if necessary
.C:c0d8  9D 6C C0    STA $C06C,X
.C:c0db  E8          INX
.C:c0dc  D0 F5       BNE .subloop       

残りは入出力であり、ダブルダブルアルゴリズムを使用して文字列と64ビット符号なし整数(リトルエンディアン)の間で変換されます。興味のある方のために、ここにエラーチェック付きのバージョンのアセンブリソース全体を示します。「ゴルフ」バージョンはブランチ「ゴルフ」にあります。

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