Sumas enteras diluidas


26

Un entero positivo se puede diluir insertando 0entre dos bits en su expansión binaria. Esto significa que un nnúmero de bits tiene n-1diluciones, que no necesariamente son todas distintas.

Por ejemplo, para 12(o 1100en binario), las diluciones son

11000 = 24
   ^

11000 = 24
  ^

10100 = 20
 ^

En este desafío, vamos a tomar la suma de todas las diluciones, excluyendo el número original. Para 12, teniendo en cuenta la suma de 24, 24, 20resultados 68, también 68debería ser la salida para 12.

Reto

Dado un entero positivo n > 1como entrada, salida / retorno de la suma diluida como se explicó anteriormente.

Ejemplos

in    out
---   ---
2       4
3       5
7      24
12     68
333  5128
512  9216

Reglas

  • Se puede suponer que la entrada y la salida encajan en el tipo de entero nativo de su idioma.
  • La entrada y la salida se pueden dar en cualquier formato conveniente .
  • Un programa completo o una función son aceptables. Si es una función, puede devolver el resultado en lugar de imprimirlo.
  • Las lagunas estándar están prohibidas.
  • Este es el por lo que se aplican todas las reglas habituales de golf, y gana el código más corto (en bytes).

¿"Cualquier formato conveniente" incluye una cadena binaria?
Shaggy

1
@Shaggy "Cualquier formato conveniente" está destinado a incluir métodos de entrada / salida, no formato . Como tal, voy a decir que no, debe tomar la entrada como un entero o una cadena que representa ese entero.
AdmBorkBork

Buen desafío!
Manish Kundu

1
Esta secuencia está actualmente (30 de enero de 2018) no en el OEIS
Giuseppe

Respuestas:


12

Python 2 , 43 39 bytes

f=lambda n,i=2:n/i and n*2-n%i+f(n,i*2)

Pruébalo en línea!


¿Cómo?

Cada llamada de la función recursiva calcula una única dilución. La posición del insertado 0es log2(i). La función se repite hasta que se ihace más grande ny la inserción estaría a la izquierda del número. Si i>n, se n/ievalúa como 0, que es un valor falso en Python.

n*2desplaza el dígito binario número uno completo a la izquierda, n%io n % 2**(position of insertion)calcula el valor de la parte que no debe desplazarse a la izquierda. Este valor se resta del número desplazado.

Ejemplo (n = 7)

call       n/i          bin(n)  n*2     n%i   dilution       return value

f(7, i=2)  3 => truthy  0b111   0b1110  0b1   0b1101 = 13    13 + f(7, 2*2) = 13 + 11 = 24
f(7, i=4)  1 => truthy  0b111   0b1110  0b11  0b1011 = 11    11 + f(7, 4*2) = 11 + 0 = 11
f(7, i=8)  0 => falsy                                        0

7

Jalea , 11 bytes

BJṖ2*ɓdḅḤ}S

Pruébalo en línea!

Cómo funciona

BJṖ2*ɓdḅḤ}S  Main link. Argument: n (integer)

B            Binary; convert n to base 2. This yields a digit array A.
 J           Indices; yield [1, ..., len(A)].
  Ṗ          Pop; remove the last element, yielding [1, 2, ..., len(A)-1].
   2*        Elevate 2 to these powers, yielding [2, 4, ..., 2**(len(A)-1)].
             Let's call the result B.
     ɓ       Begin a new, dyadic chain, with left argument n and right argument B.
      d      Divmod; yield [n/b, n%b], for each b in B.
        Ḥ}   Unhalve right; yield 2b for each b in B, i.e., [4, 8, ..., 2**len(A)].
       ḅ     Unbase; convert each [n/b, n%b] from base 2b to integer, yielding
             (2b)(n/b) + (n%b).
          S  Take the sum.

5

MATL , 13 bytes

tZl:W&\5ME*+s

¡Pruébalo en MATL Online! O verificar todos los casos de prueba .

Explicación

Considere la entrada 12como un ejemplo.

t     % Implicit input. Duplicate
      % STACK: 12, 12
Zl    % Binary logarithm
      % STACK: 12, 3.584962500721156
:     % Range (rounds down)
      % STACK: 12, [1 2 3]
W     % Power with base 2, element-wise
      % STACK: 12, [2 4 8]
&\    % 2-output modulus, element-wise: pushes remainders and quotients
      % STACK: [0 0 4], [6 3 1]
5M    % Push array of powers of 2, again
      % STACK: [0 0 4], [6 3 1], [2 4 8]
E     % Multiply by 2
      % STACK: [0 0 4], [6 3 1], [4 8 16]
*     % Multiply, element-wise
      % STACK: [0 0 4], [24 24 16]
+     % Add, element-wise
      % STACK: [24 24 20]
s     % Sum of array. Implicit display
      % STACK: 68

4

C,  58  56 bytes

¡Gracias a @Dennis por guardar dos bytes!

s,k;f(n){for(s=0,k=2;k<=n;k*=2)s+=n/k*k*2+n%k;return s;}

Pruébalo en línea!

C (gcc) , 50 bytes

s,k;f(n){for(s=0,k=2;k<=n;)s+=n%k+n/k*(k+=k);k=s;}

Volver por k=s;es un comportamiento indefinido, pero funciona con gcc cuando las optimizaciones están deshabilitadas. Además, n%k+n/k*(k+=k)tiene un comportamiento no especificado , pero parece funcionar bien con gcc.

Pruébalo en línea!


s,k;f(n){for(s=0,k=2;k<=n;)s+=n%k+n/k*(k*=2);return s;}(55 bytes)
Kevin Cruijssen

1
No se sabe cuál se evalúa primero n%ko cuál n/k*(k*=2).
Steadybox

1
@KevinCruijssen El lado que se evalúa primero se deja sin especificar. C es así ...
Steadybox

2
Ah, veo que has añadido eso en tu respuesta. No sabía que este tipo de comportamiento indefinido sucedió en C. Tengo como tres horas de experiencia en C, así que apenas sé nada al respecto. TIL :) En Java for(s=0,k=2;k<=n;)s+=n%k+n/k*(k*=2);return s;está completamente bien, y n%ksiempre se evaluará antes n/k*(k*=2)y n/ktambién se evaluará antes k*=2. Gracias por la explicación. (Eliminaré algunos de mis comentarios ahora para reducir el desorden).
Kevin Cruijssen

Me encanta usar UB como característica. Y el golf de código en un idioma de la vida real debería estar en otra categoría de todos modos :)
Regis Portalez

4

Jalea , 9 8 bytes

BḊḄÐƤạḤS

Pruébalo en línea!

B                        to binary          42 -> 1 0 1 0 1 0
 Ḋ                       drop first                 0 1 0 1 0
  ḄÐƤ                    each suffix to decimal   10 10 2 2 0
      Ḥ                  double the input                  84
     ạ                   absolute difference   74 74 82 82 84
       S                 add them up                      396

Viceversa B¹ƤṖ+BḄS: obtener prefijos, soltar al final, agregarlos a la entrada y sumar.


4

J , 20 15 14 bytes

+/@}:@:+[\&.#:

Pruébalo en línea.

15 bytes

1#.-,+:-#.\.@#:

Pruébalo en línea!

     +:             Input×2
       -            Subtract
        #.\.@#:     The list of binary suffixes of input (in decimal)
   -,               Append negative input
1#.                 Add them up

¿Por qué funciona la fórmula doble menos? ¿Por qué es equivalente a diluciones?
Jonás

1
La dilución de @Jonah es agregar un cierto prefijo binario (número "redondeado hacia abajo") al número, lo que equivale a sumar el número entero (tanto el prefijo como el resto) y luego restar el resto.
FrownyFrog

4

Japt , 12 11 bytes

¢¬£¢iYTÃÅxÍ

Intentalo


Explicación

                 :Implicit input of integer U
¢                :Convert to base-2 string
 ¬               :Split to an array of individual characters/digits
  £    Ã         :Map over the elements, with Y being the current 0-based index
   ¢             :  Convert U to a base-2 string
    iYT          :  Insert a 0 in that string at index Y
        Å        :Slice off the first element of the array
          Í      :Convert each element to a base-10 integer
         x       :Reduce by addition

3

JavaScript (ES6), 41 40 bytes

Guardado 1 byte gracias a Mr.Xcoder

f=(n,k=1)=>k<n&&(n&k)+2*(n&~k)+f(n,k-~k)

Casos de prueba


3

Retina , 53 50 47 bytes

.+
*
+`(_+)\1
$1O
O_
_
L$`\B
$`O$'
+%`\B
¶$`¶
_

Pruébalo en línea! El enlace incluye casos de prueba. Editar: Guardado 3 bytes gracias a @MartinEnder. Explicación:

.+
*
+`(_+)\1
$1O
O_
_

Convierta de decimal a binario, pero use O para representar 0, ya que no es un dígito, y _ para representar 1, ya que es el carácter de repetición predeterminado en Retina 1.

L$`\B
$`O$'

Inserte una O entre cada par de dígitos y recopile los resultados como una lista.

+%`\B
¶$`¶

Convierte de binario a unario. (Esta conversión produce Os adicionales , pero no nos importa).

_

Suma y convierte a decimal.


La conversión de binario a decimal se puede hacer en 12 bytes (guardando 3): tio.run/##K0otycxLNPz/… Vea esta respuesta para ver cómo funciona.
Martin Ender

@ Martininder Gracias, sigo olvidándome de eso. (También me decepcionó un poco que la versión alternativa solo funcione en un solo número).
Neil

Bueno, en el caso de que tenga cada número en su propia línea, puede hacer que funcione con un adicional %. Si es más complicado, necesitarías algo así /[O_]+/_.
Martin Ender

2

Pyth , 13 bytes

smiXd.BQZ2Ssl

Pruébalo aquí!

Explicación

smiXd.BQZ2Ssl | Programa completo

           sl | El logaritmo de base 2 de la entrada, con un piso entero.
          S | Cree el rango entero [1 ... el logaritmo con piso].
 m | Y mapear una función sobre ella.
------------ + - + ----------------------------------- ------------------
  iXd.BQZ2 | La función a mapear (usa una variable d).
     .BQ | En la representación binaria de la entrada ...
   XZ | ... Insertar un cero ...
    d | ... En el índice d.
  i 2 | Y convierta el resultado de la base 2 a un entero.
------------ + - + ----------------------------------- ------------------
s | Suma la lista resultante.

2

Jalea , 10 bytes

BµLḤ_J’×µḄ

Pruébalo en línea!

No es el más corto actualmente, pero podría serlo si hay una forma de evitarlo Bµ µḄ...

Explicación

BµLḤ_J’×µḄ    Main link. Argument: n (integer)
B             Binary; convert n to an binary of binary digits. Call this A.
 µ            Start a new monadic link with argument A.
  L           Length; yield len(A). We'll call this l.
   Ḥ          Unhalve; yield l * 2.
     J        Length range; yield [1, 2, ..., l].
    _         Subtract; yield [l*2 - 1, l*2 - 2, ..., l].
      ’       Decrement; subtract one from each item.
       ×      Multiply each item by the corresponding item in A. Call this B.
        µ     Start a new monadic link with argument B.
         Ḅ    Unbinary; convert from a binary array to a decimal.

Básicamente, esto funciona multiplicando cada dígito binario por un número mágico. No puedo explicarlo sin visualizarlo, así que aquí está el número binario con el que trabajaremos:

1111

Como se explica en el desafío, el resultado que queremos es la suma de estos números binarios:

10111  = 2^4 + 2^2 + 2^1 + 2^0
11011  = 2^4 + 2^3 + 2^1 + 2^0
11101  = 2^4 + 2^3 + 2^2 + 2^0

Sin embargo, en realidad no tenemos que insertar ceros: el átomo "no binario" de Jelly aceptará otros números además de 0y 1. Cuando nos permitimos usar 2, este patrón se vuelve más simple:

2111   = 2*2^3 + 1*2^2 + 1*2^1 + 1*2^0
2211   = 2*2^3 + 2*2^2 + 1*2^1 + 1*2^0
2221   = 2*2^3 + 2*2^2 + 2*2^1 + 1*2^0

Cuando sumamos los dígitos en cada columna, obtenemos

6543   = 6*2^3 + 5*2^2 + 4*2^1 + 3*2^0 = 48 + 20 + 8 + 3 = 79.

El truco que usa esta respuesta es generar este patrón y multiplicar cada dígito por el dígito correspondiente en el original para cancelar las columnas necesarias. 12, por ejemplo, se representaría como

 1100
×6543
=6500  = 6*2^3 + 5*2^2 + 0*2^1 + 0*2^0 = 48 + 20 + 0 + 0 = 68.


1

Casco , 13 12 bytes

-1 byte gracias a @Mr. Xcoder!

ṁḋ§z·+Θḣotṫḋ

Pruébalo en línea!

Explicación

ṁḋ§z·+Θḣ(tṫ)ḋ  -- example input: 6
            ḋ  -- convert to binary: [1,1,0]
  §            -- fork argument
        (tṫ)   -- | tail of tails: [[1,0],[0]]
       ḣ       -- | heads: [[1],[1,1],[1,1,0]]
   z           -- and zipWith the following (example with [1,0] [1])
    · Θ        -- | prepend 0 to second argument: [0,1]
     +         -- | concatenate: [1,0,0,1]
               -- : [[1,0,1,0],[1,1,0,0]]
ṁ              -- map the following (example with [1,0,1,0]) and sum
 ḋ             -- | convert from binary: 10
               -- : 22


1

Pip , 21 18 bytes

2*a-a%2**_MS1,#TBa

Pruébalo en línea!

Explicación

Llame a nuestro número de entrada a. Para cada índice binario ien el que queremos insertar un cero, podemos calcular los bits a la izquierda del punto de inserción como a // 2**i(donde //es la división de enteros y la **exponenciación), los bits a la derecha del punto de inserción como a % 2**iy, por lo tanto, el entero diluido como 2 * (a // 2**i) * 2**i + (a % 2**i). Pero (a // 2**i) * 2**ies igual a a - (a % 2**i), por lo que podemos reorganizar a una fórmula más corta: 2 * (a - a % 2**i) + a % 2**i= 2 * a - a % 2**i.

2*a-a%2**_MS1,#TBa
                       a is 1st command-line argument (implicit)
               TBa     Convert a to binary
              #        Length of the binary expansion
            1,         Range from 1 up to (but not including) that number
          MS           Map this function to the range and sum the results:
2*a-a%2**_              The above formula, where _ is the argument of the function
                       The final result is autoprinted

1

R , 141 48 bytes

function(n,l=2^(1:log2(n)))sum(n%%l+(n%/%l*2*l))

Pruébalo en línea!

O estoy haciendo algo realmente mal o R es simplemente terrible en la manipulación de bits. Portabilidad el enfoque de Luis Mendo es fácil, correcto y golfoso.

Pero si realmente solo quieres perder el tiempo con operaciones de bits, MickyT sugirió el siguiente byte de 105:

function(i)sum(sapply(1:max(which(b<-intToBits(i)>0)),function(x)packBits(head(append(b,F,x),-1),"i")))-i

Pruébalo en línea!


Aquí hay uno de 111 bytes del que estoy seguro de que podría sacar un poco más.
MickyT

@MickyT ¡Salud! muy agradable, ¡aunque portar un enfoque completamente diferente es mejor!
Giuseppe


1

Lote, 92 77 bytes

@set/an=2,t=0
:l
@if %1 geq %n% set/at+=%1*2-(%1%%n),n*=2&goto l
@echo %t%

Editar: cambió a la misma fórmula que todos los demás están usando.




0

Adjunto , 57 bytes

Sum##UnBin=>{Join[Join=>_,"0"]}=>SplitAt#1&`:@{#_-1}##Bin

Pruébalo en línea!

Pensé que abordaría el problema desde un enfoque de manipulación sin bits, ya que dicho enfoque no es práctico en Attache. Tengo que investigar algunas de las partes de este enfoque para buscar alternativas.

Explicación

Aquí hay una versión ampliada:

Define[$joinByZero, {Join[Join=>_,"0"]}]

Define[$insertionPoints,
    SplitAt#1&`:@{#_-1}
]

Define[$f,
Sum##UnBin=>joinByZero=>insertionPoints##Bin
]

Esto simplemente toma la representación binaria del número, lo divide en ciertos puntos, inserta ceros allí, los convierte a decimales y los suma.


0

J , 33 bytes

1#.[:}:#.@(<\;@(,0;])"0<@}.\.)@#:

Lo más probable es que haya mucho espacio para más golf.

¿Cómo?

@#: convertir a binario y

<@}.\. - encuentra todos los suficientes, suelta el primer dígito de cada cuadro

<\ - encuentra todos los prefijos y los encajona

(,0;])"0 - a cada prefijo agregue 0 y luego agregue el sufijo decapitado correspondiente

;@ raze (sin caja)

1#.[:}:#.@ - convertir a decimal, acortar y sumar

Pruébalo en línea!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.