バイナリ部分文字列


17

BMO2 2009の 4番目の問題に触発されました。

入力またはパラメータとして正の整数nを指定すると、nのバイナリ展開でブロックとしてバイナリ表現が発生する正の整数の数を返します。

たとえば、13-> 6は、バイナリの13が1101であり、サブストリングがあるため1101, 110, 101, 11, 10, 1です。ゼロで始まる2進数はカウントせず、ゼロ自体もカウントしません。

テストケース

13 -> 6
2008 -> 39
63 -> 6
65 -> 7
850 -> 24
459 -> 23
716 -> 22
425 -> 20
327 -> 16

あなたにはかかりますnは、次のいずれかのよう:

  • 整数
  • バイナリ表現の真偽値のリスト
  • バイナリ表現の文字列
  • 10を基数とする文字列(なぜこれを行うのかはわかりませんが)

コードをできるだけ短くしてください。


3
6ではなく63-> 5を確認できますか?ビン(63)= 111111 - > 6つの異なる非ゼロのストリング
dylnan

関連。(サブストリングの代わりにサブシーケンスを使用し、先行ゼロを無視しません。)
マーティン・エンダー

1
@dylnan Typo。修繕。
0WJYxW9FMN

@MartinEnderこれは、このサイトにとどまるのに十分な違いがありますか、それとも重複として削除しますか?私はそれは十分に異なっていると思いますが、あなたは私よりもずっとよく知っています。
0WJYxW9FMN

@ J843136028重複させないことの大きな違いは、他のチャレンジの時間制限です。大丈夫だよ。(リンクを投稿するだけで、チャレンジはお互いのサイドバーに表示されます。)
マーティン・エンダー

回答:


7

Pythonの3、54の 50バイト

lambda n:sum(bin(i)[2:]in bin(n)for i in range(n))

4バイトを節約してくれたRodとJonathan Allanに感謝します。


あなたが移動できる+1範囲からbin(i)
ロッド

1
実際、私たちは以来、常にカウントn自体をしてしている、常に排除し0、我々は代わりに常に除外することができ、当社のカウントからn、常にカウント0(ビン(n)が起動する'0b...'ので、我々は削除することができ、)1,+1完全に及び休業bin(i)4つのバイトを保存することであるとして、オンラインでそれを試してみてください!
ジョナサンアラン

5

ゼリー、4バイト

ẆQSḢ

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

入力を0sおよび1sのリストとして受け取ります。

数字でオンラインで試してみてください!

説明:

ẆQSḢ Argument: B = list of bits, e.g. [1, 1, 0, 1]
Ẇ    Get B's non-empty sublists (i.e. [[1], [1], [0], [1], [1, 1], [1, 0], [0, 1], [1, 1, 0], [1, 0, 1], [1, 1, 0, 1]])
 Q   Keep first occurrences (i.e. [[1], [0], [1, 1], [1, 0], [0, 1], [1, 1, 0], [1, 0, 1], [1, 1, 0, 1]])
  S  Reduce by vectorized addition (i.e. [6, 4, 1, 1])
   Ḣ Pop first element (i.e. 6)

それが機能する証拠:

このプログラムは、入力番号Nを取得します。この製品が最初に行うことは、もちろん、N 2の部分文字列(基数2のN)を取得することです。これには、0または1で始まる重複部分文字列が含まれます。

その後、単純にサブストリングリスト内の各値の最初の出現のみを保持することにより、一意のサブストリングを取得します。

次に、このプログラムは、リストの最初の要素、次に2番目の要素、3番目、4番目などを合計し、リストの1つにそのような要素0がない場合を想定します。課題が効果的に求めるのは1から始まる一意の部分文字列がバイナリ形式でいくつあるかということです。。カウントされる最初の要素はすべてである1ため、適切なサブストリングをフィルタリングする代わりに単純に合計することができます。

ここで、上記の合計の結果リストの最初の要素には、部分文字列の最初のビットのカウントが保持されるため、単純にポップして最終的にそれを返します。


4

オクターブ62 61バイト

@(n)sum(arrayfun(@(t)any(strfind((g=@dec2bin)(n),g(t))),1:n))

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

説明

input nでは、コードはから1までのすべての数値をテストnして、それらのバイナリ表現が入力のバイナリ表現の部分文字列であるかどうかを確認します。

@(n)                                                          % Anonymous function of n
        arrayfun(                                      ,1:n)  % Map over range 1:n
                 @(t)                                         % Anonymous function of t
                         strfind(               ,    )        % Indices of ...
                                                 g(t)         % t as binary string ...
                                 (g=@dec2bin)(n)              % within n as binary string
                     any(                             )       % True if contains nonzero
    sum(                                                    ) % Sum of array

3

05AB1E、5バイト

入力をバイナリ文字列として受け取ります。
テストを容易にするために、ヘッダーは整数入力をバイナリに変換します。

ŒCÙĀO

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

説明

Œ        # push all substrings of input
 C       # convert to base-10 int
  Ù      # remove duplicates
   Ā     # truthify (convert non-zero elements to 1)
    O    # sum

ああ...私のフィルターはスマートだと思った。bŒʒć}Ùgしかし、いや、それは良いです。
魔法のタコ


2

PowerShell103 92 82バイト

param($s)(($s|%{$i..$s.count|%{-join$s[$i..$_]};$i++}|sort -u)-notmatch'^0').count

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

1andの配列として入力を受け取ります0(PowerShellではtrueおよびfalsey)。ループします$s(つまり、入力配列の要素数)。ループ内で、現在の番号(として保存$i)からまでループし$s.countます。各内側のループは-join、配列を文字列にスライスします。私たちは、その後sort-u(より短いniqueフラグselect-unique旗、我々は、彼らが並べ替えられたりしていないかどうかを気にしない)、で始まらないものを取り0、全体を取ります.count。それはパイプラインに残り、出力は暗黙的です。


2

JavaScript(ES6)、55バイト

f=(s,q="0b"+s)=>q&&s.includes((q--).toString(2))+f(s,q)

入力をバイナリ文字列として受け取ります。

これは、数値と再帰関数を使用してそれを行う悲しい試みです。

f=(n,q=n)=>q&&(g=n=>n?n^q&(h=n=>n&&n|h(n>>1))(q)?g(n>>1):1:0)(n)+f(s,q-1)

古いアプローチ、74バイト

s=>(f=s=>+s?new Set([+s,...f(s.slice(1)),...f(s.slice(0,-1))]):[])(s).size

また、入力をバイナリ文字列として受け取ります。


1

パイソン2 118の  81バイト

37バイトを節約してくれた@Rodに感謝します!

lambda n:len({int(n[i:j+1],2)for i in range(len(n))for j in range(i,len(n))}-{0})

入力をバイナリ文字列として受け取ります。

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

Python 2、81バイト

@Rodに感謝します!

lambda n:len({n[i:j+1]for i in range(len(n))for j in range(i,len(n))if'1'==n[i]})

入力をバイナリ文字列として受け取ります。

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


あなたが入力としてバイナリ文字列を受け入れることができ、あなたも置き換えることができるset(...){...}してxrangerange
ロッド

また、移動することができ+1、スライスの範囲から、と切り替えるs.startswithためにint(s,2) 、次のように
ロッド

1
あなたは古いアプローチを維持したい場合は、使用することができ、これを同じバイト数のために
ロッド

1

ゼリー、5バイト

ẆḄQṠS

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

入力を1と0のリストとして受け取ります。リンクのフッターは、投稿内の各例に関数を適用します。

ジョナサン・アランẆḄQTLは、Tそれがすべての真実の要素のインデックスを見つけるアトムを使用する5バイトの代替であると指摘しました。

説明

例としてbin(13)= 1101を取り上げます。入力は[1,1,0,1]

ẆḄQṠS
Ẇ       All contiguous sublists -> 1,1,0,1,11,10,01,110,101,1101 (each is represented as a list)
 Ḅ      From binary to decimal. Vectorizes to each element of the above list -> 1,1,0,1,3,2,1,6,5,13
  Q     Unique elements
   Ṡ    Sign. Positive nums -> 1 , 0 -> 0.
    S   Sum

05AB1E回答から「truthify」(この場合はサイン)アイデアを取得しました


1
あなたは、実際に、ゼリーのTruthyインデックス原子を使用することができTて、ẆḄQTL
ジョナサン・アラン

1

R88 77バイト

function(x)sum(!!unique(strtoi(mapply(substring,x,n<-1:nchar(x),list(n)),2)))

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

入力をバイナリ文字列として受け取ります。

を使用mapplyすると、入力のすべての部分文字列の配列が生成されます。strtoiそれらを基本2整数として変換し!!、結果のエントリの論理変換()の合計を取得します。


1

網膜37 29バイト

.+
*
+`(_+)\1
$1#
#_
_
wp`_.*

オンラインでお試しください!Retina 1.0のw修飾子を試す必要がありました。編集:@MartinEnderのおかげで8バイト保存されました。説明:

.+
*

10進数から単項に変換します。

+`(_+)\1
$1#
#_
_

#for 0および_for 1 を使用して、単項からバイナリに変換します。

wp`_.*

始まる部分文字列を生成し1、私は、意味します_w修飾子は、すべてのサブストリング、それぞれの始動時だけではなく、最長のものと一致_しながら、p修飾重複排除試合。最後に、これが最終段階であるため、一致の数が暗黙的に返されます。


に加えてq(またはp)修飾子を使用すると、最後の3つのステージを1つにロールできますwC明示的に指定する必要もありません。ソースが1つしかない場合はデフォルトのステージタイプであるためです。
マーティンエンダー

@MartinEnderありがとう、私はまだMデフォルトのステージタイプであることに慣れています!
ニール

まあ、Cちょっと何かMに使用されます。:)
マーティンエンダー

なぜこれがデフォルトであるかは知っていますが、切り替えに慣れているだけです。
ニール

1

Pyth、8バイト

l #{vM.:

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

入力をバイナリ文字列として受け取ります。

.:、すべてのサブストリングを生成するvM(すなわち、それはバイナリからそれぞれの変換)、それぞれを評価{重複排除、<space>#アイデンティティによってフィルタおよびl長さを取得します。





0

Java、232バイト

String b=toBin(n);
l.add(b);
for(int i=1;i<b.length();i++){
for(int j=0;j<=b.length()-i;j++){
String t="";
if((""+b.charAt(j)).equals("0"))continue;
for(int k=0;k<i;k++){
t+=""+b.charAt(j+k);
}
if(!l.contains(t))l.add(t);
}
}
return l.size();

ここで、nは入力、bはバイナリ表現、lはすべての部分文字列のリストです。ここに初めて投稿し、間違いなく改善する必要があり、間違いを指摘してください!読みやすくするために少し編集しました。


PPCGへようこそ!読みやすくするために改行を挿入する場合、通常は、ヘッダーに書き込まれたバイト数を正確に記録する1つのスコアリングバージョンと、読みやすくするために追加のゴルフなしまたはゴルフの少ないバージョンを用意することをお勧めします。
ライコニ

@ライコニヘッズアップをありがとう!今後の投稿に留意してください!
ニヒリッシュ

String b=...,tそしてint i=...,j,k、同じ型の繰り返し宣言のために文字を保存します。また、コードはスニペットであり、完全なプログラムでも機能的なフラグメントでもないため、エントリとしては資格がありません。関数を記述するか、ラムダ形式でコードをラップする必要があります
Unihedron

0

アタッシュ、35バイト

`-&1@`#@Unique@(UnBin=>Subsets@Bin)

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

同等:

{#Unique[UnBin=>Subsets[Bin[_]]]-1}

説明

(明示的に)従う方が簡単なので、2番目のバージョンについて説明します。

{#Unique[UnBin=>Subsets[Bin[_]]]-1}
{                                 }   lambda: _ = first argument
                        Bin[_]        convert to binary
                Subsets[      ]       all subsets of input
         UnBin=>                      map UnBin over these subsets
  Unique[                      ]      remove all duplicates
 #                              -1    size - 1 (since subsets is improper)


0

Java 8、160 159 158バイト

import java.util.*;b->{Set s=new HashSet();for(int l=b.length(),i=0,j;i<l;i++)for(j=l-i;j>0;s.add(new Long(b.substring(i,i+j--))))s.add(0L);return~-s.size();}

バイナリ文字列として入力します。
もっと短い方法が必要です。..>。>

説明:

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

import java.util.*;          // Required import for Set and HashSet
b->{                         // Method with String as parameter and integer as return-type
  Set s=new HashSet();       //  Create a Set
  for(int l=b.length(),      //  Set `l` to the length of the binary-String
      i=0,j;i<l;i++)         //  Loop from 0 up to `l` (exclusive)
    for(j=l-i;j>0;           //   Inner loop from `l-i` down to `0` (exclusive)
      s.add(new Long(b.substring(i,i+j--))))
                             //    Add every substring converted to number to the Set
      s.add(0L);             //    Add 0 to the Set
  return~-s.size();}         //  Return the amount of items in the Set minus 1 (for the 0)

0

C ++、110バイト

#include<set>
std::set<int>s;int f(int n){for(int i=1;i<n;i+=i+1)f(n&i);return n?s.insert(n),f(n/2):s.size();}

これは再帰的な関数です。私たちはstd::setて、重複を無視して値をカウントします。2つの再帰呼び出しは、左(f(n&i))および右(f(n/2))からビットをマスクし、最終的にすべての部分文字列を整数として生成します。

再度呼び出したい場合は、 s呼び出し間でクリアする必要がある。

テストプログラム

#include <cstdlib>
#include <iostream>

int main(int, char **argv)
{
    while (*++argv) {
        auto const n = std::atoi(*argv);
        s={};
        std::cout << n << " -> " << f(n) << std::endl;
    }
}

結果

./153846 13 2008 63 65 850 459 716 425 327
13 -> 6
2008 -> 39
63 -> 6
65 -> 7
850 -> 24
459 -> 23
716 -> 22
425 -> 20
327 -> 16



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