Binary to decimal converter
As far as I can see, we don't have a simple binary to decimal conversion challenge.
Write a program or function that takes a positive binary integer and outputs its decimal value.
You are not allowed to use any builtin base conversion functions. Integer-to-decimal functions (e.g., a function that turns 101010 into [1, 0, 1, 0, 1, 0] or "101010") are exempt from this rule and thus allowed.
Rules:
- The code must support binary numbers up to the highest numeric value your language supports (by default)
- You may choose to have leading zeros in the binary representation
- The decimal output may not have leading zeros.
- Input and output formats are optional, but there can't be any separators between digits.
(1,0,1,0,1,0,1,0)is not a valid input format, but both10101010and(["10101010"])are.- You must take the input in the "normal" direction.
1110is14not7.
- You must take the input in the "normal" direction.
Test cases:
1
1
10
2
101010
42
1101111111010101100101110111001110001000110100110011100000111
2016120520371234567
This challenge is related to a few other challenges, for instance this, this and this.
95 Answers 95
Jelly, 5 bytes
DḤ+\/
Explanation
The cast
Dis a monad (single argument function): digits, turning1234into[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).Dis 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 + yas the final working value, which is returned.
So the whole expression evaluates to:
1∗0∗1∗0∗1∗0 =わ ×ばつ(×ばつ(×ばつ(×ばつ(×ばつ1+0)+1)+0)+1)+0
= 32×ばつかける1 +たす 16×ばつかける0 +たす 8×ばつかける1 +たす 4×ばつかける0 +たす 2×ばつかける1 +たす 1×ばつかける0
=わ 42
-
12\$\begingroup\$ Your explanations are getting better and better :-) \$\endgroup\$Luis Mendo– Luis Mendo2016年12月06日 01:22:38 +00:00Commented Dec 6, 2016 at 1:22
-
2\$\begingroup\$ Heh, I guess you do it from now on? That's awesome, +1. \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2016年12月06日 12:57:36 +00:00Commented Dec 6, 2016 at 12:57
-
5\$\begingroup\$ I think this is the first piece of Jelly I've ever understood. +1! \$\endgroup\$Blue– Blue2016年12月07日 19:59:24 +00:00Commented Dec 7, 2016 at 19:59
-
\$\begingroup\$ Bravo. I actually understand what I initially thought was just a mess of seemingly random characters. Wonderful explanation. \$\endgroup\$swinefish– swinefish2016年12月08日 07:18:47 +00:00Commented Dec 8, 2016 at 7:18
-
1\$\begingroup\$ @Mark Jelly has its own codepage to make the programs look, ahem, readable, but the programs could as well just be bytestrings. \$\endgroup\$lynn– lynn2016年12月10日 13:10:54 +00:00Commented Dec 10, 2016 at 13:10
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!
-
\$\begingroup\$ Nice one! (doesn't work for 0 though I just noticed) \$\endgroup\$Emigna– Emigna2016年12月05日 20:07:42 +00:00Commented Dec 5, 2016 at 20:07
-
\$\begingroup\$ @Emigna Yep, luckily your code only needs to work for positive binary numbers. \$\endgroup\$Adnan– Adnan2016年12月05日 20:08:23 +00:00Commented Dec 5, 2016 at 20:08
-
\$\begingroup\$ Didn't even see that part. Very nice then :) \$\endgroup\$Emigna– Emigna2016年12月05日 20:09:22 +00:00Commented Dec 5, 2016 at 20:09
Turing Machine Code, 232 bytes
(Using, as usual, the morphett.info rule table syntax)
While only 40 bytes shorter than the existing solution, that solution uses 12 states whereas this one only uses 4:
0 1 0 l 0
0 0 . r 0
0 . 1 l 0
0 _ I r 1
0 I 2 r 0
0 2 3 r 0
0 3 4 r 0
0 4 5 r 0
0 5 6 r 0
0 6 7 r 0
0 7 8 r 0
0 8 9 r 0
0 9 X l 0
0 X O r 0
0 O I r 0
1 _ _ l 2
1 * * * 0
2 * _ l 3
3 O 0 l 3
3 I 1 l 3
3 . _ l 3
3 _ * * halt
3 * * l 3
Try it online!
The interesting computation (ie. base-conversion) actually just takes place in state 0. This state decrements the binary number one-by-one, each time incrementing a decimal counter.
Due to naming clashes of the number-bases' alphabets, I make use of O and I during the conversion. State 1,2,3 only take care of cleaning the tape, converting the symbols O → 0 and I → 1 and finally halting the machine.
-
3\$\begingroup\$ Welcome to Code Golf, and nice first answer! \$\endgroup\$2021年03月15日 15:02:34 +00:00Commented Mar 15, 2021 at 15:02
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 for the compile flags -XOverloadedStrings, -XOverlappingInstances and -XFlexibleInstances.
The challenge has some cumbersome IO format, because it heavily depends on how data types are expressed in the source code. My first version (16 bytes), namely
foldl1((+).(2*))
takes a list of integers, e.g. [1,0,1,0,1,0] and was declared invalid because literal Haskell lists happen to have , between the elements. Lists per se are not forbidden. In my new version I use the very same function, now named f, but I overload "Quote enclosed character sequences". The function still takes a list of integers as you can see in the type annotation [Int] -> Int, but lists with single digit integers can now be written like "1234", e.g.
f "101010"
which evaluates to 42. Unlucky Haskell, because the native list format doesn't fit the challenge rules. Btw, f [1,0,1,0,1,0] still works.
-
2\$\begingroup\$ Unfortunately a list is not a valid input. \$\endgroup\$Jonathan Allan– Jonathan Allan2016年12月05日 20:43:21 +00:00Commented Dec 5, 2016 at 20:43
-
\$\begingroup\$ @JonathanAllan: Why? And if so, how should it take input at all? In Haskell a string is just a list of characters. \$\endgroup\$nimi– nimi2016年12月05日 21:04:58 +00:00Commented Dec 5, 2016 at 21:04
-
\$\begingroup\$ I don't know why ...but I enquired about this early on and an edit was made to add "
(1,0,1,0,1,0,1,0)is not a valid input format, but both10101010and(["10101010"])are." furthermore a comment suggests the array of characters is acceptable if that is how a string input is interpreted. \$\endgroup\$Jonathan Allan– Jonathan Allan2016年12月05日 21:10:33 +00:00Commented Dec 5, 2016 at 21:10 -
1\$\begingroup\$ @JonathanAllan: any "binary integer" (the input we have to take) is inherently separated, it's a sequence of powers of 2. The restriction is about explicit separators (between the digits) and not about separation. Somehow I have to take separated digits. \$\endgroup\$nimi– nimi2016年12月05日 22:56:31 +00:00Commented Dec 5, 2016 at 22:56
-
2\$\begingroup\$ Op here: if it's possible to input
10101010,"10101010"or something similar and make it work then the submission is valid. You may call it a string, list, integer or whatever. Inputting[1][0][1][0]or[1,0,1,0]is not ok. Basically, it should be possible to just hit a bunch of ones and zeros in a row somewhere. Is this clear? \$\endgroup\$Stewie Griffin– Stewie Griffin2016年12月06日 09:55:13 +00:00Commented Dec 6, 2016 at 9:55
Labyrinth, (削除) 17 (削除ここまで) 15 bytes
-+:
8 +
4_,`)/!
Labyrinth is a two-dimensional, stack-based language. In labyrinth, code execution follows the path of the code like a maze with spaces acting as walls and beginning at the top-left-most non-space character. The code flow is determined by the sign of the top of the stack. Since the stack has implicit zeroes at the bottom, the first four instructions (-+:+) have no effect.
Loop starting at the ,
,Push the ascii code value of the next input character to the stop of the stack, or push -1 if EOF._48pushes 48 to the top of the stack-Pop y, pop x, pushx-y. The previous instructions have the effect of subtracting 48 from the input yielding 0 for "0" and 1 for "1".+Pop y, pop x, pushx+y.:Duplicate the top of the stack+This and the previous instruction have the effect of multiplying the current value by 2
So the circular part of the code, in effect, multiples the current number by 2 and adds either a 1 or a 0 depending on if the character 1 or 0 was input.
Tail
If the top of the stack is negative (meaning EOF was found), the code will turn left at the junction (going towards the semicolon).
- ``` Negate the top of the stack to get 1
)Icrement the top of the stack to get 2/Pop y, pop x, push x/y (integer division). This has the effect of undoing the last*2from the loop.!Output the integer representation of the top of the stack. At this point the program turns around because it hit a dead end and then exits with an error because it tries to divide by zero.
Thanks to @Martin Ender for saving me 2 bytes (and teaching me how to better think in Labyrinth).
-
\$\begingroup\$ Instead of
_48-you can simply do#%but unfortunately I don't see how it might help with the byte count. \$\endgroup\$Martin Ender– Martin Ender2016年12月07日 20:51:22 +00:00Commented Dec 7, 2016 at 20:51 -
\$\begingroup\$ You can save a byte with
`)instead of;_2though. \$\endgroup\$Martin Ender– Martin Ender2016年12月07日 20:52:11 +00:00Commented Dec 7, 2016 at 20:52 -
\$\begingroup\$ @MartinEnder, I don't understand your comment about
#%. Can you explain how that works as a replacement for_48-to convert from ascii to int. Thanks for the)tip. I'll make that change. \$\endgroup\$Robert Hickman– Robert Hickman2016年12月07日 21:22:50 +00:00Commented Dec 7, 2016 at 21:22 -
\$\begingroup\$ At that point in your program there are always two values on the stack so
#is just short for_2. While_2%isn't a general conversion method for ASCII to integer, it works here because you're only interested in the first two digits as possible input. An alternative would be_1&(since modulo 2 simply extracts the least significant bit). \$\endgroup\$Martin Ender– Martin Ender2016年12月07日 21:28:52 +00:00Commented Dec 7, 2016 at 21:28 -
\$\begingroup\$ Oh. That's brilliant. But yeah I'm not sure how to use that substitution (
#%) to shorten the code overall. \$\endgroup\$Robert Hickman– Robert Hickman2016年12月07日 21:33:56 +00:00Commented Dec 7, 2016 at 21:33
JavaScript (ES6), (削除) 33 (削除ここまで) 31 bytes
s=>[...s].map(c=>r+=+c+r,r=0)|r
Edit: Shorter but less sweet: 2 bytes saved thanks to @ETHproductions.
-
\$\begingroup\$ As is often the case,
.mapis shorter:s=>[...s].map(c=>+c+r+r,r=0)|r\$\endgroup\$ETHproductions– ETHproductions2016年12月06日 23:10:21 +00:00Commented Dec 6, 2016 at 23:10 -
\$\begingroup\$ @ETHproductions How does your function return anything other than 0? \$\endgroup\$Neil– Neil2016年12月07日 00:43:14 +00:00Commented Dec 7, 2016 at 0:43
-
\$\begingroup\$ Sorry, it should be
s=>[...s].map(c=>r+=+c+r,r=0)|r\$\endgroup\$ETHproductions– ETHproductions2016年12月07日 00:52:45 +00:00Commented Dec 7, 2016 at 0:52
Retina, 15 bytes
Converts from binary to unary, then unary to decimal.
1
01
+`10
011
1
-
\$\begingroup\$ You are not allowed to use any builtin base conversion functions. ~OP \$\endgroup\$Linnea Gräf– Linnea Gräf2016年12月05日 20:15:45 +00:00Commented Dec 5, 2016 at 20:15
-
13\$\begingroup\$ @RomanGräf There aren't any. I was simply describing the process of my solution. \$\endgroup\$mbomb007– mbomb0072016年12月05日 20:25:14 +00:00Commented Dec 5, 2016 at 20:25
PHP, 44 bytes
for(;""<$c=$argv[1][$i++];)$n+=$n+$c;echo$n;
I could have sworn that I ́ve seen that question before. But well.
Reads the number from left to right, shifts left and adds the current bit.
Brain-Flak, (削除) 46 (削除ここまで), 28 bytes
([]){{}({}<>({}){})<>([])}<>
Many many bytes saved thanks to @Riley!
Since brain-flak can't take binary input, input is a list of '0's and '1's.
Explanation:
#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.
<>
-
\$\begingroup\$ Love the explanation! So hard to read brain-flak without it :) \$\endgroup\$Emigna– Emigna2016年12月05日 20:08:26 +00:00Commented Dec 5, 2016 at 20:08
-
2\$\begingroup\$ ^. I can't even read my own programs if I don't leave myself a few comments. \$\endgroup\$Riley– Riley2016年12月05日 20:10:28 +00:00Commented Dec 5, 2016 at 20:10
-
\$\begingroup\$ You can get it down to 32 bytes by getting rid of the whole if part,and for the step "add number to other stack" just add it to the (other stack)*2.
([]){({}[()]<({}<>({}){})><>)}<>\$\endgroup\$Riley– Riley2016年12月05日 20:16:38 +00:00Commented Dec 5, 2016 at 20:16 -
\$\begingroup\$ And you can save another 4 by just popping at the start of the while and pushing the height again at the end.
([]){{}({}<>({}){})<>([])}<>\$\endgroup\$Riley– Riley2016年12月05日 20:18:15 +00:00Commented Dec 5, 2016 at 20:18 -
\$\begingroup\$ @Riley Oh my gosh, that's genius. Thankyou very much! \$\endgroup\$DJMcMayhem– DJMcMayhem2016年12月05日 20:20:38 +00:00Commented Dec 5, 2016 at 20:20
Java, (削除) 84 (削除ここまで) (削除) 79 (削除ここまで) (削除) 46 (削除ここまで) 48 bytes
- Version 3.1
Changed to long/48 bytes:
s->{long x=0;for(char c:s)x=c-48l+x*2;return x;}
- Version 3.0
Did some golfing/46 bytes:
s->{int x=0;for(char c:s)x=c-48+x*2;return x;}
- Version 2.0
Thanks to @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;}
-
1\$\begingroup\$ guess i should have done an iterative solution. lulz. good job \$\endgroup\$Poke– Poke2016年12月05日 20:46:59 +00:00Commented Dec 5, 2016 at 20:46
-
\$\begingroup\$ Is your input type List<Character> or String? If it's the latter, I was unaware Java8 could do that! If it's the former is that allowed by the challenge? \$\endgroup\$Poke– Poke2016年12月05日 21:00:05 +00:00Commented Dec 5, 2016 at 21:00
-
\$\begingroup\$
sshould bechar[]. I hope that's allowed... \$\endgroup\$Linnea Gräf– Linnea Gräf2016年12月05日 21:01:38 +00:00Commented Dec 5, 2016 at 21:01 -
\$\begingroup\$ What is the return type here? I think it should be long because "The code must support binary numbers up to the highest numeric value your language supports" per the OP but for smaller values I would think it returns an int \$\endgroup\$Poke– Poke2016年12月05日 21:02:20 +00:00Commented Dec 5, 2016 at 21:02
-
1
Befunge-98, 12 bytes
2j@.~2%2円*+
Reads one char at a time from input, converts it to 0 or 1 by taking its value modulo 2 (0 is char(48), 1 is char(49)), then uses the usual algorithm of doubling the current value and adding the new digit each time.
Bonus: This works with any kind of input string, I've been trying for a while now to find any funny input->output combination, but I wasn't able to produce anything (sadly, "answer"=46). Can you?
-
\$\begingroup\$ LOL. I was playing the same game with my answer. Most interesting number I could generate was 666. \$\endgroup\$James Holderness– James Holderness2016年12月06日 12:27:07 +00:00Commented Dec 6, 2016 at 12:27
-
\$\begingroup\$ Nice one! I hadn't managed to find anything fitting for 666 :D It would be a lot easier if capitalization had an effect on values... \$\endgroup\$Leo– Leo2016年12月06日 14:01:17 +00:00Commented Dec 6, 2016 at 14:01
-
\$\begingroup\$ @James Holderness - I've been doing the same and I've only found 'theleapyear' to bring back 366, yours is really good. \$\endgroup\$Teal pelican– Teal pelican2016年12月06日 14:19:40 +00:00Commented Dec 6, 2016 at 14:19
C# 6, (削除) 85 (削除ここまで) (削除) 37 (削除ここまで) 36 bytes
long b(long n)=>n>0?n%2+2*b(n/10):0;
- Thanks to Kade for saving 41 bytes!
- Changing to C# 6 saved another 7 bytes.
-
-
\$\begingroup\$ @Kade It does, thanks! I was looking at the Python answer which uses the same technique at the same moment you linked that :D I can get even shorter with C# 6. \$\endgroup\$Yytsi– Yytsi2016年12月05日 21:47:58 +00:00Commented Dec 5, 2016 at 21:47
Vyxal s, 31 bitsv2 , (削除) 9 (削除ここまで) (削除) 7 (削除ここまで) 3.875 bytes
fṘTE
fṘTE
- -2 thanks to Steffan
- -3 chars thanks to lyxal
Explanation:
fṘTE # Implicit input
f # Flatten into a list of digits
Ṙ # Reverse the list
T # Truthy indices
E # Two power
# Implicit output of sum
Old:
ṘėRvƒ↲∑ # Implicit input
Ṙė # Reverse and enumerate
R # Reverse each
vƒ # Vecorised reduce over:
↲ # Left bit-shift
∑ # Sum
# Implicit output
-
\$\begingroup\$ "You are not allowed to use any builtin base conversion functions." \$\endgroup\$naffetS– naffetS2023年01月08日 14:43:46 +00:00Commented Jan 8, 2023 at 14:43
-
\$\begingroup\$ Sorry, I didn't see that. I've updated the answer \$\endgroup\$The Thonnu– The Thonnu2023年01月08日 14:49:03 +00:00Commented Jan 8, 2023 at 14:49
-
\$\begingroup\$ 7 bytes:
ṘėRvƒ↲∑(a*2**bisa<<b, or↲) \$\endgroup\$naffetS– naffetS2023年01月08日 14:53:09 +00:00Commented Jan 8, 2023 at 14:53 -
\$\begingroup\$
Ris "reverse each" in this case, not "reduce".vƒ↲is vectorized reduce over left bit-shift (it'sƒnotf) \$\endgroup\$naffetS– naffetS2023年01月10日 03:13:38 +00:00Commented Jan 10, 2023 at 3:13 -
\$\begingroup\$ @Steffan thanks \$\endgroup\$The Thonnu– The Thonnu2023年01月10日 07:24:41 +00:00Commented Jan 10, 2023 at 7:24
Perl, 25 bytes
-3 bytes thanks to @Dom Hastings.
24 bytes of code + 1 byte for -p flag.
$\|=$&<<$v++while s/.$//
To run it:
perl -pe '$\|=$&<<$v++while s/.$//' <<< 101010
Explanations:
$\|=$&<<$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
-
\$\begingroup\$ 21 bytes, Try it online! \$\endgroup\$Nahuel Fouilleul– Nahuel Fouilleul2020年07月18日 20:02:03 +00:00Commented Jul 18, 2020 at 20:02
Javascript (ES7) (削除) 41 (削除ここまで) (削除) 40 (削除ここまで) 36 bytes
f=([c,...b])=>c?c*2**b.length+f(b):0
takes a string as input
Shaved a byte thanks to ETHproductions
f=([c,...b])=>c?c*2**b.length+f(b):0
document.write([
f('101010'),
f('11010'),
f('10111111110'),
f('1011110010110'),
].join("<br>"))
-
1\$\begingroup\$ The right-to-left associativity of
**is weird, but nice job using it here.1<<b.lengthwould do the same thing, but it would require parentheses to keep from being parsed as(c*1)<<(b.length+...). I think you can save a byte by replacingb[0]withb+b(see here). \$\endgroup\$ETHproductions– ETHproductions2016年12月06日 15:09:57 +00:00Commented Dec 6, 2016 at 15:09
Retina, 12 bytes
Byte count assumes ISO 8859-1 encoding.
+%`\B
¶$`:
1
Alternative solution:
+1`\B
:$`:
1
Explanation
This will probably be easier to explain based on my old, less golfed, version and then showing how I shortened it. I used to convert binary to decimal like this:
^
,
+`,(.)
$`1,ドル
1
The only sensible way to construct a decimal number in Retina is by counting things (because Retina has a couple of features that let it print a decimal number representing an amount). So really the only possible approach is to convert the binary to unary, and then to count the number of unary digits. The last line does the counting, so the first four convert binary to unary.
How do we do that? In general, to convert from a list of bits to an integer, we initialise the result to 0 and then go through the bits from most to least significant, double the value we already have and add the current bit. E.g. if the binary number is 1011, we'd really compute:
(((0 * 2 + 1) * 2 + 0) * 2 + 1) * 2 + 1 = 11
^ ^ ^ ^
Where I've marked the individual bits for clarity.
The trick to doing this in unary is a) that doubling simply means repeating the number and b) since we're counting the 1s at the end, we don't even need to distinguish between 0s and 1s in the process. This will become clearer in a second.
What the program does is that it first adds a comma to the beginning as marker for how much of the input we've already processed:
^
,
Left of the marker, we'll have the value we're accumulating (which is correctly initialised to the unary representation of zero), and right of the value will be the next bit to process. Now we apply the following substitution in a loop:
,(.)
$`1,ドル
Just looking at ,(.) and 1,ドル, this moves the marker one bit to the right each time. But we also insert $`, which is everything in front of the marker, i.e. the current value, which we're doubling. Here are the individual steps when processing input 1011, where I've marked the result of inserting $` above each line (it's empty for the first step):
,1011
1,011
_
110,11
___
1101101,1
_______
110110111011011,
You'll see that we've retained and doubled the zero along with everything else, but since we're disregarding them at the end, it doesn't matter how often we've doubled them, as long as the number of 1s is correct. If you count them, there are 11 of them, just what we need.
So that leaves the question of how to golf this down to 12 bytes. The most expensive part of the 18-byte version is having to use the marker. The goal is to get rid of that. We really want to double the prefix of every bit, so a first idea might be this:
.
$`$&
The problem is that these substitutions happen simultaneously, so first bit doesn't get doubled for each bit, but it just gets copied once each time. For input 1011 we'd get (marking the inserted $`):
_ __ ___
1101011011
We do still need to process the input recursively so that the doubled first prefix is doubled again by the second and so on. One idea is to insert markers everywhere and repeatedly replace them with the prefix:
\B
,
+%`,
¶$`
After replacing each marker with the prefix for the first time, we need to remember where the beginning of the input was, so we insert linefeeds as well and use the % option to make sure that the next $` only picks up things up the closest linefeed.
This does work, but it's still too long (16 bytes when counting 1s at the end). How about we turn things around? The places where we want to insert markers are identified by \B (a position between two digits). Why don't we simply insert prefixes into those positions? This almost works, but the difference is that in the previous solution, we actually removed one marker in each substitution, and that's important to make the process terminate. However, the \B aren't character but just positions, so nothing gets removed. We can however stop the \B from matching by instead inserting a non-digit character into this place. That turns the non-word boundary into a word boundary, which is the equivalent of removing the marker character earlier. And that's what the 12-byte solution does:
+%`\B
¶$`:
Just for completeness, here are the individual steps of processing 1011, with an empty line after each step:
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
Again, you'll find that the last result contains exactly 11 1s.
As an exercise for the reader, can you see how this generalises quite easily to other bases (for a few additional bytes per increment in the base)?
Bash + GNU utilities, 29 bytes
sed 's/./2*&+/g;s/.*/K&p/'|dc
I/O via stdin/stdout.
The sed expression splits the binary up into each digit and builds a RPN expression for dc to evaluate.
C, 53
v(char*s){int v=0,c;while(c=*s++)v+=v+c-48;return v;}
Same as my javascript answer
Test Ideone
-
\$\begingroup\$ You can save 4 bytes by declaring
vandcas global variables (though you need to change the name ofv, since it's already the name of the function) like this:w=0;c;v(char*s){while(c=*s++)w+=w+c-48;return w;}\$\endgroup\$Steadybox– Steadybox2016年12月06日 19:55:40 +00:00Commented Dec 6, 2016 at 19:55 -
\$\begingroup\$ @Steadybox it could be
w,c;but I don't want use globals when the answer is a function (even in code-golf) \$\endgroup\$edc65– edc652016年12月06日 20:24:01 +00:00Commented Dec 6, 2016 at 20:24 -
\$\begingroup\$ @Steadybox Globals defaults to 0 as well, so you can drop the
=0. \$\endgroup\$algmyr– algmyr2016年12月08日 01:22:03 +00:00Commented Dec 8, 2016 at 1:22 -
\$\begingroup\$ This answers only half the question - it converts a binary string into an integer result, but doesn't do the hard part of converting that integer to decimal representation \$\endgroup\$Toby Speight– Toby Speight2025年08月18日 12:18:48 +00:00Commented Aug 18 at 12:18
Mathematica, (削除) 27 (削除ここまで) (削除) 13 (削除ここまで) 11 bytes
Fold[#+##&]
Accepts a List of bits as input (e.g. {1, 0, 1, 1, 0} -- Mathematica's binary representation of the number 22)
-
\$\begingroup\$ Following up from the comment on Greg's answer, how is "splitting all the digits in the input" not a base conversion function? \$\endgroup\$Martin Ender– Martin Ender2016年12月06日 05:33:31 +00:00Commented Dec 6, 2016 at 5:33
-
\$\begingroup\$ @MartinEnder I'm using it like the
Charactersfunction. \$\endgroup\$JungHwan Min– JungHwan Min2016年12月06日 05:48:06 +00:00Commented Dec 6, 2016 at 5:48 -
\$\begingroup\$ @MartinEnder Actually, as seen in @nimi's answer, I could just accept a list of 1s and 0s because that is the only way to represent a binary number in Mathematica, meaning I don't need
IntegerDigitsin the first place. \$\endgroup\$JungHwan Min– JungHwan Min2016年12月06日 05:52:27 +00:00Commented Dec 6, 2016 at 5:52 -
\$\begingroup\$ That assumes that base 10 is the "natural" representation of an integer. An actual integer value has no preferred base attached to it (I guess you could say the way it's stored is probably base 256 or maybe even base 2 but that's an implementation detail). Just because we (normally) use base 10 to write integer literals there doesn't mean integer values are already in base 10. \$\endgroup\$Martin Ender– Martin Ender2016年12月06日 05:52:41 +00:00Commented Dec 6, 2016 at 5:52
-
\$\begingroup\$ @MartinEnder @Lynn's Jelly code uses
D, which does the same thing asIntegerDigits\$\endgroup\$JungHwan Min– JungHwan Min2016年12月06日 05:53:32 +00:00Commented Dec 6, 2016 at 5:53
Pushy, 10 bytes
Takes input as a list of 0/1 on the command line: $ pushy binary.pshy 1,0,1,0,1,0.
L:vK2*;OS#
The algorithm really shows the beauty of having a second stack:
\ 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
This method works because the stack will be doubled stack length - n times before reaching number n, which is then dumped into the second stack for later. Here's what the process looks like for input 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
R (32-bit), 64 Bytes
Input for the function should be given as character. The base functions of R support 32-bit integers.
Input:
# 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")
Output:
> f("1")
[1] 1
> f("10")
[1] 2
> f("101010")
[1] 42
> f("1101111111010101100101110111001110001000110100110011100000111")
[1] 2.016121e+18
R (64-bit), 74 Bytes
Input for the function should be given as character. The package bit64 has to be used for 64-bit integers.
Input:
# 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")
Output:
> g("1")
integer64
[1] 1
> g("10")
integer64
[1] 2
> g("101010")
integer64
[1] 42
> g("1101111111010101100101110111001110001000110100110011100000111")
integer64
[1] 2016120520371234567
-
2\$\begingroup\$ You can do:
el(strsplit(x,""))instead ofstrsplit(x,split="")[[1]]to save a couple of bytes. \$\endgroup\$Billywob– Billywob2016年12月07日 10:14:25 +00:00Commented Dec 7, 2016 at 10:14 -
\$\begingroup\$ Thanks a lot! Especially for the
elfunction - I was not aware of it. \$\endgroup\$djhurio– djhurio2016年12月07日 20:47:35 +00:00Commented Dec 7, 2016 at 20:47
Matlab, 30 Bytes
@(x)sum(2.^find(flip(x)-48)/2)
The last test case has rounding errors (because of double), so if you need full precision:
@(x)sum(2.^uint64(find(flip(x)-48))/2,'native')
with 47 Bytes.
-
\$\begingroup\$ I can't test this, but I believe
@(x)sum(2.^(find(flip(x)-48)-1))will give the correct result for all cases for 32 bytes.flipworks likefliplrifxis one dimensional. \$\endgroup\$Stewie Griffin– Stewie Griffin2016年12月06日 16:51:51 +00:00Commented Dec 6, 2016 at 16:51 -
\$\begingroup\$ Nice solution! I also ran into the rounding error, thanks for the fix. What is the format of x? Calling flip or fliplr on a number just returns that number. \$\endgroup\$hwm– hwm2016年12月10日 01:35:31 +00:00Commented Dec 10, 2016 at 1:35
-
\$\begingroup\$ x is the binary string, so call it with
f=@(x)..; f('1111001010'). \$\endgroup\$Jonas– Jonas2016年12月10日 13:38:27 +00:00Commented Dec 10, 2016 at 13:38
Elm, (削除) 60 (削除ここまで) 41 bytes
String.foldl(\b a->2*a+Char.toCode b-48)0
-19 bytes thanks to Wheat Wizard and alephalpha
You can try it here. Here's a full test snippet:
import Html exposing (text)
f : String -> Int
f=String.foldl(\b a->2*a+Char.toCode b-48)0
main = text (String.fromInt (f "101010"))
-
\$\begingroup\$ Since you only use
nonce you can very easily express this using point free to save 4 bytes. \$\endgroup\$2023年01月10日 03:21:36 +00:00Commented Jan 10, 2023 at 3:21 -
1\$\begingroup\$ You can use
String.foldlinstead ofList.Foldl+String.toList. \$\endgroup\$alephalpha– alephalpha2023年01月10日 03:35:23 +00:00Commented Jan 10, 2023 at 3:35 -
\$\begingroup\$ You don't need to count the
f=since the body is a valid anonymous function. \$\endgroup\$2023年01月10日 17:42:32 +00:00Commented Jan 10, 2023 at 17:42
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
PHP, 64 bytes
foreach(str_split(strrev($argv[1]))as$k=>$v)$t+=$v*2**$k;echo$t;
We reverse our binary number, split it into its component digits, and sum them based on position.
PowerShell v2+, 55 bytes
param($n)$j=1;$n[$n.length..0]|%{$i+=+"$_"*$j;$j*=2};$i
(削除) Feels too long ... (削除ここまで) Can't seem to golf it down any -- tips appreciated.
Explanation
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
MATL, 7 bytes
PoofqWs
P % Implicitly input string. Reverse
o % Convert to array of ASCII codes
o % Modulo 2: '1' becomes 1, '0' becomes 0
f % Find: push array of 1-based indices of nonzeros
q % Subtract 1 from each entry
W % 2 raised to each entry
s % Sum of array. Implicitly display
-
2\$\begingroup\$ My mind went Poof! \$\endgroup\$Adám– Adám2016年12月12日 14:54:28 +00:00Commented Dec 12, 2016 at 14:54
JavaScript (ES6), 32 bytes
f=([...n])=>n+n&&+n.pop()+2*f(n)
Recursion saves the day again! Though the parameterization seems a little long...
-
\$\begingroup\$ Since it's a single "argument", does
[...n]need to be surrounded in parentheses? \$\endgroup\$Cyoce– Cyoce2016年12月11日 18:38:26 +00:00Commented Dec 11, 2016 at 18:38 -
\$\begingroup\$ @Cyoce Unfortunately, yes, or JS throws a SyntaxError. \$\endgroup\$ETHproductions– ETHproductions2016年12月11日 21:18:02 +00:00Commented Dec 11, 2016 at 21:18
-1(32 1'sand64 1's) \$\endgroup\$round(x)==xyou're fine :)2.000is accepted output for10. \$\endgroup\$20161205193745*****:) \$\endgroup\$