Soma de Substrings Binárias

16

Esse desafio é simples, dado um número decimal, converta em binário e calcule a soma das sub-strings do número binário, cujo comprimento é menor que o número original. Aqui está um exemplo:

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

Seu programa deve usar um único número inteiro decimal como entrada e gerar a soma das sub-strings binárias, como visto acima. Você pode assumir que a entrada sempre terá mais de dois dígitos em sua representação binária e que a entrada não causará erros durante a execução do seu programa.

Este é o , o código mais curto em bytes vence!

Casos de teste:

2  => 1
3  => 2
4  => 3
5  => 5
6  => 7
7  => 9
8  => 7
9  => 10
10 => 14
11 => 17
GamrCorps
fonte
4
Curiosamente, a exclusão da substring completa é um desafio extra significativo.
Peter Taylor

Respostas:

12

Geléia, 10 7 bytes

BṡRḄFS_

Experimente online!

Como funciona

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.
Dennis
fonte
Qual codificação fornece 1 byte / char para esse programa?
Toby Speight 23/02
1
O @TobySpeight Jelly usa sua própria página de códigos.
a spaghetto
8

Pitão, 10

sPiR2.:.BQ

Experimente online ou execute o Test Suite

Explicação:

sPiR2.:.BQ    ##   Q = eval(input())
       .BQ    ##   get binary string of Q
     .:       ##   get all substrings of that
  iR2         ##   convert them all to base 10
sP            ##   sum all but the last element, which is the input number
FryAmTheEggman
fonte
6

CJam, 27 21 bytes

Grite ao Dennis por me ajudar a economizar 6 bytes!

q~:Q{)Q2bew2fb~}%1bQ-

Funciona apenas com a versão mais recente do CJam (disponível no TIO). Experimente online !

Versão antiga:

qi2b_,,0-\f{ew}{{2b}%}%e_:+

Experimente online .

GamrCorps
fonte
5

Python 3, 111 caracteres

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

EDIT : Explicação:

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

Converta a string de entrada em um int, depois o int em uma string binária e remova seus dois primeiros caracteres, pois o binmétodo retorna uma string no formato de0b...

Pegue todas as substrings da string binária, converta-as em decimal usando int(n, 2)e some-as.

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

é uma lista de todas as substrings. Versão não destruída:

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

Espero que isto ajude.

shooqie
fonte
4

CJam (22 bytes)

Esse é um byte a mais do que a melhor resposta atual do CJam, mas a abordagem provavelmente pode ser adaptada para alguns outros idiomas com bastante lucro.

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

Demonstração online

Análise

Suponha que a pergunta fosse

calcular a soma das sub-strings do número binário

sem a parte

cujo comprimento é menor que o número original

Então não é muito difícil mostrar que o bit mais significativo ocorre com o peso total, 1*(2^B-1)onde Bestá o número de bits; o segundo bit mais significativo ocorre com o peso total 2*(2^(B-1)-1); até o bit B-mais significativo, que ocorre com o peso total B*(2^1-1).

Considerando agora a subtração do número original x, terminamos com a soma

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

Dissecação

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

A conversão para a base 2 fornece a primeira parte da soma principal mais x; a base 1 fornece a segunda parte mais x; e a base 0 fornece apenas x, portanto, subtrair a base-1 da base-2 o xcancelamento e subtrair a base-0 fornece o resultado desejado.

Peter Taylor
fonte
3

JavaScript (ES6), 78 bytes

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

O externo mapconstrói substrings principais da nrepresentação binária de; o interno extrai substrings finais das principais substrings, cobrindo assim todas as possíveis substrings, incluindo a representação binária original.

Cada substring é convertida de binário de volta para decimal e subtraída da entrada original, pois é um pouco mais curta do que juntá-las e subtrair a entrada original.

Neil
fonte
2

Mathematica, 73 70 bytes

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

Função. Inteiro-> Inteiro

CalculatorFeline
fonte
1
Uma pena que o mathematica não tenha ótimas ferramentas para lidar com sublistas.
Um Simmons
1

Retina , 64

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

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

Experimente online!

Um estágio de alto nível por descrição do estágio: converte decimal em unário, unário em binário, obtenha prefixos, obtenha sufixos de prefixos, despeje o número original, converte binário em unário, conte retorno. Escreverei uma descrição mais detalhada assim que terminar o golfe, muitas dessas etapas parecem suspeitas ...

FryAmTheEggman
fonte
1

C, 71 bytes

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

Mantemos um acumulador ae uma máscara m. A máscara começa em 1 e fica um pouco mais cada vez ao redor do loop externo. No loop interno, uma cópia ida entrada é deslocada sucessivamente para a direita até ficar mais curta que a máscara, acumulando o valor mascarado a cada vez.

Programa de teste

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

Saída de teste

./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
Toby Speight
fonte
1

C #, 148 bytes

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

Ou, se eu adicionar Import "using System.Math estático;" então 138 com

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

Linguagens OOP como C # não vencerão essa corrida, mas eu queria tentar de qualquer maneira. Aqui está uma versão mais embelezada + testador.

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

O do-while aninhado adiciona o valor à direita do iTemp (depois de atribuí-lo) desde que o turno + 1 seja menor que o pos. A próxima linha calcula o próximo valor alterado do 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 e x2 calculam a máscara, x3 a aplica e depois a desloca para a esquerda, pois o último dígito é sempre descartado. Para o 11, fica assim:

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
DW.com
fonte
Eu sei, a maioria das respostas em C também funciona perfeitamente em C # (@ Tony-Speight funcionou sem problemas), mas eu desafiaria o objetivo. Além disso, eu não olhei para os comentários (bem, exceto os cabeçalhos em negrito) até terminar, então não havia perigo de fazê-lo "como C".
DW.com 24/02
0

PowerShell v2 +, 138 bytes

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

Ooof. Essa conversão de / para o binário é cara.

Recebe entrada $ae usa a chamada .NET[convert]::ToString($a,2) para transformá-la na representação binária. A partir daí, passamos por dois loops - o primeiro conta para trás do final da corda até 1e o segundo conta para cima 0. (O primeiro é o tempo de duração de uma substring e o segundo é o índice de onde na string iniciar a substring.) Definimos um auxiliar $lao longo do caminho para passar isso para o loop interno.

Dentro do loop interno, usamos outra chamada .NET[convert]::ToInt32() para converter o apropriado.substring() da base 2em um número inteiro. Cada um deles é deixado no pipeline. Encapsulamos tudo isso com parênteses ()e -joineles juntamente com a e +, em seguida, lançamos isso para iex(abreviação de Invoke-Expressione similar a eval).

Eu que isso tecnicamente exige que a v2 ou mais recente chame corretamente as chamadas do .NET.

AdmBorkBork
fonte