Двійкові підрядки


17

Натхненний четвертою проблемою з BMO2 2009 .

Давши додатне ціле число n як вхід чи параметр, поверніть кількість натуральних чисел, бінарні подання яких є блоками у бінарному розширенні n .

Наприклад, 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

Ви можете взяти n як будь-яке з наступного:

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

Зробіть свій код якомога коротшим.


3
Чи можете ви підтвердити 63-> 5, а не 6? Bin (63) = 111111 -> шість різних ненульових
підрядів

Пов'язані. (Використовує підзакони замість підрядків і не ігнорує провідні нулі.)
Мартін Ендер

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)
Rod

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

Awwhh ... Я думав, мій фільтр розумний. bŒʒć}Ùgале ні, так краще.
Чарівний восьминіг Урна


2

PowerShell , 103 92 82 байт

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

Спробуйте в Інтернеті!

Приймає дані як масив 1та 0(truthy та falsey в PowerShell). Проведіть цикл $s(тобто скільки елементів у вхідному масиві). Всередині циклу ми робимо цикл від поточного числа (збереженого як $i) до $s.count. Кожну внутрішню петлю, ми -joinвирізаємо масив в рядок. Потім ми sortз -uNique прапор (який коротше , ніж 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 байт

Дякуємо @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})

Приймає вхід як двійковий рядок.

Спробуйте в Інтернеті!

Пітон 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атом, який знаходить показники всіх елементарних елементів.

Пояснення

Візьміть бін (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

Взяв ідею "truthify" (підпишіться в цьому випадку) з відповіді 05AB1E


1
Ви насправді можете використовувати атом індексів Truthy Jelly 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`_.*

Спробуйте в Інтернеті! Мені просто довелося випробувати wмодифікатор Retina 1.0 . Редагувати: Збережено 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

Мова Вольфрама (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 Дякую за голову! Майте на увазі для майбутніх постів!
Нігіліш

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

0

Attache , 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();}

Введіть як двійковий-String.
Повинен бути коротший шлях ..>.>

Пояснення:

Спробуйте в Інтернеті.

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

Це рекурсивна функція. Ми використовуємо a 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.