Binary to decimal converter
Jelly, 5 bytes
DḤ+¥/
Try it online!
Explanation
The cast
D
is a monad (single argument function): digits, turning1234
into[1, 2, 3, 4]
.Ḥ
is a monad that doubles its single argument.+
is a dyad (two argument function) that adds its left and right arguments.
From there, it gets a little tricky.
Here’s what happens at parse time
D
,Ḥ
, and+
are read. The chain looks like[D, Ḥ, +]
.The next two characters are quicks, which act like parse-time postfix operators on the links (functions) we've read so far.
When
¥
is read, the last two links get popped and replaced by a link that acts like the dyad formed by composing them. So now the chain looks like[D, dyad(Ḥ+)]
.When
/
is read, the last link (which ought to be a dyad) gets popped and replaced by a monad that folds using this dyad (intuitively:f/
takes a list, replaces the commas in it withf
, and evaluates the result.)The final chain looks like
[D, fold(dyad(Ḥ+))]
, two monads.
Here's what happens at run time
Input (a number) is implicitly read into the working value (say,
101010
).D
is executed, replacing the working value with its digits ([1,0,1,0,1,0]
).fold(dyad(Ḥ+))
is executed, replacing the working value with1∗0∗1∗0∗1∗0
, where∗
is the dyadḤ+
.
So what does x∗y
evaluate to?
In a dyadic definition, the working value is initially the left argument,
x
.Ḥ
, the double monad, doubles this value. The working value is now2x
.+
, the plus dyad, lacks a right argument, so this is a hook: a special syntactical pattern where the right argument of this dyad gets injected into+
. This yields2x + y
as the final working value, which is returned.
So the whole expression evaluates to:
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
Python 2, 49 37 31 30 Bytes
Now this will take a binary number in a decimal representation, since Python can handle arbitrarily large integers.
b=lambda n:n and n%2+2*b(n/10)
thanks to xnor for saving a byte :)
The easiest way to see how this works is by seeing a basic formula for converting binary to 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
This is a 'standard' way of converting. You can expand the third line like so:
= ((((1*2 + 0)*2 + 1)*2 + 0)*2 + 1)*2 + 0
And this is essentially what the recursive method I've made is doing.
Alternate solutions I had:
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))
05AB1E, 6 bytes
Code:
$¦v·y+
For the explantion, let's take the example 101010. We start with the number 1 (which is represented by the first digit). After that, we have two cases:
- If the digit is a 0, multiply the number by 2.
- If the digit is a 1, multiply the number by 2 and add 1.
So for the 101010 case, the following is calculated:
- 101010, start with the number 1.
- 101010, multiply by two, resulting into 2.
- 101010, multiply by two and add one, resulting into 5.
- 101010, multiply by two, resulting into 10.
- 101010, multiply by two and add one, resulting into 21.
- 101010, multiply by two, resulting into 42, which is the desired result.
Code explanation:
$ # 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)
Uses the CP-1252 encoding. Try it online!