Suma de subcadenas binarias

16

Este desafío es simple, dado un número decimal, convertir a binario y calcular la suma de las subcadenas del número binario, cuya longitud es más corta que el número original. Aquí hay un ejemplo:

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

Su programa debe tomar un solo entero decimal como entrada y salida de la suma de las subcadenas binarias, como se ve arriba. Puede suponer que la entrada siempre tendrá más de dos dígitos en su representación binaria y que en la entrada no causará ningún error durante la ejecución de su programa.

Este es el , ¡el código más corto en bytes gana!

Casos de prueba:

2  => 1
3  => 2
4  => 3
5  => 5
6  => 7
7  => 9
8  => 7
9  => 10
10 => 14
11 => 17
GamrCorps
fuente
44
Curiosamente, la exclusión de la subcadena de longitud completa es un desafío adicional significativo.
Peter Taylor

Respuestas:

12

Jalea, 10 7 bytes

BṡRḄFS_

Pruébalo en línea!

Cómo 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
fuente
¿Qué codificación le da 1 byte / char para ese programa?
Toby Speight
1
@TobySpeight Jelly usa su propia página de códigos.
un espagueti
8

Pyth, 10

sPiR2.:.BQ

Pruébelo en línea o ejecute Test Suite

Explicación:

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
fuente
6

CJam, 27 21 bytes

¡Gracias a Dennis por ayudarme a ahorrar 6 bytes!

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

Funciona solo con la versión más nueva de CJam (disponible en TIO). Pruébalo en línea !

Versión antigua:

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

Pruébalo en línea .

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

EDITAR : Explicación:

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

Convierta la cadena de entrada en un int, luego el int en una cadena binaria y elimine sus dos primeros caracteres, ya que el binmétodo devuelve una cadena en el formato de0b...

Tome todas las subcadenas de la cadena binaria, conviértalas a decimales usando int(n, 2)y sumelas.

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

es una lista de todas las subcadenas. Versión sin golf:

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 esto ayude.

shooqie
fuente
4

CJam (22 bytes)

Este es un byte más largo que la mejor respuesta actual de CJam, pero el enfoque probablemente se pueda adaptar a otros idiomas de manera bastante rentable.

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

Demostración en línea

Análisis

Supongamos que la pregunta fuera

calcular la suma de las subcadenas del número binario

sin el bit

cuya longitud es más corta que el número original

Entonces no es demasiado difícil demostrar que el bit más significativo ocurre con el peso total, 1*(2^B-1)donde Bestá el número de bits; el segundo bit más significativo ocurre con el peso total 2*(2^(B-1)-1); hasta el bit más significativo de Bth, que ocurre con el peso totalB*(2^1-1) .

Teniendo en cuenta ahora la resta del número original x, terminamos con la suma

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

Disección

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

La conversión a la base 2 da la primera parte de la suma principal más x; a base 1 da la segunda parte más x; y a base 0 da justo x, así que restando la base-1 de la base-2 se xcancela s, y restando la base-0 da el resultado deseado.

Peter Taylor
fuente
3

JavaScript (ES6), 78 bytes

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

El exterior mapacumula subcadenas principales de nla representación binaria de '; el interno extrae las subcadenas finales de las subcadenas iniciales, cubriendo así todas las subcadenas posibles, incluida la representación binaria original.

Cada subcadena se convierte de binario a decimal y se resta de la entrada original, ya que esto es un poco más corto que sumarlas y restar la entrada original.

Neil
fuente
2

Mathematica, 73 70 bytes

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

Función. Entero-> Entero

CalculadoraFeline
fuente
1
Una lástima Mathica no tiene excelentes herramientas para lidiar con sublistas.
Un Simmons
1

Retina , 64

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

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

Pruébalo en línea!

Una descripción de etapa por etapa de alto nivel: convertir decimal a unario, unario a binario, obtener prefijos, obtener sufijos de prefijos, volcar el número original, convertir binario a unario, conteo devuelto. Escribiré una descripción más detallada una vez que termine de jugar al golf, muchas de estas etapas parecen sospechosas ...

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

Mantenemos un acumulador ay una máscara m. La máscara comienza en 1 y se alarga un poco cada vez alrededor del bucle externo. En el bucle interno, una copia ide la entrada se desplaza sucesivamente hacia la derecha hasta que sea más corta que la máscara, acumulando el valor enmascarado cada vez.

Programa de prueba

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

Prueba de salida

./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
fuente
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;}

O, si agrego Importar "usando System.Math estático"; entonces 138 con

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

Los lenguajes OOP como C # no ganarán tal carrera, pero quería probarlo de todos modos. Aquí hay una versión más embellecida + probador.

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

El Do-while anidado agrega el valor desplazado a la derecha de iTemp (después de asignarlo) siempre que shift + 1 sea menor que pos. La siguiente línea calcula el siguiente valor desplazado de 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 y x2 calculan la máscara, x3 la aplica y luego la desplaza hacia la izquierda, ya que el último dígito siempre se descarta. Para 11, se ve así:

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
fuente
Lo sé, la mayoría de las respuestas en C también funcionan sin problemas en C # (@ Tony-Speight trabajó sin problemas), pero eso desafiaría el propósito. Además, no miré los comentarios (bueno, excepto los encabezados en negrita) hasta que terminé, así que no había peligro de hacerlo "como C".
DW.com
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 Esa conversión a / desde binario es costosa.

Toma entrada $a, luego usa la llamada .NET[convert]::ToString($a,2) para convertirla en la representación binaria. A partir de ahí, pasamos por dos bucles: el primero cuenta hacia atrás desde el final de la cadena hacia abajo 1y el segundo cuenta hacia arriba desde 0. (El primero es cuánto tiempo debe extraerse una subcadena, y el segundo es el índice de dónde en la cadena comenzar la subcadena). Establecemos un ayudante $len el camino para pasarlo al bucle interno.

Dentro del bucle interno, usamos otra llamada .NET[convert]::ToInt32() para convertir la .substring()base apropiada 2en un entero. Cada uno de ellos se deja en la tubería. Encapsulamos todo eso con parens ()y -joinellos junto con a +, luego lo arrojamos a iex(short for Invoke-Expressiony similar-ish to eval).

Creo que esto técnicamente requiere v2 o más reciente para llamar correctamente a las llamadas .NET.

AdmBorkBork
fuente