Conversor de binário para decimal

32

Conversor de binário para decimal

Tanto quanto posso ver, não temos um desafio simples de conversão de binário para decimal.


Escreva um programa ou função que pega um número inteiro binário positivo e gera seu valor decimal.

Você não tem permissão para usar nenhuma função de conversão básica embutida. Funções de número inteiro para decimal (por exemplo, uma função que se transforma 101010em [1, 0, 1, 0, 1, 0]ou "101010") são isentas desta regra e, portanto, são permitidas.

Regras:

  • O código deve suportar números binários até o valor numérico mais alto suportado pelo seu idioma (por padrão)
  • Você pode optar por ter zeros à esquerda na representação binária
  • A saída decimal pode não ter zeros à esquerda.
  • Os formatos de entrada e saída são opcionais, mas não pode haver separadores entre dígitos. (1,0,1,0,1,0,1,0)não é um formato de entrada válido, mas ambos 10101010e (["10101010"])são.
    • Você deve pegar a entrada na direção "normal". não 1110é .147

Casos de teste:

1
1

10
2

101010
42

1101111111010101100101110111001110001000110100110011100000111
2016120520371234567

Este desafio está relacionado com alguns outros desafios, por exemplo este , este e este .

Stewie Griffin
fonte
Relacionados
mbomb007
A saída precisa ser não assinada ou pode ser assinada? Além disso, se o meu idioma alternar automaticamente entre números inteiros de 32 e 64 bits, dependendo do tamanho do valor, a saída poderá ser assinada nos dois intervalos? Por exemplo: existem dois valores binários que serão convertidos em decimal -1( 32 1'se 64 1's)
ordenado
Além disso, a saída pode ser flutuante? Ela precisa ser um número inteiro?
Carcigenicate
@Carcigenicate Deve ser um número inteiro, mas pode ser de qualquer tipo de dados. Contanto que round(x)==xvocê esteja bem :) 2.000é aceito como saída 10.
Stewie Griffin
Oh querida. Obrigado.
Carcigenicate

Respostas:

56

Gelatina , 5 bytes

DḤ+¥/

Experimente online!

Explicação

insira a descrição da imagem aqui

O elenco

  • Dé uma mônada (função de argumento único): dígitos, transformando 1234- se em [1, 2, 3, 4].

  • é uma mônada que dobra seu único argumento.

  • + é uma díade (função de dois argumentos) que adiciona seus argumentos esquerdo e direito.

A partir daí, fica um pouco complicado.

Aqui está o que acontece no momento da análise

  • D,, e +são lidos. A corrente parece [D, Ḥ, +].

  • Os próximos dois caracteres são rápidos , que agem como operadores de postfix de tempo de análise nos links (funções) que lemos até agora.

  • Quando ¥é lido, os dois últimos links são exibidos e substituídos por um link que age como a díade formada pela composição deles. Então agora a cadeia parece [D, dyad(Ḥ+)].

  • Quando /é lido, o último link (que deveria ser uma díade) é exibido e substituído por uma mônada que dobra usando essa díade (intuitivamente: f/pega uma lista, substitui as vírgulas nela fe avalia o resultado).

  • A cadeia final parece [D, fold(dyad(Ḥ+))]duas mônadas.

Aqui está o que acontece em tempo de execução

  • A entrada (um número) é implicitamente lida no valor de trabalho (digamos 101010).

  • Dé executado, substituindo o valor de trabalho por seus dígitos ( [1,0,1,0,1,0]).

  • fold(dyad(Ḥ+))é executado, substituindo o valor de trabalho por 1∗0∗1∗0∗1∗0, onde está a díade Ḥ+.

Então, o que x∗yavaliar para?

  • Em uma definição diádica, o valor de trabalho é inicialmente o argumento esquerdox ,.

  • , a mônada dupla , dobra esse valor. O valor de trabalho é agora 2x.

  • +, a díade mais , carece de um argumento correto, então isso é um gancho : um padrão sintático especial em que o argumento correto dessa díade é injetado +. Isso gera 2x + ycomo o valor final de trabalho, que é retornado.

Portanto, toda a expressão é avaliada 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
fonte
10
Suas explicações estão ficando cada vez melhores :-)
Luis Mendo
2
Heh, eu acho que você faz isso a partir de agora? Isso é incrível, +1.
Erik the Outgolfer
4
Eu acho que este é o primeiro pedaço de geléia que eu já entendi. +1!
Azul
Bravo. Na verdade, eu entendo o que inicialmente pensei que era apenas uma bagunça de personagens aparentemente aleatórios. Explicação maravilhosa.
swinefish
11
O @Mark Jelly tem sua própria página de códigos para fazer com que os programas pareçam incríveis, legíveis, mas os programas também podem ser apenas seqüências de caracteres.
Lynn
20

Python 2, 49 37 31 30 bytes

Agora, isso terá um número binário em uma representação decimal, pois o Python pode lidar com números inteiros arbitrariamente grandes.

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

graças ao xnor por salvar um byte :)

A maneira mais fácil de ver como isso funciona é ver uma fórmula básica para converter binário em 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 é uma maneira 'padrão' de converter. Você pode expandir a terceira linha da seguinte maneira:

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

E é essencialmente isso que o método recursivo que eu fiz está fazendo.

Soluções alternativas que tive:

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
fonte
6
Você pode fazer n%5ou em n%2vez de n%10.
Xnor
@ xnor Ah, não sei como eu perdi isso! Obrigado :)
Kade
12

05AB1E , 6 bytes

Código:

$¦v·y+

Para a explicação, vamos dar o exemplo 101010 . Começamos com o número 1 (que é representado pelo primeiro dígito). Depois disso, temos dois casos:

  • Se o dígito for 0 , multiplique o número por 2.
  • Se o dígito for 1 , multiplique o número por 2 e adicione 1.

Portanto, para o caso 101010 , o seguinte é calculado:

  • 1 01010, comece com o número 1 .
  • 1 0 1010, multiplique por dois, resultando em 2 .
  • 10 1 010, multiplique por dois e adicione um, resultando em 5 .
  • 101 0 10, multiplique por dois, resultando em 10 .
  • 1010 1 0, multiplique por dois e adicione um, resultando em 21 .
  • 10101 0 , multiplique por dois, resultando em 42 , que é o resultado desejado.

Explicação do 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)

Usa a codificação CP-1252 . Experimente online!

Adnan
fonte
Agradável! (não funciona para 0 embora eu só notei)
Emigna
@ Emigna Sim, felizmente, seu código só precisa funcionar para números binários positivos.
Adnan
Nem vi essa parte. Muito bom então :)
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 os sinalizadores de compilação -XOverloadedStrings, -XOverlappingInstancese -XFlexibleInstances.

O desafio tem um formato de E / S complicado , porque depende muito de como os tipos de dados são expressos no código-fonte. Minha primeira versão (16 bytes), a saber

foldl1((+).(2*))

pega uma lista de números inteiros, por exemplo, [1,0,1,0,1,0]e foi declarada inválida porque as listas literais de Haskell têm ,entre os elementos. Listas em si não são proibidas. Na minha nova versão, uso a mesma função, agora chamada f, mas sobrecarrego "Citar sequências de caracteres incluídas". A função ainda pega uma lista de números inteiros, como você pode ver na anotação de tipo [Int] -> Int, mas as listas com números inteiros de um dígito agora podem ser escritas como "1234", por exemplo,

f "101010"

que avalia como 42. Haskell azarado, porque o formato da lista nativa não se encaixa nas regras de desafio. Btw, f [1,0,1,0,1,0]ainda funciona.

nimi
fonte
2
Infelizmente, uma lista não é uma entrada válida.
Jonathan Allan
@ JonathanAllan: Por quê? E se sim, como deve receber alguma contribuição? Em Haskell, uma string é apenas uma lista de caracteres.
N /
Não sei por que ... mas perguntei sobre isso desde o início e uma edição foi feita para adicionar " (1,0,1,0,1,0,1,0)não é um formato de entrada válido, mas ambos 10101010e (["10101010"])são". além disso, um comentário sugere que a matriz de caracteres é aceitável se é assim que uma entrada de string é interpretada.
Jonathan Allan
11
@ JonathanAllan: qualquer "número inteiro binário" (a entrada que precisamos pegar) é inerentemente separado, é uma sequência de potências de 2. A restrição é sobre separadores explícitos (entre os dígitos) e não sobre separação. De alguma forma eu tenho que pegar dígitos separados.
nimi
2
Op aqui: se é possível inserir 10101010, "10101010"ou algo semelhante e fazê-lo funcionar, o envio é válido. Você pode chamá-lo de uma string, lista, número inteiro ou o que seja. Introduzir [1][0][1][0]ou [1,0,1,0]não está bem. Basicamente, deve ser possível apenas acertar vários zeros e zeros em algum lugar. Isso está claro?
Stewie Griffin
7

Retina, 15 bytes

Converte de binário em unário e unário em decimal.

1
01
+`10
011
1

Experimente online

mbomb007
fonte
Você não tem permissão para usar nenhuma função de conversão básica embutida. ~ OP
Roman Gräf
10
@ RomanGräf Não há nenhum. Eu estava simplesmente descrevendo o processo da minha solução.
mbomb007
7

PHP, 44 bytes

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

Eu poderia jurar que já vi essa pergunta antes. Mas, bem.

Lê o número da esquerda para a direita, muda para a esquerda e adiciona o bit atual.

Titus
fonte
7

JavaScript (ES6), 33 31 bytes

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

Edit: Mais curto, mas menos doce: 2 bytes salvos graças a @ETHproductions.

Neil
fonte
Como costuma ser o caso, .mapé mais curto:s=>[...s].map(c=>+c+r+r,r=0)|r
ETHproductions
@ETHproductions Como sua função retorna algo diferente de 0?
7116 Neil
Desculpe, deveria sers=>[...s].map(c=>r+=+c+r,r=0)|r
ETHproductions
7

Labirinto , 17 15 bytes

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

Experimente online!

Imagem do código

Labirinto é uma linguagem bidimensional baseada em pilha. No labirinto, a execução do código segue o caminho do código como um labirinto, com espaços atuando como paredes e começando no caractere não espacial do canto superior esquerdo. O fluxo do código é determinado pelo sinal da parte superior da pilha. Como a pilha possui zeros implícitos na parte inferior, as quatro primeiras instruções ( -+:+) não têm efeito.

Loop começando no ,

  • , Empurre o valor do código ascii do próximo caractere de entrada até a parada da pilha ou empurre -1 se EOF.
  • _48 empurra 48 para o topo da pilha
  • -Pop y, pop x, empurre x-y. As instruções anteriores têm o efeito de subtrair 48 da entrada produzindo 0 para "0" e 1 para "1".
  • +Pop y, pop x, empurre x+y.
  • : Duplique a parte superior da pilha
  • + Esta e a instrução anterior têm o efeito de multiplicar o valor atual por 2

Portanto, a parte circular do código, na verdade, multiplica o número atual por 2 e adiciona 1 ou 0, dependendo se o caractere 1 ou 0 foi inserido.

Rabo

Se a parte superior da pilha for negativa (significando que o EOF foi encontrado), o código vira à esquerda no cruzamento (indo em direção ao ponto e vírgula).

  • `` Negue o topo da pilha para obter 1
  • ) Icrementar o topo da pilha para obter 2
  • /Pop y, pop x, pressione x / y (divisão inteira). Isso tem o efeito de desfazer o último *2do loop.
  • !Saída a representação inteira da parte superior da pilha. Nesse ponto, o programa muda porque atinge um beco sem saída e sai com um erro porque tenta dividir por zero.

Agradeço a @Martin Ender por me salvar 2 bytes (e por me ensinar a pensar melhor em Labyrinth).

Robert Hickman
fonte
Em vez de _48-você pode simplesmente fazer, #%mas infelizmente não vejo como isso pode ajudar na contagem de bytes.
27530 Martin Ender #
Você pode salvar um byte em `)vez de no ;_2entanto.
Martin Ender
@ MartinEnder, eu não entendo o seu comentário sobre #%. Você pode explicar como isso funciona como um substituto para _48-converter de ascii para int. Obrigado pela )dica. Eu vou fazer essa mudança.
Robert Hickman
Nesse ponto do seu programa, sempre existem dois valores na pilha, portanto, #é apenas uma abreviação de _2. Embora _2%não seja um método geral de conversão de ASCII para inteiro, ele funciona aqui porque você está interessado apenas nos dois primeiros dígitos como entrada possível. Uma alternativa seria _1&(já que o módulo 2 simplesmente extrai o bit menos significativo).
Martin Ender
Oh. Isso é brilhante. Mas sim, não tenho certeza de como usar essa substituição ( #%) para reduzir o código em geral.
Robert Hickman
6

Flak cerebral , 46 , 28 bytes

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

Experimente online!

Muitos bytes salvos graças ao @Riley!

Como a quebra cerebral não pode receber entrada binária, a entrada é uma lista de '0' e '1'.

Explicação:

#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
fonte
Ame a explicação! Tão difícil de ler cérebro-Flak sem ele :)
Emigna
2
^. Nem consigo ler meus próprios programas se não me deixar alguns comentários.
Riley #
Você pode reduzi-lo para 32 bytes, livrando-se do todo, se parte, e para a etapa "adicionar número a outra pilha", basta adicioná-lo ao (outra pilha) * 2. ([]){({}[()]<({}<>({}){})><>)}<>
Riley
E você pode salvar outros 4 clicando no início e pressionando a altura novamente no final. ([]){{}({}<>({}){})<>([])}<>
Riley
@Riley Oh meu Deus, isso é genial. Muito obrigado!
DJMcMayhem
6

Java, 84 79 46 48 bytes

  • Versão 3.1

Alterado para long/ 48 bytes:

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

Jogou golfe / 46 bytes:

s->{int x=0;for(char c:s)x=c-48+x*2;return x;}
  • Versão 2.0

Graças 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;}
  • Versão 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
fonte
11
acho que eu deveria ter feito uma solução iterativa. lulz. bom trabalho
Puxão
O seu tipo de entrada List <Character> ou String? Se for o último, eu não sabia que o Java8 poderia fazer isso! Se é o primeiro, isso é permitido pelo desafio?
Poke
sdeveria ser char[]. Espero que isso seja permitido ...
Roman Gräf /
Qual é o tipo de retorno aqui? Eu acho que deve ser longo porque "O código deve suportar números binários até o valor numérico mais alto suportado pela sua linguagem" pelo OP, mas para valores menores eu acho que ele retorna um int
Poke
11
Provavelmente bem no tipo de entrada por isso . Pode querer levar o hit de 2 bytes para a saída imo
Poke
4

Befunge-98, 12 bytes

2j@.~2%\2*+

Experimente online!

Lê um caractere de cada vez da entrada, converte-o para 0 ou 1 assumindo seu valor módulo 2 (0 é char (48), 1 é char (49)) e, em seguida, usa o algoritmo usual de duplicar o valor atual e adicionar o valor novo dígito de cada vez.

Bônus: Isso funciona com qualquer tipo de string de entrada. Estou tentando há algum tempo encontrar alguma combinação engraçada de entrada-> saída, mas não consegui produzir nada (infelizmente, "resposta" = 46). Você pode?

Leo
fonte
RI MUITO. Eu estava jogando o mesmo jogo com a minha resposta. O número mais interessante que pude gerar foi 666 .
James Holderness
Agradável! Eu não tinha conseguido encontrar encaixe qualquer coisa para 666: D Seria muito mais fácil se a capitalização teve um efeito sobre os valores ...
Leo
@ James Holderness - eu tenho feito o mesmo e só encontrei 'o próximo ano' para trazer de volta 366, o seu é realmente bom.
Teal pelican
4

Javascript (ES7) 41 40 36 bytes

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

pega uma string como entrada

Raspou um byte graças à 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
fonte
11
A associatividade da direita para a esquerda **é estranha, mas é um bom trabalho usá-la aqui. 1<<b.lengthfaria a mesma coisa, mas exigiria parênteses para não ser analisado como (c*1)<<(b.length+...). Eu acho que você pode salvar um byte substituindo b[0]por b+b( veja aqui ).
ETHproductions
4

C # 6, 85 37 36 bytes

long b(long n)=>n>0?n%2+2*b(n/10):0;
  • Agradecemos a Kade por salvar 41 bytes!
  • Mudar para C # 6 salvou outros 7 bytes.
Yytsi
fonte
Talvez isso possa fornecer alguma inspiração? ;)
Kade
@Kade Sim, obrigado! Eu estava olhando para a resposta Python que utiliza a mesma técnica no mesmo momento que você vinculado que: DI pode ficar ainda mais curto com C # 6.
Yytsi
3

05AB1E , 7 bytes

RvNoy*O

Experimente online!

Explicação

R         # reverse input
 v     O  # sum of
  No      # 2^index
     *    # times
    y     # digit
Emigna
fonte
3

C, 53

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

Igual à minha resposta javascript

Ideona de teste

edc65
fonte
Você pode salvar 4 bytes declarando ve ccomo variáveis ​​globais (embora seja necessário alterar o nome de v, já que ele já é o nome da função) assim:w=0;c;v(char*s){while(c=*s++)w+=w+c-48;return w;}
Steadybox 6/16
@Steadybox que poderia ser w,c;, mas eu não quero usar globais quando a resposta é uma função (mesmo em código-golf)
edc65
O @Steadybox Globals também assume como padrão 0, para que você possa largar o =0.
precisa saber é
3

Perl, 25 bytes

-3 bytes graças a @Dom Hastings.

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

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

Para executá-lo:

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

Explicações:

$\|=$&<<$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
fonte
3

Pushy , 10 bytes

Toma entrada como uma lista de 0/1 na linha de comando: $ pushy binary.pshy 1,0,1,0,1,0.

L:vK2*;OS#

O algoritmo realmente mostra a beleza de ter uma segunda pilha:

            \ 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

Esse método funciona porque a pilha será duplicada stack length - nvezes antes de atingir o número n, que é despejado na segunda pilha para mais tarde. Aqui está a aparência do processo para 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
fonte
3

Matlab, 30 bytes

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

O último caso de teste possui erros de arredondamento (por causa de double), portanto, se você precisar de precisão total:

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

com 47 bytes.

Jonas
fonte
Não posso testar isso, mas acredito @(x)sum(2.^(find(flip(x)-48)-1))que dará o resultado correto para todos os casos por 32 bytes. flipfunciona como fliplrse xé unidimensional.
Stewie Griffin
Ótima solução! Também encontrei o erro de arredondamento, obrigado pela correção. Qual é o formato de x? Chamar flip ou fliplr em um número apenas retorna esse número.
MattWH
x é a string binária, então chame-a com f=@(x)..; f('1111001010').
Jonas
3

Retina , 12 bytes

A contagem de bytes assume a codificação ISO 8859-1.

+%`\B
¶$`:
1

Experimente online!

Solução alternativa:

+1`\B
:$`:
1

Explicação

Provavelmente será mais fácil explicar isso com base na minha versão antiga, menos golfe, e depois mostrar como a reduzi. Eu costumava converter binário em decimal como este:

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

A única maneira sensata de construir um número decimal no Retina é contando as coisas (porque o Retina possui alguns recursos que permitem imprimir um número decimal representando um valor). Então, realmente, a única abordagem possível é converter o binário em unário e, em seguida, contar o número de dígitos unários. A última linha faz a contagem; portanto, os quatro primeiros convertem o binário em unário.

Como fazemos isso? Em geral, para converter de uma lista de bits em um número inteiro, inicializamos o resultado 0e depois passamos pelos bits do mais para o menos significativo, o dobro do valor que já temos e adicionamos o bit atual. Por exemplo, se o número binário for 1011, calcularíamos realmente:

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

Onde marquei os bits individuais para maior clareza.

O truque para fazer isso em unário é a) que dobrar significa repetir o número eb) já que estamos contando os 1s no final, nem precisamos distinguir 0s e 1s no processo. Isso ficará mais claro em um segundo.

O que o programa faz é adicionar primeiro uma vírgula no início como marcador de quanto da entrada já processamos:

^
,

À esquerda do marcador, teremos o valor que estamos acumulando (que foi corretamente inicializado para a representação unária de zero) e à direita do valor será o próximo bit a ser processado. Agora aplicamos a seguinte substituição em um loop:

,(.)
$`$1,

Apenas olhando ,(.)e $1,, isso move o marcador um pouco para a direita a cada vez. Mas também inserimos $`, que é tudo à frente do marcador, ou seja, o valor atual, que estamos dobrando. Aqui estão as etapas individuais ao processar a entrada 1011, onde eu marquei o resultado da inserção $`acima de cada linha (ela está vazia na primeira etapa):

,1011

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

Você verá que retivemos e dobramos o zero junto com todo o resto, mas, como os desconsideramos no final, não importa com que frequência os duplicamos, desde que o número de 1s seja corrigir. Se você os contar, existem 11, exatamente o que precisamos.

Portanto, isso deixa a questão de como jogar isso em golfe até 12 bytes. A parte mais cara da versão de 18 bytes é usar o marcador. O objetivo é se livrar disso. Nós realmente queremos dobrar o prefixo de cada bit, então uma primeira idéia pode ser a seguinte:

.
$`$&

O problema é que essas substituições ocorrem simultaneamente, portanto, o primeiro bit não é duplicado para cada bit, mas é copiado uma vez de cada vez. Para entrada 1011, obteríamos (marcando o inserido $`):

 _ __ ___
1101011011

Ainda precisamos processar a entrada recursivamente para que o primeiro prefixo duplicado seja duplicado novamente pelo segundo e assim por diante. Uma idéia é inserir marcadores em todos os lugares e substituí-los repetidamente pelo prefixo:

\B
,
+%`,
¶$`

Depois de substituir cada marcador pelo prefixo pela primeira vez, precisamos lembrar onde estava o início da entrada; portanto, inserimos feeds de linha também e usamos a %opção para garantir que o próximo $`aponte apenas o feed de linha mais próximo.

Isso funciona, mas ainda é muito longo (16 bytes ao contar 1s no final). Que tal mudar as coisas? Os locais onde queremos inserir marcadores são identificados por \B(uma posição entre dois dígitos). Por que simplesmente não inserimos prefixos nessas posições? Isso quase funciona, mas a diferença é que, na solução anterior, removemos um marcador em cada substituição, e isso é importante para encerrar o processo. No entanto, o \Bpersonagem não é apenas uma posição, então nada é removido. No entanto, podemos parar o\Bda correspondência inserindo um caractere não dígito neste local. Isso transforma o limite de não palavra em um limite de palavra, o que equivale a remover o caractere marcador anteriormente. E é isso que a solução de 12 bytes faz:

+%`\B
¶$`:

Apenas para completar, aqui estão as etapas individuais do processamento 1011, com uma linha vazia após cada etapa:

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

Novamente, você verá que o último resultado contém exatamente 11 1s.

Como um exercício para o leitor, você pode ver como isso se generaliza facilmente para outras bases (por alguns bytes adicionais por incremento na base)?

Martin Ender
fonte
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
fonte
2

PHP, 64 bytes

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

Invertemos nosso número binário, dividimos em seus dígitos componentes e os somamos com base na posição.

Xanderhall
fonte
2

Utilitários Bash + GNU, 29 bytes

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

E / S via stdin / stdout.

A sedexpressão divide o binário em cada dígito e cria uma expressão RPN para dcavaliação.

Trauma Digital
fonte
2

PowerShell v2 +, 55 bytes

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

Parece muito tempo ... Não consigo jogar golfe - dicas apreciadas.

Explicação

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
fonte
2

JavaScript (ES6), 32 bytes

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

A recursão salva o dia novamente! Embora a parametrização pareça um pouco longa ...

ETHproductions
fonte
Como é um "argumento" único, [...n]precisa estar entre parênteses?
Cyoce
@ Cyy Infelizmente, sim, ou JS lança um SyntaxError.
ETHproductions
2

Mathematica, 27 13 11 bytes

Fold[#+##&]

Aceita um Listde bits como entrada (por exemplo {1, 0, 1, 1, 0}- representação binária do número do Mathematica22 )

JungHwan Min
fonte
Seguindo o comentário da resposta de Greg, como "dividir todos os dígitos da entrada" não é uma função de conversão básica?
Martin Ender
@MartinEnder Estou usando como a Charactersfunção.
JungHwan Min
@MartinEnder Na verdade, como visto na resposta de @ nimi , eu poderia aceitar uma lista de 1s e 0s porque essa é a única maneira de representar um número binário no Mathematica , o que significa que não preciso IntegerDigitsem primeiro lugar.
JungHwan Min
Isso pressupõe que a base 10 é a representação "natural" de um número inteiro. Um valor inteiro real não tem base preferencial anexada a ele (acho que você poderia dizer que a maneira como ele é armazenado é provavelmente a base 256 ou talvez até a base 2, mas esse é um detalhe da implementação). Só porque nós (normalmente) base de uso 10 para escrever inteiro literais lá não significa inteiros valores já estão na base 10.
Martin Ender
@MartinEnder @ O código Jelly de Lynn usa D, o que faz a mesma coisa que:IntegerDigits
JungHwan Min
2

Clojure, 114 105 63 41 bytes

V4: 41 bytes

-22 bytes graças a @cliffroot. Como digité um caractere, ele pode ser convertido em seu código via e int, em seguida, 48 são subtraídos para obter o número real. O mapa também foi fatorado. Não sei por que parecia necessário.

#(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 (!) Espiando outras respostas. Meu "fechamento" era evidentemente muito ingênuo. Em vez de elevar 2 à potência do local atual, multiplicando-o pelo dígito atual e adicionando o resultado ao acumulador, ele apenas multiplica o acumulador por 2, adiciona o dígito atual e o adiciona ao acumulador. Também converteu a função de redução em uma macro para se barbear um pouco.

Obrigado a @nimi e @Adnan!

Ungolfed:

(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, invertendo a string para que eu não precise criar um intervalo descendente estranho.

V1: 114 bytes

Bem, certamente não estou ganhando! Em minha defesa, este é o primeiro programa que eu já escrevi que se converte entre bases, então eu tive que aprender como fazê-lo. Também não ajuda que Math/powretorne um dobro que exija a conversão de e Integer/parseIntnão aceite um caractere; portanto, o dígito precisa ser quebrado antes da passagem.

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

Fecha a string com um índice decrescente que representa o número do local. Reduz sobre a lista resultante.

Ungolfed:

(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)))
Carcinigenicado
fonte
#(reduce(fn[a b](+(* a 2)(-(int b)48)))0 %)versão melhorada. Moveu mapparte do código diretamente para reduce, alterou o método de análise de números inteiros, criou funções externas com sintaxe abreviada de lambda.
Cliffroot 6/12/16
@cliffroot intpode ser usado para analisar !? Isso vai bater 10 bytes em todos os desafios que eu fiz aqui, rs.
Carcigenicate
Oh, eu vejo o que você está fazendo. Tomando o código ascii e subtraindo para obter o valor. Eu acho que isso só funcionaria em circunstâncias selecionadas. Oh bem, obrigado pela dica.
Carcigenicate
2

Perl, 21 19 16 + 4 = 20 bytes

-4 bytes graças a @Dada

Corra com -F -p(incluindo o espaço extra após o F). Conduza os valores para a função usandoecho -n

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

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

Eu sinto que isso é suficientemente diferente da resposta da @ Dadá que merece sua própria entrada.

Explicação:

-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 $\

Isso usa meu algoritmo pessoal de escolha para conversão de binário em decimal. Dado um número binário, inicie seu acumulador em 0 e repare os bits um a um. Dobre o acumulador a cada bit, adicione o próprio bit ao acumulador e você terá o valor decimal. Funciona porque cada bit acaba dobrando o número apropriado de vezes para sua posição, com base em quantos bits restam no número binário original.

Gabriel Benamy
fonte
Ainda mais curto:perl -F -pE '$\+=$_+$\for@F}{'
Dada
Eu honestamente ri de como isso é curto agora. Obrigado.
Gabriel Benamy
Sim, é bem arrumado, bem feito!
Dada
2

R (32 bits), 64 bytes

A entrada para a função deve ser fornecida como caractere. As funções básicas do R suportam números inteiros 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")

Saída:

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

R (64 bits), 74 bytes

A entrada para a função deve ser fornecida como caractere. O pacote bit64deve ser usado para números inteiros 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")

Saída:

> g("1")
integer64
[1] 1
> g("10")
integer64
[1] 2
> g("101010")
integer64
[1] 42
> g("1101111111010101100101110111001110001000110100110011100000111")
integer64
[1] 2016120520371234567
djhurio
fonte
2
Você pode fazer: em el(strsplit(x,""))vez de strsplit(x,split="")[[1]]salvar alguns bytes.
Billywob
Muito obrigado! Especialmente para a elfunção - eu não estava ciente disso.
djhurio
2

Dyalog APL , 12 bytes

(++⊢)/⌽⍎¨⍞

obter entrada de string

⍎¨ converter cada caractere em número

marcha ré

(... )/insira a seguinte função entre os números

++⊢ a soma dos argumentos mais o argumento certo


ngn raspou 2 bytes.

Adão
fonte
1

k, 8 bytes

O mesmo método da resposta de Haskell acima.

{y+2*x}/

Exemplo:

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