Convertidor binario a decimal

32

Convertidor binario a decimal

Hasta donde puedo ver, no tenemos un desafío simple de conversión de binario a decimal.


Escriba un programa o función que tome un entero binario positivo y genere su valor decimal.

No está permitido utilizar ninguna función de conversión de base integrada. Las funciones de entero a decimal (por ejemplo, una función que se convierte 101010en [1, 0, 1, 0, 1, 0]o "101010") están exentas de esta regla y, por lo tanto, están permitidas.

Reglas:

  • El código debe admitir números binarios hasta el valor numérico más alto que admite su idioma (de forma predeterminada)
  • Puede elegir tener ceros a la izquierda en la representación binaria
  • La salida decimal puede no tener ceros a la izquierda.
  • Los formatos de entrada y salida son opcionales, pero no puede haber separadores entre los dígitos. (1,0,1,0,1,0,1,0)no es un formato de entrada válido, pero ambos 10101010y (["10101010"])son.
    • Debe tomar la entrada en la dirección "normal". 1110es 14no 7.

Casos de prueba:

1
1

10
2

101010
42

1101111111010101100101110111001110001000110100110011100000111
2016120520371234567

Este reto se relaciona con algunos otros retos, por ejemplo, este , este y este .

Stewie Griffin
fuente
Relacionado
mbomb007
¿La salida tiene que estar sin firmar o puede estar firmada? Además, si mi idioma cambia automáticamente entre enteros de 32 bits y 64 bits dependiendo de la longitud del valor, ¿se puede firmar la salida en ambos rangos? Por ejemplo, hay dos valores binarios que se convertirán a decimal -1( 32 1'sy 64 1's)
leche
Además, ¿puede la salida ser flotante? ¿Es necesario que sea un número entero?
Carcigenicate
@Carcigenicate Debe ser un número entero, pero puede ser de cualquier tipo de datos. Mientras round(x)==xestés bien :) 2.000se acepta la salida para 10.
Stewie Griffin
Oh dulce. Gracias.
Carcigenicate

Respuestas:

56

Jalea , 5 bytes

DḤ+¥/

Pruébalo en línea!

Explicación

ingrese la descripción de la imagen aquí

El elenco

  • Des una mónada (función de argumento único): dígitos, convirtiéndose 1234en [1, 2, 3, 4].

  • es una mónada que duplica su argumento único.

  • + es una diada (función de dos argumentos) que agrega sus argumentos izquierdo y derecho.

A partir de ahí, se pone un poco complicado.

Esto es lo que sucede en el momento del análisis

  • D, y +son leídos. La cadena se parece [D, Ḥ, +].

  • Los siguientes dos caracteres son rápidos , que actúan como operadores de postfix en tiempo de análisis en los enlaces (funciones) que hemos leído hasta ahora.

  • Cuando ¥se lee, los dos últimos enlaces aparecen y se reemplazan por un enlace que actúa como la diada formada al componerlos. Así que ahora se ve la cadena [D, dyad(Ḥ+)].

  • Cuando /se lee, el último enlace (que debería ser una díada) aparece y se reemplaza por una mónada que se pliega usando esta díada (intuitivamente: f/toma una lista, reemplaza las comas fy evalúa el resultado).

  • La cadena final se parece a [D, fold(dyad(Ḥ+))]dos mónadas.

Esto es lo que sucede en el tiempo de ejecución.

  • La entrada (un número) se lee implícitamente en el valor de trabajo (por ejemplo, 101010).

  • Dse ejecuta, reemplazando el valor de trabajo con sus dígitos ( [1,0,1,0,1,0]).

  • fold(dyad(Ḥ+))se ejecuta, reemplazando el valor de trabajo con 1∗0∗1∗0∗1∗0, donde está la diada Ḥ+.

Entonces, ¿qué x∗yevalúa?

  • En una definición diádica, el valor de trabajo es inicialmente la izquierda argumento x.

  • , la mónada doble , duplica este valor. El valor de trabajo es ahora 2x.

  • +, la díada más , carece de un argumento correcto, por lo que este es un gancho : un patrón sintáctico especial donde se inyecta el argumento correcto de esta díada +. Esto rinde 2x + ycomo el valor de trabajo final, que se devuelve.

Entonces toda la expresión se evalúa como:

1∗0∗1∗0∗1∗0 = 2×(2×(2×(2×(2×1+0)+1)+0)+1)+0
            = 32×1 + 16×0 + 8×1 + 4×0 + 2×1 + 1×0
            = 42
Lynn
fuente
10
Tus explicaciones son cada vez mejores :-)
Luis Mendo
2
Je, supongo que lo harás de ahora en adelante. Eso es asombroso, +1.
Erik the Outgolfer
44
Creo que esta es la primera pieza de gelatina que he entendido. +1!
Azul
Bravo. Realmente entiendo lo que inicialmente pensé que era solo un desastre de personajes aparentemente aleatorios. Maravillosa explicación.
swinefish
1
@ Mark Jelly tiene su propia página de códigos para hacer que los programas se vean, ejem, legibles, pero los programas también podrían ser cadenas de bytes.
Lynn
20

Pitón 2, 49 37 31 30 Bytes

Ahora, esto tomará un número binario en una representación decimal, ya que Python puede manejar enteros arbitrariamente grandes.

b=lambda n:n and n%2+2*b(n/10)

gracias a xnor por guardar un byte :)

La forma más fácil de ver cómo funciona esto es ver una fórmula básica para convertir binario a decimal:

= 101010 
= 1*(2^5) + 0*(2^4) + 1*(2^3) + 0*(2^2) + 1*(2^1) + 0*(2^0)
= 1*32 + 0*16 + 1*8 + 0*4 + 1*2 + 0*1
= 42

Esta es una forma 'estándar' de conversión. Puede expandir la tercera línea así:

= ((((1*2 + 0)*2 + 1)*2 + 0)*2 + 1)*2 + 0

Y esto es esencialmente lo que está haciendo el método recursivo que he hecho.

Soluciones alternativas que tenía:

b=lambda n:n and n%10+2*b(n/10)
b=lambda n:n%10+2*(n and b(n/10))
b=lambda n:0if n<1else n%10+2*b(n/10)
b=lambda n:0**(n/10)or n%10+2*b(n/10)
b=lambda n,o=0:o*(n<'0')or b(n[1:],2*o+int(n[0]))
lambda j:sum(int(b)*2**a for a,b in enumerate(j,1))
Kade
fuente
66
Puedes hacer n%5o en n%2lugar de n%10.
xnor
@xnor Ah, ¡no estoy seguro de cómo me perdí eso! Gracias :)
Kade
12

05AB1E , 6 bytes

Código:

$¦v·y+

Para la explicación, tomemos el ejemplo 101010 . Comenzamos con el número 1 (que está representado por el primer dígito). Después de eso, tenemos dos casos:

  • Si el dígito es un 0 , multiplique el número por 2.
  • Si el dígito es un 1 , multiplique el número por 2 y agregue 1.

Entonces, para el caso 101010 , se calcula lo siguiente:

  • 1 01010, comienza con el número 1 .
  • 1 0 1010, multiplica por dos, resultando en 2 .
  • 10 1 010, multiplique por dos y agregue uno, resultando en 5 .
  • 101 0 10, multiplica por dos, lo que resulta en 10 .
  • 1010 1 0, multiplique por dos y agregue uno, resultando en 21 .
  • 10101 0 , multiplique por dos, resultando en 42 , que es el resultado deseado.

Explicación del código:

$         # Push 1 and input
 ¦        # Remove the first character
  v       # For each character (starting with the first)
   ·      #   Multiply the carry number by two
    y+    #   Add the current character (converted automatically to a number)

Utiliza la codificación CP-1252 . Pruébalo en línea!

Adnan
fuente
¡Buena esa! (no funciona para 0, aunque me acabo de dar cuenta)
Emigna 05 de
@Emigna Sí, afortunadamente su código solo necesita funcionar para números binarios positivos.
Adnan
Ni siquiera vi esa parte. Muy agradable entonces :)
Emigna
9

Haskell, 16 111 + 57 = 168 bytes

import Data.String
instance IsString[Int]where fromString=map((-48+).fromEnum)
f::[Int]->Int
f=foldl1((+).(2*))

+57 bytes para los indicadores de compilación -XOverloadedStrings, -XOverlappingInstancesy -XFlexibleInstances.

El desafío tiene un formato de E / S engorroso , porque depende en gran medida de cómo se expresan los tipos de datos en el código fuente. Mi primera versión (16 bytes), a saber

foldl1((+).(2*))

toma una lista de enteros, por ejemplo, [1,0,1,0,1,0]y se declaró no válida porque las listas literales de Haskell tienen ,entre los elementos. Las listas per se no están prohibidas. En mi nueva versión utilizo la misma función, ahora nombrada f, pero sobrecargo "Citar secuencias de caracteres incluidas". La función todavía toma una lista de enteros como puede ver en la anotación de tipo [Int] -> Int, pero las listas con enteros de un solo dígito ahora se pueden escribir como "1234", por ejemplo

f "101010"

que será evaluado 42. Haskell desafortunado, porque el formato de lista nativa no se ajusta a las reglas de desafío. Por cierto, f [1,0,1,0,1,0]todavía funciona.

nimi
fuente
2
Lamentablemente, una lista no es una entrada válida.
Jonathan Allan
@JonathanAllan: ¿Por qué? Y si es así, ¿cómo debería tomar algo? En Haskell, una cadena es solo una lista de caracteres.
nimi
No sé por qué ... pero pregunté sobre esto desde el principio y se realizó una edición para agregar " (1,0,1,0,1,0,1,0)no es un formato de entrada válido, pero ambos 10101010y lo (["10101010"])son". además, un comentario sugiere que la matriz de caracteres es aceptable si así es como se interpreta una entrada de cadena.
Jonathan Allan
1
@JonathanAllan: cualquier "entero binario" (la entrada que tenemos que tomar) está inherentemente separado, es una secuencia de potencias de 2. La restricción se trata de separadores explícitos (entre los dígitos) y no de la separación. De alguna manera tengo que tomar dígitos separados.
nimi
2
Op aquí: si es posible ingresar 10101010, "10101010"o algo similar y hacer que funcione, entonces el envío es válido. Puede llamarlo cadena, lista, número entero o lo que sea. Ingresando [1][0][1][0]o [1,0,1,0]no está bien. Básicamente, debería ser posible golpear un montón de unos y ceros en una fila en alguna parte. ¿Está esto claro?
Stewie Griffin
7

Retina, 15 bytes

Convierte de binario a unario, luego unario a decimal.

1
01
+`10
011
1

Pruébalo en línea

mbomb007
fuente
No está permitido utilizar ninguna función de conversión de base integrada. ~ OP
Roman Gräf
10
@ RomanGräf No hay ninguno. Simplemente estaba describiendo el proceso de mi solución.
mbomb007
7

PHP, 44 bytes

for(;""<$c=$argv[1][$i++];)$n+=$n+$c;echo$n;

Podría haber jurado que había visto esa pregunta antes. Pero bueno.

Lee el número de izquierda a derecha, se desplaza a la izquierda y agrega el bit actual.

Titus
fuente
7

JavaScript (ES6), 33 31 bytes

s=>[...s].map(c=>r+=+c+r,r=0)|r

Editar: más corto pero menos dulce: 2 bytes guardados gracias a @ETHproductions.

Neil
fuente
Como suele ser el caso, .mapes más corto:s=>[...s].map(c=>+c+r+r,r=0)|r
ETHproductions
@ETHproductions ¿Cómo devuelve su función algo que no sea 0?
Neil
Lo sentimos, debería sers=>[...s].map(c=>r+=+c+r,r=0)|r
ETHproductions
7

Laberinto , 17 15 bytes

-+:
8 +
4_,`)/!

Pruébalo en línea!

Imagen del codigo

Labyrinth es un lenguaje bidimensional basado en la pila. En el laberinto, la ejecución del código sigue la ruta del código como un laberinto con espacios que actúan como muros y comienzan en el carácter no espacial más a la izquierda. El flujo del código está determinado por el signo de la parte superior de la pila. Como la pila tiene ceros implícitos en la parte inferior, las primeras cuatro instrucciones ( -+:+) no tienen efecto.

Loop que comienza en el ,

  • , Presione el valor del código ASCII del siguiente carácter de entrada hasta el tope de la pila, o presione -1 si EOF.
  • _48 empuja 48 a la cima de la pila
  • - Pop y, pop x, empujar x-y . Las instrucciones anteriores tienen el efecto de restar 48 de la entrada produciendo 0 para "0" y 1 para "1".
  • +Pop y, pop x, empujar x+y.
  • : Duplicar la parte superior de la pila.
  • + Esta y la instrucción anterior tienen el efecto de multiplicar el valor actual por 2

Entonces, la parte circular del código, en efecto, multiplica el número actual por 2 y agrega 1 o 0 dependiendo de si se ingresó el carácter 1 o 0.

Cola

Si la parte superior de la pila es negativa (lo que significa que se encontró EOF), el código girará a la izquierda en el cruce (hacia el punto y coma).

  • `` Niega la parte superior de la pila para obtener 1
  • ) Icrement la parte superior de la pila para obtener 2
  • /Pop y, pop x, push x / y (división entera). Esto tiene el efecto de deshacer el último *2del bucle.
  • !Salida de la representación entera de la parte superior de la pila. En este punto, el programa se da vuelta porque llegó a un callejón sin salida y luego sale con un error porque intenta dividir por cero.

Gracias a @Martin Ender por guardarme 2 bytes (y enseñarme a pensar mejor en Labyrinth).

Robert Hickman
fuente
En lugar de _48-usted, simplemente puede hacerlo, #%pero desafortunadamente no veo cómo podría ayudar con el recuento de bytes.
Martin Ender
Usted puede guardar un byte con `)en lugar de ;_2embargo.
Martin Ender
@ MartinEnder, no entiendo tu comentario sobre #%. ¿Puede explicar cómo funciona eso como un reemplazo para _48-convertir de ascii a int. Gracias por el )dato. Haré ese cambio.
Robert Hickman
En ese punto de su programa, siempre hay dos valores en la pila, por lo que #es la abreviatura de _2. Si bien _2%no es un método de conversión general para ASCII a entero, funciona aquí porque solo le interesan los dos primeros dígitos como entrada posible. Una alternativa sería _1&(ya que el módulo 2 simplemente extrae el bit menos significativo).
Martin Ender
Oh. Eso es brillante. Pero sí, no estoy seguro de cómo usar esa sustitución ( #%) para acortar el código en general.
Robert Hickman
6

Brain-Flak , 46 , 28 bytes

([]){{}({}<>({}){})<>([])}<>

Pruébalo en línea!

¡Muchos, muchos bytes guardados gracias a @Riley!

Dado que brain-flak no puede tomar entradas binarias, la entrada es una lista de '0' y '1'.

Explicación:

#Push the height of the stack
([])

#While true:
{

 #Pop the height of the stack
 {}

 #Push this top number to (the other stack * 2)
 ({}<>({}){})

 #Toggle back on to the main stack
 <>

 #Push the new height of the stack
 ([])

#endwhile
}

#Toggle back to the other stack, implicitly display.
<>
DJMcMayhem
fuente
Me encanta la explicación! Tan difícil de leer el cerebro sin él :)
Emigna
2
^. Ni siquiera puedo leer mis propios programas si no me dejo algunos comentarios.
Riley
Puede reducirlo a 32 bytes deshaciéndose del todo si es parte, y para el paso "agregar número a otra pila" simplemente agréguelo a (otra pila) * 2. ([]){({}[()]<({}<>({}){})><>)}<>
Riley
Y puede guardar otros 4 simplemente haciendo estallar al comienzo del tiempo y presionando la altura nuevamente al final. ([]){{}({}<>({}){})<>([])}<>
Riley
@Riley Oh, Dios mío, eso es genial. ¡Muchas gracias!
DJMcMayhem
6

Java, 84 79 46 48 bytes

  • Versión 3.1

Cambiado a long/ 48 bytes:

s->{long x=0;for(char c:s)x=c-48l+x*2;return x;}
  • Versión 3.0

Hice algo de golf / 46 bytes:

s->{int x=0;for(char c:s)x=c-48+x*2;return x;}
  • Versión 2.0

Gracias a @Geobits! / 79 bytes:

s->{int i=Math.pow(2,s.length-1),j=0;for(char c:s){j+=c>48?i:0;i/=2;}return j;}
  • Version 1.0

84 bytes:

s->{for(int i=-1,j=0;++i<s.length;)if(s[i]>48)j+=Math.pow(2,s.length-i+1);return j;}
Roman Gräf
fuente
1
Supongo que debería haber hecho una solución iterativa. lulz buen trabajo
Poke
¿Es su tipo de entrada List <Character> o String? Si es lo último, ¡no sabía que Java8 podría hacer eso! Si es lo primero, ¿está permitido por el desafío?
Poke
sdebería ser char[]. Espero que eso esté permitido ...
Roman Gräf
¿Cuál es el tipo de devolución aquí? Creo que debería ser largo porque "El código debe admitir números binarios hasta el valor numérico más alto que admite su idioma" según el OP, pero para valores más pequeños, creo que devuelve un int
Poke
1
Probablemente bien en el tipo de entrada por esto . Es posible que desee tomar el hit de 2 bytes para la salida de la OMI
Poke
4

Befunge-98, 12 bytes

2j@.~2%\2*+

Pruébalo en línea!

Lee un carácter a la vez desde la entrada, lo convierte a 0 o 1 tomando su valor módulo 2 (0 es carácter (48), 1 es carácter (49)), luego utiliza el algoritmo habitual para duplicar el valor actual y agregar el nuevo dígito cada vez.

Bonificación: esto funciona con cualquier tipo de cadena de entrada, he estado intentando por un tiempo encontrar alguna combinación divertida de entrada-> salida, pero no pude producir nada (lamentablemente, "respuesta" = 46). ¿Puedes?

León
fuente
Jajaja Estaba jugando el mismo juego con mi respuesta. El número más interesante que pude generar fue 666 .
James Holderness
¡Buena esa! No había logrado encontrar nada apropiado para 666: D Sería mucho más fácil si la capitalización tuviera un efecto en los valores ...
Leo
@James Holderness: he estado haciendo lo mismo y solo he encontrado 'theleapyear' para traer de vuelta 366, el tuyo es realmente bueno.
Teal pelican
4

Javascript (ES7) 41 40 36 bytes

f=([c,...b])=>c?c*2**b.length+f(b):0

toma una cadena como entrada

Afeitado un byte gracias a ETHproductions

f=([c,...b])=>c?c*2**b.length+f(b):0
document.write([
    f('101010'),
    f('11010'),
    f('10111111110'),
    f('1011110010110'),
].join("<br>"))

Shaun H
fuente
1
La asociatividad de derecha a izquierda de **es extraña, pero es un buen trabajo usarla aquí. 1<<b.lengthharía lo mismo, pero requeriría paréntesis para evitar ser analizado como (c*1)<<(b.length+...). Creo que puede guardar un byte reemplazándolo b[0]con b+b( ver aquí ).
ETHproductions
4

C # 6, 85 37 36 bytes

long b(long n)=>n>0?n%2+2*b(n/10):0;
  • Gracias a Kade por guardar 41 bytes!
  • El cambio a C # 6 salvó otros 7 bytes.
Yytsi
fuente
Tal vez esto podría proporcionar algo de inspiración? ;)
Kade
@Kade Sí, gracias! Estaba mirando la respuesta de Python que usa la misma técnica en el mismo momento en que vinculaste eso: DI puede
acortarse
3

C, 53

v(char*s){int v=0,c;while(c=*s++)v+=v+c-48;return v;}

Igual que mi respuesta de JavaScript

Prueba de ideona

edc65
fuente
Puede guardar 4 bytes declarando vy ccomo variables globales (aunque necesita cambiar el nombre de v, ya que ya es el nombre de la función) de esta manera:w=0;c;v(char*s){while(c=*s++)w+=w+c-48;return w;}
Steadybox
@Steadybox podría ser, w,c;pero no quiero usar globals cuando la respuesta es una función (incluso en code-golf)
edc65
@Steadybox Globals también tiene el valor predeterminado 0, por lo que puede soltar el =0.
algmyr
3

Perl, 25 bytes

-3 bytes gracias a @Dom Hastings.

24 bytes de código + 1 byte para -pbandera.

$\|=$&<<$v++while s/.$//

Para ejecutarlo:

perl -pe '$\|=$&<<$v++while s/.$//' <<< 101010

Explicaciones:

$\|=$&<<$v++  # Note that: we use $\ to store the result
              # at first $v=0, and each time it's incremented by one
              # $& contains the current bit (matched with the regex, see bellow)
              # So this operation sets a $v-th bit of $\ to the value of the $v-th bit of the input
while         # keep doing this while...
s/.$//        #  ... there is a character at the end of the string, which we remove.
         # $\ is implicitly printed thanks to -p flag
Dada
fuente
3

Pushy , 10 bytes

Toma la entrada como una lista de 0/1 en la línea de comando: $ pushy binary.pshy 1,0,1,0,1,0 .

L:vK2*;OS#

El algoritmo realmente muestra la belleza de tener una segunda pila:

            \ Implicit: Input on stack
L:    ;     \ len(input) times do:
  v         \   Push last number to auxiliary stack
   K2*      \   Double all items
       OS#  \ Output sum of auxiliary stack

Este método funciona porque la pila se duplicará stack length - n antes de alcanzar el númeron , que luego se volcará en la segunda pila para más adelante. Así es como se ve el proceso para la entrada 101010:

1: [1,0,1,0,1,0]
2: []

1: [2,0,2,0,2]
2: [0]

1: [4,0,4,0]
2: [2]

1: [8,0,8]
2: [2,0]

1: [16,0]
2: [2,0,8]

1: [32]
2: [2,0,8,0]

1: []
2: [2,0,8,0,32]

2 + 8 + 32 -> 42
FlipTack
fuente
3

Matlab, 30 bytes

@(x)sum(2.^find(flip(x)-48)/2)

El último caso de prueba tiene errores de redondeo (debido a double), por lo que si necesita precisión completa:

@(x)sum(2.^uint64(find(flip(x)-48))/2,'native')

con 47 bytes.

Jonas
fuente
No puedo probar esto, pero creo @(x)sum(2.^(find(flip(x)-48)-1))que dará el resultado correcto para todos los casos para 32 bytes. flipfunciona como fliplrsi xes unidimensional.
Stewie Griffin
Buena solución! También me encontré con el error de redondeo, gracias por la solución. ¿Cuál es el formato de x? Llamar a flip o fliplr en un número solo devuelve ese número.
MattWH
x es la cadena binaria, así que llámalo con f=@(x)..; f('1111001010').
Jonas
3

Retina , 12 bytes

El recuento de bytes asume la codificación ISO 8859-1.

+%`\B
¶$`:
1

Pruébalo en línea!

Solución alternativa:

+1`\B
:$`:
1

Explicación

Probablemente será más fácil de explicar según mi versión anterior, menos golfizada, y luego mostrar cómo la acorté. Solía ​​convertir binario a decimal así:

^
,
+`,(.)
$`$1,
1

La única forma sensata de construir un número decimal en Retina es contando cosas (porque Retina tiene un par de características que le permiten imprimir un número decimal que representa una cantidad). Entonces, realmente, el único enfoque posible es convertir el binario en unario, y luego contar el número de dígitos unarios. La última línea cuenta, por lo que los primeros cuatro convierten el binario en unario.

¿Como hacemos eso? En general, para convertir de una lista de bits a un entero, inicializamos el resultado 0y luego pasamos por los bits del más significativo al menos significativo, duplicamos el valor que ya tenemos y sumamos el bit actual. Por ejemplo, si el número binario es 1011, realmente calcularíamos:

(((0 * 2 + 1) * 2 + 0) * 2 + 1) * 2 + 1 = 11
           ^        ^        ^        ^

Donde he marcado los bits individuales para mayor claridad.

El truco para hacer esto en unario es a) que duplicar simplemente significa repetir el número yb) ya que estamos contando la 1s al final, ni siquiera necesitamos distinguir entre 0sy 1s en el proceso. Esto se aclarará en un segundo.

Lo que hace el programa es que primero agrega una coma al principio como marcador de la cantidad de información que ya hemos procesado:

^
,

A la izquierda del marcador, tendremos el valor que estamos acumulando (que se inicializa correctamente en la representación unaria de cero), y la derecha del valor será el siguiente bit a procesar. Ahora aplicamos la siguiente sustitución en un bucle:

,(.)
$`$1,

Solo mirando ,(.)y $1,, esto mueve el marcador un poco hacia la derecha cada vez. Pero también insertamos $`, que está todo delante del marcador, es decir, el valor actual, que estamos duplicando. Estos son los pasos individuales al procesar la entrada 1011, donde he marcado el resultado de insertar$` encima de cada línea (está vacío para el primer paso):

,1011

1,011
 _
110,11
   ___
1101101,1
       _______
110110111011011,

Verá que hemos retenido y duplicado el cero junto con todo lo demás, pero como los estamos ignorando al final, no importa con qué frecuencia los hayamos duplicado, siempre que el número de 1 s sea correcto. Si los cuenta, hay algunos 11de ellos, justo lo que necesitamos.

Eso deja la cuestión de cómo jugar golf a 12 bytes. La parte más cara de la versión de 18 bytes es tener que usar el marcador. El objetivo es deshacerse de eso. Realmente queremos duplicar el prefijo de cada bit, por lo que una primera idea podría ser esta:

.
$`$&

El problema es que estas sustituciones ocurren simultáneamente, por lo que el primer bit no se duplica para cada bit, sino que solo se copia una vez cada vez. Para la entrada 1011obtendríamos (marcando el insertado $`):

 _ __ ___
1101011011

Todavía necesitamos procesar la entrada de forma recursiva para que el primer prefijo duplicado se duplique nuevamente por el segundo y así sucesivamente. Una idea es insertar marcadores en todas partes y reemplazarlos repetidamente con el prefijo:

\B
,
+%`,
¶$`

Después de reemplazar cada marcador con el prefijo por primera vez, debemos recordar dónde estaba el comienzo de la entrada, por lo que también insertamos saltos de línea y usamos la %opción para asegurarnos de que el siguiente$` solo recoja los elementos del salto de línea más cercano.

Esto funciona, pero aún es demasiado largo (16 bytes al contar 1s al final). ¿Qué tal si cambiamos las cosas? Los lugares donde queremos insertar marcadores se identifican por \B(una posición entre dos dígitos). ¿Por qué no simplemente insertamos prefijos en esas posiciones? Esto casi funciona, pero la diferencia es que en la solución anterior, en realidad eliminamos un marcador en cada sustitución, y eso es importante para que el proceso finalice. Sin embargo, \Bno son personajes sino solo posiciones, por lo que no se elimina nada. Nosotros podemos sin embargo detener la\Bde la coincidencia insertando en su lugar un carácter sin dígitos en este lugar. Eso convierte el límite sin palabras en un límite de palabras, que es el equivalente a eliminar el carácter marcador anterior. Y eso es lo que hace la solución de 12 bytes:

+%`\B
¶$`:

Solo para completar, aquí están los pasos individuales de procesamiento 1011, con una línea vacía después de cada paso:

1
1:0
10:1
101:1

1
1:0
1
1:0:1
1
1:0
10:1:1

1
1:0
1
1:0:1
1
1:0
1
1:0:1:1

Nuevamente, encontrará que el último resultado contiene exactamente 11 1s.

Como ejercicio para el lector, ¿puede ver cómo esto se generaliza fácilmente a otras bases (por unos pocos bytes adicionales por incremento en la base)?

Martin Ender
fuente
2

T-SQL, 202 bytes

DECLARE @b varchar(max)='1',@ int=1 declare @l int=LEN(@b)declare @o bigint=CAST(SUBSTRING(@b,@l,1)AS bigint)WHILE @<@l BEGIN SET @o=@o+POWER(CAST(SUBSTRING(@b,@l-@,1)*2AS bigint),@)SET @=@+1 END PRINT @o
Nelz
fuente
2

PHP, 64 bytes

foreach(str_split(strrev($argv[1]))as$k=>$v)$t+=$v*2**$k;echo$t;

Invertimos nuestro número binario, lo dividimos en sus dígitos componentes y los sumamos según la posición.

Xanderhall
fuente
2

Bash + utilidades GNU, 29 bytes

sed 's/./2*&+/g;s/.*/K&p/'|dc

E / S a través de stdin / stdout.

La sedexpresión divide el binario en cada dígito y crea una expresión RPN para dcevaluar.

Trauma digital
fuente
2

PowerShell v2 +, 55 bytes

param($n)$j=1;$n[$n.length..0]|%{$i+=+"$_"*$j;$j*=2};$i

Se siente demasiado tiempo ... Parece que no puedo jugar golf, consejos apreciados.

Explicación

param($n)$j=1;$n[$n.length..0]|%{$i+=+"$_"*$j;$j*=2};$i
param($n)$j=1;                                          # Take input $n as string, set $j=1
              $n[$n.length..0]                          # Reverses, also converts to char-array
                              |%{                  };   # Loop over that array
                                 $i+=+"$_"*$j;          # Increment by current value of $j times current digit
                                              $j*=2     # Increase $j for next loop iteration
                                                     $i # Leave $i on pipeline
                                                        # Implicit output
AdmBorkBork
fuente
2

JavaScript (ES6), 32 bytes

f=([...n])=>n+n&&+n.pop()+2*f(n)

¡La recursión salva el día otra vez! Aunque la parametrización parece un poco larga ...

ETHproducciones
fuente
Dado que es un solo "argumento", ¿ [...n]necesita estar entre paréntesis?
Cyoce
@Cyoce Desafortunadamente, sí, o JS lanza un SyntaxError.
ETHproductions
2

Mathematica, 27 13 11 bytes

Fold[#+##&]

Acepta a Listde bits como entrada (p {1, 0, 1, 1, 0}. Ej . , La representación binaria de Mathematica del número 22)

JungHwan Min
fuente
Siguiendo el comentario sobre la respuesta de Greg, ¿cómo "dividir todos los dígitos en la entrada" no es una función de conversión de base?
Martin Ender
@ MartinEnder Lo estoy usando como la Charactersfunción.
JungHwan Min
@MartinEnder En realidad, como se ve en la respuesta de @ nimi , podría aceptar una lista de 1s y 0s porque esa es la única forma de representar un número binario en Mathematica , lo que significa que no necesito IntegerDigitsen primer lugar.
JungHwan Min
Eso supone que la base 10 es la representación "natural" de un número entero. Un valor entero real no tiene una base preferida asociada (supongo que se podría decir que la forma en que está almacenado es probablemente base 256 o incluso base 2, pero eso es un detalle de implementación). El hecho de que (normalmente) usemos la base 10 para escribir literales enteros no significa que los valores enteros ya estén en la base 10.
Martin Ender
@MartinEnder @ Lynn usa el código JellyD , que hace lo mismo queIntegerDigits
JungHwan Min
2

Clojure, 114 105 63 41 bytes

V4: 41 bytes

-22 bytes gracias a @cliffroot. Dado que digites un carácter, se puede convertir a su código a través de int, luego se puede restar 48 para obtener el número real. El mapa también fue factorizado. No sé por qué parecía necesario.

#(reduce(fn[a d](+(* a 2)(-(int d)48)))%)

V3: 63 bytes

(fn[s](reduce #(+(* %1 2)%2)(map #(Integer/parseInt(str %))s)))

-42 bytes (!) Mirando otras respuestas. Mi "zipper" fue evidentemente muy ingenuo. En lugar de aumentar 2 al poder del lugar actual, luego multiplicarlo por el dígito actual y agregar el resultado al acumulador, simplemente multiplica el acumulador por 2, agrega el dígito actual y luego lo agrega al acumulador. También convirtió la función de reducción a una macro para reducir un poco.

¡Gracias a @nimi y @Adnan!

Sin golf:

(defn to-dec [binary-str]
  (reduce (fn [acc digit]
            (+ (* acc 2) digit))
          (map #(Integer/parseInt (str %)) binary-str)))

V2: 105 bytes

#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range)(reverse %)))

-9 bytes invirtiendo la cadena para que no necesite crear un rango descendente incómodo.

V1: 114 bytes

Bueno, ciertamente no estoy ganando! En mi defensa, este es el primer programa que he escrito que convierte entre bases, así que tuve que aprender cómo hacerlo. Tampoco ayuda que Math/powdevuelva un doble que requiera la conversión y Integer/parseIntno acepte un carácter, por lo que el dígito debe ajustarse antes de pasar.

#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range(dec(count %))-1 -1)%))

Comprime la cadena con un índice descendente que representa el número de lugar. Reduce sobre la lista resultante.

Sin golf:

(defn to-dec [binary-str]
  (reduce (fn [acc [place digit]]
            (let [parsed-digit (Integer/parseInt (str digit))
                  place-value (long (Math/pow 2 place))]
              (+ acc (* parsed-digit place-value))))
          0
          (map vector (range (dec (count binary-str)) -1 -1) binary-str)))
Carcigenicate
fuente
#(reduce(fn[a b](+(* a 2)(-(int b)48)))0 %)versión mejorada. Movió mapparte del código directamente a reduce, cambió el método de análisis de enteros, realizó una función externa con sintaxis lambda abreviada.
Cliffroot
¿@cliffroot intse puede usar para analizar? Eso eliminará como 10 bytes en cada desafío que he hecho aquí jajaja.
Carcigenicate
Oh, ya veo lo que estás haciendo. Tomando el código ASCII, luego restando para obtener el valor. Supongo que esto solo funcionaría en circunstancias selectas. Oh bueno, gracias por el consejo.
Carcigenicate
2

Perl, 21 19 16 + 4 = 20 bytes

-4 bytes gracias a @Dada

Ejecutar con -F -p(incluido el espacio extra después de F). Canalizar valores a la función usandoecho -n

$\+=$_+$\for@F}{

Correr como echo -n "101010" | perl -F -pE '$\+=$_+$\for@F}{'

Siento que esto es lo suficientemente diferente de la respuesta de @ Dada que merece su propia entrada.

Explicación:

-F                              #Splits the input character by character into the @F array
-p                              #Wraps the entire program in while(<>){ ... print} turning it into
while(<>){$\+=$_+$\for@F}{print}
                   for@F        #Loops through the @F array in order ($_ as alias), and...
          $\+=$_+$\             #...doubles $\, and then adds $_ to it (0 or 1)...
while(<>){              }       #...as long as there is input.
                         {print}#Prints the contents of $_ (empty outside of its scope), followed by the output record separator $\

Esto utiliza mi algoritmo personal de elección para la conversión de binario a decimal. Dado un número binario, inicie su acumulador en 0 y recorra sus bits uno por uno. Duplique el acumulador cada bit, luego agregue el bit en sí mismo a su acumulador, y terminará con el valor decimal. Funciona porque cada bit termina siendo duplicado el número apropiado de veces para su posición en función de cuántos bits más quedan en el número binario original.

Gabriel Benamy
fuente
Aún más corto:perl -F -pE '$\+=$_+$\for@F}{'
Dada
Honestamente me reí de lo corto que es esto ahora. Gracias.
Gabriel Benamy
Sí, está bastante bien, ¡bien hecho!
Dada
2

R (32 bits), 64 bytes

La entrada para la función debe darse como carácter. Las funciones básicas de R admiten enteros de 32 bits.

Entrada:

# 32-bit version (base)
f=function(x)sum(as.double(el(strsplit(x,"")))*2^(nchar(x):1-1))
f("1")
f("10")
f("101010")
f("1101111111010101100101110111001110001000110100110011100000111")

Salida:

> f("1")
[1] 1
> f("10")
[1] 2
> f("101010")
[1] 42
> f("1101111111010101100101110111001110001000110100110011100000111")
[1] 2.016121e+18

R (64 bits), 74 bytes

La entrada para la función debe darse como carácter. El paquetebit64 debe usarse para enteros de 64 bits.

Entrada:

# 64-bit version (bit64)
g=function(x)sum(bit64::as.integer64(el(strsplit(x,"")))*2^(nchar(x):1-1))
g("1")
g("10")
g("101010")
g("1101111111010101100101110111001110001000110100110011100000111")

Salida:

> g("1")
integer64
[1] 1
> g("10")
integer64
[1] 2
> g("101010")
integer64
[1] 42
> g("1101111111010101100101110111001110001000110100110011100000111")
integer64
[1] 2016120520371234567
djhurio
fuente
2
Puede hacer: en el(strsplit(x,""))lugar de strsplit(x,split="")[[1]]guardar un par de bytes.
Billywob
¡Muchas gracias! Especialmente para la elfunción, no lo sabía.
djhurio
2

Dyalog APL , 12 bytes

(++⊢)/⌽⍎¨⍞

obtener entrada de cadena

⍎¨ convierte cada caracter a numero

marcha atrás

(... )/inserte la siguiente función entre los números

++⊢ la suma de los argumentos más el argumento correcto


ngn afeitado 2 bytes.

Adán
fuente
1

k, 8 bytes

El mismo método que la respuesta anterior de Haskell.

{y+2*x}/

Ejemplo:

{y+2*x}/1101111111010101100101110111001110001000110100110011100000111b
2016120520371234567
skeevey
fuente