バイナリ部分文字列の合計


16

この課題は簡単で、10進数が与えられ、2進数に変換され、元の数字よりも短い2進数の部分文字列の合計を計算します。以下に例を示します。

Input:
  11
Binary:
  11 -> 1011
Substrings:
  101 = 5
  011 = 3
  10  = 2
  01  = 1
  11  = 3
  1   = 1
  0   = 0
  1   = 1
  1   = 1
Sum:
  5+3+2+1+3+1+0+1+1=17
Output:
  17

上記のように、プログラムは入力として単一の10進整数を取り、バイナリサブストリングの合計を出力する必要があります。入力のバイナリ表現は常に2桁以上であり、入力ではプログラムの実行中にエラーが発生しないと想定できます。

これは、バイト単位の最短コードが勝ちです!

テストケース:

2  => 1
3  => 2
4  => 3
5  => 5
6  => 7
7  => 9
8  => 7
9  => 10
10 => 14
11 => 17

4
奇妙なことに、完全な長さの部分文字列を除外することは、非常に大きな課題です。
ピーターテイラー

回答:


12

ゼリー、10 7バイト

BṡRḄFS_

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

使い方

BṡRḄFS_  Main link. Input: n

B        Convert n to base 2.
  R      Yield [1, ..., n].
 ṡ       Get all overlapping slices of lengths 1 to n.
         This yields empty arrays if the slice size is longer than the binary list.
   Ḅ     Convert each binary list to integer.
    F    Flatten the resulting, nested list.
     S   Compute the sum of the result.
      _  Subtract n from the sum.

そのプログラムでどのエンコードが1バイト/文字を提供しますか?
トビー・スペイト

1
@TobySpeight Jellyは独自のコードページを
spaghetto



5

Python 3、111文字

N=bin(int(input()))[2:];L=len(N);r=range;print(sum(int(n,2)for n in[N[j:j+i]for i in r(1,L)for j in r(L-i+1)]))

編集:説明:

N=bin(int(input()))[2:]

入力文字列をintに変換し、次にintをバイナリ文字列に変換して、binメソッドが次の形式の文字列を返すため、最初の2文字を削除します0b...

バイナリ文字列のすべての部分文字列を取得し、それらを使用して10進数に変換し、それらをint(n, 2)合計します。

[N[j:j+i]for i in r(1,L)for j in r(L-i+1)]

すべての部分文字列のリストです。ゴルフされていないバージョン:

def all_substrings(N):
    result = []
    for i in range(1, len(N)):
        for j in range(len(N) - i + 1):
            result.append(N[j:j+i])
    return result

お役に立てれば。


4

CJam(22バイト)

これは、現在のCJamの最良の回答よりも1バイト長くなりますが、おそらくこのアプローチは他のいくつかの言語に非常に有益に適応できるでしょう。

3,ri_2b_,,:).*\+fbW%:-

オンラインデモ

分析

質問があったと仮定します

2進数の部分文字列の合計を計算する

ビットなし

長さが元の数より短い

次に、総重み1*(2^B-1)Bビット数が最も大きいビットが発生することを示すのはそれほど難しくありません。2番目に重要なビットは、総重量で発生し2*(2^(B-1)-1)ます。合計重みで発生するB番目の最上位ビットまでB*(2^1-1)

元の数の減算を考慮に入れるxと、合計になります

sum_i (x & 2^i) * 2^i * 2*(B-i)  -  sum_i (x & 2^i) * (B-i)  -  x

解剖

3,        e# Put [0 1 2] on the stack - we'll need it later
ri_       e# Get the input x and copy it
2b        e# Convert the copy to base 2
_,,:).*   e# Pointwise multiply by 1 plus the index
\+        e# Append x to the resulting array, giving A
fb        e# Map a base conversion
W%:-      e# Reverse and fold a subtraction

2を基数に変換すると、主合計の最初の部分plusが得られxます。基数1に2番目の部分にプラスを付けxます。そして、ベース0にちょうどを与えるxので、ベース2からベース1 xを引くとsがキャンセルされ、ベース0を引くと望ましい結果が得られます。


3

JavaScript(ES6)、78バイト

n=>[...n.toString(2)].map(c=>[...s+=c].map((_,i)=>n-='0b'+s.slice(i)),s='')|-n

外側mapは、nのバイナリ表現の先頭部分文字列を構築します。内側のサブストリングは、先頭のサブストリングの末尾のサブストリングを抽出するため、元のバイナリ表現を含むすべての可能なサブストリングをカバーします。

各部分文字列は、バイナリから10進数に変換され、元の入力から減算されます。これは、これらを一緒に加算して元の入力を減算するよりもわずかに短いためです。


2

Mathematica、73 70バイト

Tr[FromDigits[#,2]&/@StringCases[#~IntegerString~2,__,Overlaps->All]]&

関数。整数->整数


1
哀れな数学には、サブリストを扱うための優れたツールがありません。
シモンズ

1

網膜、64

.*
$*
+`(1+)\1
$1a
a1
1
r&!M`.*
&!M`.*
^.*

+`1(a*)\b
a$.1$*1;
;

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

ステージの説明ごとの高レベルステージ:10進数を単項に変換、単項をバイナリに変換、プレフィックスを取得、プレフィックスのサフィックスを取得、元の番号をダンプ、バイナリを単項に変換、カウントを返します。ゴルフが終わったら、より詳細な説明を書きます。これらのステージの多くは疑わしいようです...


1

C、71バイト

f(n){int a=0,m=0,i;for(;++m<n;m+=m)for(i=n;i+i>m;i/=2)a+=i&m;return a;}

アキュムレータaとマスクを維持しmます。マスクは1から始まり、外側のループを回るたびに1ビット長くなります。内側のループでiは、入力のコピーがマスクよりも短くなるまで連続して右にシフトされ、そのたびにマスクされた値が累積されます。

テストプログラム

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
    while (*++argv) {
        int n = atoi(*argv);
        printf("%d -> %d\n", n, f(n));
    }
    return 0;
}

テスト出力

./73793 $(seq 0 11)
0 -> 0
1 -> 0
2 -> 1
3 -> 2
4 -> 3
5 -> 5
6 -> 7
7 -> 9
8 -> 7
9 -> 10
10 -> 14
11 -> 17

1

C#、148バイト

int x(int i){int s,r=0,j=i,p=System.Convert.ToString(i,2).Length+1,k;for(;--p>-1;){k=j;s=-1;for(;++s<p;)r+=(k>>=1);j=(i&((1<<p-1)-1))<<1;}return r;}

または、「静的System.Mathを使用して」インポートを追加する場合; その後、138

int x(int i){int s,r=0,j=i,p=(int)Round(Log(i,2)+1.49,0),k;for(;--p>-1;){k=j;s=-1;for(;++s<p;)r+=(k>>=1);j=(i&((1<<p-1)-1))<<1;}return r;}

C#のようなOOP言語はそのようなレースには勝てませんが、とにかく試してみたかったです。これは、より美しいバージョン+テスターです。

class Program
{
    // Tester: 50 bytes
    static void Main(string[] args)
    {
        int i=2;
        do System.Console.WriteLine($"{i} -> {x(i++)}"); while (i < 12);
        System.Console.Read();
    }
    // Function: 65 bytes (size according to ILDASM.exe)
    static int x(int iOrg)
    {
        int pos, shift, retVal=0, iPrev=iOrg, iTemp;
        pos = System.Convert.ToString(iOrg, 2).Length;
        do {
            iTemp = iPrev; shift = 0;
            do retVal += (iTemp >>= 1); while (++shift < pos);
            iPrev = (iOrg & ((1 << pos - 1) - 1)) << 1;
        } while (--pos > -1); 
        return retVal;
    }
}

ネストされたdo-whileは、shift + 1がposよりも小さい限り、iTempの右シフト値(割り当て後)を追加します。次の行は、iPrevの次のシフト値を計算します

x1 = 1 << p -1; // 1 << 4 -1 = 8 [1000]
x2 = x1 - 1;    // 8 -  1 = 7    [0111]
x3 = i & x2;    // 1011 & 0111 = 0011 
x4 = x3 << 1;   // 0011 << 1 = 00110
i2 = x4;

x1およびx2はマスクを計算し、x3はマスクを適用してから左シフトします。これは、最後の桁が常にドロップされるためです。11の場合、次のようになります。

START -> _1011[11]
101
10
1   -->  X0110[6], r=0+5+2+1=8
 011
 01
 0  -->  XX110[6], r=8+4=12
  11
  1 -->  XXX10[2], r=12+4=16
   1 ->  XXXX0[X], r=16+1=17

Cのほとんどの回答はC#でもシームレスに機能します(@ Tony-Speightは問題なく機能しました)が、その目的に反するでしょう。また、コメントを(Boldヘッダーを除き)見たのは自分が終わるまでだったので、「Cのように」それを行う危険はありませんでした。
-DW.com

0

PowerShell v2 +、138バイト

param($a)$a=[convert]::ToString($a,2);(($b=$a.length-1)..1|%{$l=$_;0..($b-$l+1)|%{[convert]::ToInt32($a.substring($_,$l),2)}})-join'+'|iex

やばい。バイナリへの/からの変換は高価です。

入力を受け取り$a.NET呼び出し[convert]::ToString($a,2)を使用してそれをバイナリ表現に変換します。そこから、2つのループを実行します。最初のループは、文字列の末尾から逆方向にカウントダウン1し、2番目のループは、上からカウントアップし0ます。(1つ目は、部分文字列を取り出す長さで、2つ目は、文字列内のどこで部分文字列を開始するかのインデックスです。)ヘルパーを設定して、$lそれを内部ループに渡します。

内側のループ内で、別の.NET呼び出し[convert]::ToInt32()を使用して、適切な.substring()fromから2整数に変換します。これらはそれぞれパイプラインに残されます。私たちは、括弧でそのすべてをカプセル化()し、-join一緒にそれら+その後にそのオフを投げる、iex(略しInvoke-Expressionと同様のっぽいのeval)。

私が考えて、これは技術的に正しく、.NETコールを呼び出すためにV2以降が必要です。

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