Бинарные Подстроки


17

Вдохновлен четвертой проблемой от BMO2 2009 .

Учитывая положительный целое число п в качестве входных данных или параметра, возвращает количество положительных целых чисел, двоичное представление встречается в виде блоков в двоичном разложении п .

Например, 13 -> 6, потому что 13 в двоичном виде - это 1101, и у него есть подстроки 1101, 110, 101, 11, 10, 1. Мы не считаем двоичные числа, которые начинаются с нуля, и мы не учитываем сам ноль.

Тестовые случаи

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

Вы можете взять в п , как и любой из следующих условий :

  • целое число
  • список истинных / ложных значений для двоичного представления
  • строка для двоичного представления
  • базовая строка 10 (хотя я не уверен, почему кто-то сделал бы это)

Сделайте ваш код как можно короче.


3
Можете ли вы подтвердить 63-> 5, а не 6? Bin (63) = 111111 -> шесть различных ненулевых подстрок
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))

Спасибо Роду и Джонатану Аллану за сохранение четырех байтов.


Вы можете перемещать +1из диапазона вbin(i)
Род

1
Фактически, поскольку мы всегда считаем nсебя и должны всегда исключать 0из нашего счета, мы можем вместо этого всегда исключать nи всегда считать 0(bin (n) начинается '0b...'), поэтому мы можем полностью удалить 1,и +1оставить и оставить bin(i)как есть, чтобы сохранить четыре байта. Попробуйте онлайн!
Джонатан Аллан

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 ( N в базе 2 ). Это включает повторяющиеся подстроки, начинающиеся с 0 или 1 .

После этого мы просто берем уникальные подстроки, сохраняя только первое вхождение каждого значения в списке подстрок.

Затем эта программа суммирует первые элементы списков, затем вторые элементы, затем третий, четвертый и т. Д., И если один из списков не имеет такого элемента 0, предполагается. Что задача задает эффективно? Сколько уникальных подстрок, начинающихся с 1, имеет это число в двоичной форме? , Поскольку каждый первый элемент, который должен быть подсчитан, есть 1, мы можем просто суммировать вместо фильтрации соответствующие подстроки.

Теперь первый элемент результирующего списка суммирования, описанного выше, содержит количество первых битов подстрок, поэтому мы просто извлекаем и, наконец, возвращаем его.


4

Октава , 62 61 байт

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

Попробуйте онлайн!

объяснение

Для ввода 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

PowerShell , 103 92 82 байта

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

Попробуйте онлайн!

Принимает входные данные в виде массива 1и 0(правда и ложь в PowerShell). Циклы $s(то есть, сколько элементов во входном массиве). Внутри цикла мы выполняем цикл от текущего номера (сохраненного как $i) до $s.count. В каждом внутреннем цикле мы -joinсрезаем массив в строку. Затем мы sortс -uфлагом nique (который короче, чем selectс -uфлагом nique, и нам все равно, отсортированы они или нет), берем те, которые не начинаются 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

Python 2 ,  118  81 байт

Спасибо @Rod за сохранение 37 байт!

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(...)на {...}и xrangeсrange
Rod

Вы также можете переместить элемент +1из диапазона в срез и переключить s.startswithего int(s,2) следующим образом
Rod

1
Если вы хотите сохранить свой старый подход, вы также можете использовать его для того же количества байтов
Rod

1

Желе , 5 байт

ẆḄQṠS

Попробуйте онлайн!

Вводит в виде списка 1 и 0. Нижний колонтитул в ссылке применяет функцию к каждому из примеров в посте.

Джонатан Аллан указал, что ẆḄQTL это 5-байтовая альтернатива, которая использует Tатом, который находит индексы всех истинных элементов.

объяснение

В качестве примера возьмем 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


1
На самом деле вы можете использовать атом Jelly's Truthy Indexes T, сẆḄQTL
Джонатаном Алланом

1

R , 88 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.0w модификатор . Изменить: Сохранено 8 байт благодаря @MartinEnder. Объяснение:

.+
*

Преобразовать из десятичной в одинарную.

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

Преобразовать из унарной в двоичную, используя #для 0и_ для 1.

wp`_.*

Создайте подстроки, которые начинаются с 1, я имею в виду _. wМодификатор затем сопоставляет все подстроки, а не только самый длинный по одному на каждом запуске _, в то время как pмодификатора дедуплицирует матчей. Наконец, так как это последний этап, количество совпадений возвращается неявно.


Вы можете свернуть последние три этапа в один, используя модификатор q(или p) в дополнение к w. Вам также не нужно указывать Cявно, потому что это тип сцены по умолчанию, если остался только один источник.
Мартин Эндер

@MartinEnder Спасибо, я все еще привык Mбыть типом сцены по умолчанию!
Нил

Ну, Cвроде как Mраньше. :)
Мартин Эндер

Я знаю, почему это по умолчанию, просто привыкаю к ​​переключению.
Нил

1

Pyth , 8 байт

l #{vM.:

Попробуй это здесь!

Принимает ввод в виде двоичной строки.

.:генерирует все подстроки, vMоценивает каждую (то есть конвертирует каждую из двоичных), {дедуплицирует, <space>#фильтрует по тождественности и lполучает длину.


1

Wolfram Language (Mathematica) , 35 байт

Подсчет уникальных подпоследовательностей двоичного представления, которые начинаются с единицы, хотя я не уверен, что этот код даже нуждается в объяснении.

Union@Subsequences@#~Count~{1,___}&

Попробуйте онлайн!


Что делает ___?
FrownyFrog

Сопоставление с образцом, _ - это один элемент, __ - один или несколько, ___ - 0 или более.
Келли Лоудер



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! Что касается вставки новых строк для удобства чтения, обычно предпочтительнее иметь одну версию с оценкой, которая имеет ровно столько байтов, как написано в заголовке, а затем дополнительную версию без начинки или с меньшим количеством символов для удобства чтения.
Лайкони

@Laikoni Спасибо за внимание! Буду иметь в виду будущие посты!
Nihilish

String b=...,tи int i=...,j,kсохранить символы для повторных объявлений одного типа. Ваш код также не будет считаться записью, потому что это фрагмент, ни полная программа, ни функциональный фрагмент, вы должны написать либо функцию, либо
заключить

0

Атташе , 35 байт

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

Попробуйте онлайн!

Эквивалентное:

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

объяснение

Я объясню вторую версию, так как за ней легче следовать (будучи явным):

{#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для подсчета значений, игнорируя дубликаты. Два рекурсивных вызова маскируют биты слева ( 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



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.