Sottostringhe binarie


17

Ispirato al quarto problema di BMO2 2009 .

Dato un intero positivo n come input o un parametro, restituisce il numero di numeri interi positivi le cui rappresentazioni binarie si presentano come blocchi nell'espansione binaria di n .

Ad esempio, 13 -> 6 perché 13 in binario è 1101 e ha sottostringhe 1101, 110, 101, 11, 10, 1. Non contiamo i numeri binari che iniziano con zero e non contiamo zero stesso.

Casi test

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

Puoi prendere n come uno dei seguenti:

  • un numero intero
  • un elenco di valori di verità / falsità per la rappresentazione binaria
  • una stringa per la rappresentazione binaria
  • una stringa di base 10 (anche se non sono sicuro del motivo per cui qualcuno dovrebbe farlo)

Rendi il tuo codice il più breve possibile.


3
Puoi confermare 63-> 5 e non 6? Bin (63) = 111111 -> sei distinte sottostringhe diverse da zero
dylnan il

Relazionato. (Utilizza sottosequenze invece di sottostringhe e non ignora gli zeri iniziali.)
Martin Ender

1
@dylnan Typo. Fisso.
0WJYxL9FMN il

@MartinEnder È abbastanza diverso per rimanere su questo sito o devo cancellarlo come duplicato? Penso che sia sufficientemente diverso, ma sai molto meglio di me.
0WJYxL9FMN il

@ J843136028 La differenza più grande nel non farne un duplicato è la restrizione temporale sull'altra sfida. Stai bene. (Ho appena pubblicato il link, in modo che le sfide si presentino reciprocamente nella barra laterale.)
Martin Ender,

Risposte:


7

Python 3, 54 50 byte

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

Grazie a Rod e Jonathan Allan per aver salvato quattro byte.


Puoi spostare la +1gamma dabin(i)
Rod

1
In effetti da quando abbiamo sempre contare nse stessa e devono sempre di escludere 0dal nostro conteggio possiamo invece sempre escludere ne sempre contare 0(Bin (n) inizia '0b...'), quindi possiamo rimuovere la 1,e +1del tutto e il congedo bin(i), come è quello di salvare quattro byte Provalo in rete!
Jonathan Allan il

5

Gelatina , 4 byte

ẆQSḢ

Provalo online!

Prende input come elenco di 0s e 1s.

Provalo online con i numeri!

Spiegazione:

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

Prova funziona:

Questo programma ottiene un numero di input, N . La prima cosa che fa questo prodotto è, ovviamente, prendere le sottostringhe di N 2 ( N nella base 2 ). Ciò include sottostringhe duplicate che iniziano con 0 o 1 .

Successivamente, prendiamo semplicemente le sottostringhe univoche mantenendo solo la prima occorrenza di ciascun valore nell'elenco delle sottostringhe.

Quindi, questo programma somma insieme i primi elementi degli elenchi, quindi i secondi elementi, quindi il terzo, il quarto, ecc. E se uno degli elenchi non ha tale elemento 0viene assunto. Ciò che la sfida si pone è efficace : quante sottostringhe univoche iniziano con 1 ha questo numero nella sua forma binaria? . Poiché ogni primo elemento da conteggiare è 1, possiamo semplicemente sommare invece di filtrare per sottostringhe appropriate.

Ora, il primo elemento dell'elenco risultante della sommatoria sopra descritto contiene il conteggio dei primi bit delle sottostringhe, quindi semplicemente pop e infine lo restituiamo.


4

Ottava , 62 61 byte

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

Provalo online!

Spiegazione

Per l'input n, il codice verifica tutti i numeri da 1a nper vedere se la loro rappresentazione binaria è una sottostringa della rappresentazione binaria dell'input.

@(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 byte

Accetta l'input come stringa binaria.
L'intestazione converte l'input intero in binario per facilitare i test.

ŒCÙĀO

Provalo online!

Spiegazione

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

Awwhh ... Pensavo che il mio filtro fosse intelligente. bŒʒć}Ùgma no, va meglio.
Magic Octopus Urn


2

PowerShell , 103 92 82 byte

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

Provalo online!

Accetta input come una matrice di 1e 0(verità e falsità in PowerShell). Passa attraverso $s(ovvero quanti elementi nella matrice di input). All'interno del loop, eseguiamo il loop dal numero corrente (salvato come $i) fino a $s.count. Ogni ciclo interno, abbiamo -joinl'array slice in una stringa. Quindi sortcon la -ubandiera della nicchia (che è più corta che selectcon la -ubandiera della nicchia e non ci importa se sono ordinati o meno), prendiamo quelli che non iniziano con 0e prendiamo il totale .count. Rimane in cantiere e l'output è implicito.


2

JavaScript (ES6), 55 byte

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

Accetta l'input come stringa binaria.

Ecco un triste tentativo di farlo con numeri e funzioni ricorsive:

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)

Vecchio approccio, 74 byte

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

Accetta anche l'input come stringa binaria.


1

Python 2 ,  118  81 byte

Grazie a @Rod per aver salvato 37 byte!

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

Accetta l'input come stringa binaria.

Provalo online!

Python 2 , 81 byte

Grazie a @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]})

Accetta l'input come stringa binaria.

Provalo online!


Puoi accettare una stringa binaria come input, puoi anche sostituirla set(...)con {...}e xrangeconrange
Rod

Puoi anche spostare il +1da l'intervallo al slice e passare s.startswitha in int(s,2) questo modo
Rod

1
Se si desidera mantenere il vostro vecchio approccio, è anche possibile utilizzare questo per lo stesso numero di byte
Rod

1

Gelatina , 5 byte

ẆḄQṠS

Provalo online!

Accetta input come un elenco di 1 e 0 secondi. Il piè di pagina nel collegamento applica la funzione a ciascuno degli esempi nel post.

Jonathan Allan ha sottolineato che si ẆḄQTLtratta di un'alternativa a 5 byte che utilizza l' Tatomo che trova gli indici di tutti gli elementi di verità.

Spiegazione

Prendi bin (13) = 1101 come esempio. L'input è[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

Ha preso l'idea "verità" (accedi in questo caso) dalla risposta 05AB1E


1
Potresti effettivamente usare l'atomo di Truthy Indexes di Jelly T, conẆḄQTL
Jonathan Allan il

1

R , 88 77 byte

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

Provalo online!

Accetta l'input come stringa binaria.

usando mapply, genera un array di tutte le sottostringhe dell'input. strtoili converte come 2numeri interi di base e prendo la somma della conversione logica ( !!) delle voci nel risultato.


1

Retina , 37 29 byte

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

Provalo online! Ho dovuto provare il wmodificatore di Retina 1.0 . Modifica: salvato 8 byte grazie a @MartinEnder. Spiegazione:

.+
*

Converti da decimale a unario.

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

Converti da unario a binario, usando #per0 e _per 1.

wp`_.*

Genera sottostringhe che iniziano con 1, voglio dire, _. Il wmodificatore quindi abbina tutte le sottostringhe, non solo la più lunga ad ogni inizio _, mentre il pmodificatore deduplica le corrispondenze. Infine, poiché questa è l'ultima fase, il conteggio delle partite viene restituito implicitamente.


È possibile eseguire il roll degli ultimi tre stadi in uno utilizzando il modificatore q(o p) in aggiunta a w. Inoltre, non è necessario specificare Cesplicitamente, poiché è il tipo di fase predefinito se è rimasta una sola fonte.
Martin Ender,

@MartinEnder Grazie, sono ancora abituato a Messere il tipo di scena predefinito!
Neil,

Beh, Cun po 'è quello che Mera. :)
Martin Ender il

So perché è l'impostazione predefinita, si sta solo abituando al passaggio.
Neil,

1

Pyth , 8 byte

l #{vM.:

Provalo qui!

Accetta l'input come stringa binaria.

.:genera tutte le sottostringhe, vMvaluta ciascuna (ovvero converte ciascuna da binario), {deduplica, <space>#filtra per identità e ne lottiene la lunghezza.





0

Java, 232 byte

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

Dove n è l'input, b è la rappresentazione binaria e l è un elenco di tutte le sottostringhe. La prima volta che pubblichi qui, sicuramente bisogno di migliorare e sentiti libero di segnalare eventuali errori! Leggermente modificato per leggibilità.


Benvenuti in PPCG! Per quanto riguarda l'inserimento di nuove righe per la leggibilità, di solito si preferisce avere una versione di punteggio che abbia esattamente la quantità di byte come scritto nell'intestazione, e quindi una versione aggiuntiva non golfizzata o meno giocata per la leggibilità.
Laikoni,

@Laikoni Grazie per l'heads-up! Terrò a mente per i post futuri!
Nihilish,

String b=...,te int i=...,j,kper salvare i caratteri per le dichiarazioni ripetute dello stesso tipo. Inoltre il tuo codice non si qualificherebbe come una voce perché è uno snippet, né un programma completo né un frammento funzionale, devi scrivere una funzione o racchiudere il tuo codice nel modulo lambda
Unihedron

0

Attache , 35 byte

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

Provalo online!

Equivalentemente:

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

Spiegazione

Spiegherò la seconda versione, poiché è più facile da seguire (essendo esplicito):

{#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 byte

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

Input come stringa binaria.
Deve esserci un modo più breve ..>.>

Spiegazione:

Provalo online.

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 byte

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

Questa è una funzione ricorsiva. Usiamo a std::setper contare i valori, ignorando i duplicati. Le due chiamate ricorsive mascherano i bit a sinistra ( f(n&i)) e a destra (f(n/2) ), producendo infine tutte le sottostringhe come numeri interi.

Si noti che se si desidera richiamarlo nuovamente, è snecessario cancellarlo tra le chiamate.

Programma di test

#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;
    }
}

risultati

./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


0

J , 15 byte

#.\\.#@=@-.&,0:

L'input è un elenco binario. Provalo online!

#.\\.               Convert every substring to decimal
         -.&,0:     Flatten and remove the 0s.        
     #@=            How many unique elements?

0

Perl 6 , 34 byte

{+unique ~«(.base(2)~~m:ex/1.*/)}

Provalo

Allargato:

{
  +                                # turn into Numeric (number of elements)
   unique                          # use only the unique ones
          ~«(                      # turn into strings
             .base(2)              # the input in base 2
                     ~~
                       m:ex/1.*/   # :exhaustive match substrings
                                )
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.