Code Golf Asked on October 27, 2021
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:
(1,0,1,0,1,0,1,0)
is not a valid input format, but both 10101010
and (["10101010"])
are.
1110
is 14
not 7
.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.
(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
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.
Answered by who cares on October 27, 2021
Fo+Dd
F # Fold from left
# (apply binary function to each element,
# together with the value of the previous result)
d # over all the digits of the input,
# with this function:
o # o = combination of 2 functions
+ # add second argument (each new digit, from left) to
D # double the first argument (previous result)
Answered by Dominic van Essen on October 27, 2021
2100 f810 2b01 b112 0852 4149 e7f9 4770
Commented assembly:
.syntax unified
.arch armv6t2
.thumb
.globl bin2int
.thumb_func
// Input: null terminated string in r0
// Output: integer in r1
bin2int:
// Set initial result to zero
movs r1, #0
.Lloop:
// Load char from r0 into r2, increment
ldrb r2, [r0], #1
// Was it ' '? If so, bail.
cbz r2, .Lend
// Shift the lowest bit into the carry flag
// ASCII '0' has the lowest bit clear, ASCII '1'
// does not.
lsrs r2, r2, #1
// Multiply the result by 2 (by adding to itself),
// and add the carry flag to that result
adcs r1, r1
// Jump back to .Lloop (our loop condition is cbz)
b .Lloop
.Lend:
// Return
bx lr
The input is a null terminated string in r0
and the output is in r1
.
I came up with the same idea as 640KB (SHR/ADC
, or in my case, lsrs/adcs
) without even seeing their solution. ?
Great minds think alike, I guess.
Answered by EasyasPi on October 27, 2021
Answered by Razetime on October 27, 2021
Answered by Matthew Jensen on October 27, 2021
-11 bytes thanks to Dominic van Essen
sum(utf8ToInt(scan(,""))%%2*2^(31:0))
Takes input as a string, left-padded with 0s to 32 bits. Try it online!
I copied some good ideas from djhurio's much earlier R answer, so go give that an upvote too. As with the first solution there, this solution won't work for the last test case because it's too large to fit into R's default size of integer.
To get a vector of the bits as integers 0 and 1, we use uft8ToInt
to convert to a vector of character codes. This gives us a list of 48s and 49s, which we take mod 2 to get 0s and 1s.
Then, to get the appropriate powers of 2 in descending order, we construct a range from 31 down to 0. Then we convert each of those numbers to the corresponding power of two (2^
).
Finally, we multiply the two vectors together and return their sum
.
Answered by DLosc on October 27, 2021
-p
) = 19 bytesCombines techniques from the other Perl entries. Scored using the rules at the time of posting.
s/./$+=$+$&/ge}{
Answered by Xcali on October 27, 2021
$+(**_*BMERVa)
Doesn't work on TIO because unary ** is only in the latest Pip version.
Answered by Razetime on October 27, 2021
Trailing parens already discounted. Tested in Excel Online.
A1
: InputB1
: =LEN(A1)
(7)A pretty simple "add all the powers of 2" formula:
=SUM(MID(A1,1+B1-SEQUENCE(B1),1)/2*2^SEQUENCE(B1))
Verify with:
=DECIMAL(A1,2)
Answered by Calculuswhiz on October 27, 2021
07717134200446170134271600446170001755630036117700136161177546635
077 Initialize counter to 0 (an empty section) 17134200..77546635 Push the main loop onto the frame
Once the original code has finished executing, the frame is
||6||7134200447013427160044700017556300377700136177754635
The last section of this is the main loop, which will run repeatedly until it gets deleted. All of it except the last two commands is data and section separators, which push commands onto the frame to leave it as:
||6|| (main loop) |73426644|6734216644|6667553663||00137||54
3
outputs the last section (54
) and discards the last two bars. On the first iteration, 5
is interpreted as a switch to output format 5 ("US-TTY"), which converts each pair of commands to a character. The 4
following it does not form a group, so it is ignored. On future iterations, we are already in output format 5, so 54
is interpreted as a group meaning "input character". To do this, the character from STDIN is converted into its character code (or, on EOF, -1
), and 1 is added. Then, the last section (which is now the 00137
) is repeated that many times. In summary:
0
, 00137
is repeated 49 times.1
, 00137
is repeated 50 times.00137
is repeated 0 times (i.e. deleted).00137
is left alone (i.e. repeated 1 time).5
removes the last section (00137
repeated some number of times) from the frame and executes it, resulting in this many sections containing 6673
.
The main loop has now finished executing, so the last section (which is 6673
unless we reached EOF) runs. 66
concatenates the last three sections into one (and has some other effects that don't affect the number of sections), which 73
deletes. Thus, the last three sections are deleted, and this repeats until the last section is no longer 6673
.
0
, after removing the last three sections 0 or 16 times, there is just one copy left on the frame. This copy deletes itself and the two sections before it, leaving everything up to the main loop and the section after it.1
, after removing the last three sections 17 times, all 50 copies and the third section after the main loop (the EOF handler) have been deleted.Now, the last section left on the frame runs. This could, depending on the inputted character, be any of the three sections after the main loop.
If this is the first iteration or the character was 0
, the section just after the main loop, 73426644
, runs.
73
deletes this section, and 4
swaps the main loop with the counter behind it. This counter keeps track of the number we want to output, stored as the number of 7
s and 1
s minus the number of 6
s and 0
s. This metric has the property that it is not changed by pacification (which changes some 6
s into 0
s, some 7
s into 1
s, and sometimes inserts 7...6
around code). 2
duplicates the counter and 6
concatenates the two copies (after pacifying the second, which, as we saw, does not change the value it represents), so the value is doubled. If this was the first iteration, the counter was previously empty, and doubling it still results in an empty section. Then, 6
gets rid of the empty section inserted by 4
(and pacifies the counter again, leaving the value unchanged), and 44
swaps the counter back to its original position. This leaves two empty sections on the end of the frame, which are removed automatically, and the main loop runs again.
If the character was 1
, the second section after the main loop (6734216644
) runs. This is just like the section before it (explained in the last paragraph), except for two extra commands: a 6
at the start, which joins the section with the previous one before 73
deletes it, and a 1
in the middle, which adds a 7
to the counter (increasing its value by 1) after it gets doubled.
If we reached EOF, the third section after the main loop (6667553663
) runs. 666
joins the last four sections (everything after the counter) into one section, to be deleted by 3
. 7553
exits output format 5 by outputting 55
and deletes the section before it, leaving only ||6| (counter)
on the frame. 66
pacifies the two sections and combines them, turning the 6
back into a 0
(and not changing the value of the counter). Finally, the last 3
outputs everything.
The 0
at the start enters output format 0 ("Numerical output"), and the rest of the section (i.e. the counter) is converted to a number by taking the number of 7
s and 1
s minus the number of 6
s and 0
s. This value, which is the input converted from binary, is output in decimal and the program terminates.
Answered by Pizgenal Filegav on October 27, 2021
-rr
, 0&÷^⑷2⑻Ë*⑹⑸⅀
0& # Place 0 into the register. This will serve as the power to which 2 will be raised
÷^ # Take the input as a number and split it into it's individual numbers. It is then reversed.
⑷ # Start a map applying the following to each item in the input:
2⑻Ë* # Exponate 2 to the power of the register and multiply the number by that value
⑹ # Increment the register
⑸⅀ # Close the map and sum the stack, printing that sum implicitly
Answered by lyxal on October 27, 2021
{+/a×⌽1,2x*⍳¯1+≢a←1-⍨⎕D⍳⍵}
test:
f←{+/a×⌽1,2x*⍳¯1+≢a←1-⍨⎕D⍳⍵}
⎕fmt f"0"
0
~
f"1"
1
⎕fmt f"101010"
42
~~
f"10"
2
(≢,f)"11011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
152 4995366924470859583704000893073232977339613183
152 bits... It should be limited from memory for store string and numbers.
Answered by user58988 on October 27, 2021
Binary:
00000000: 31d2 acd0 e811 d2e2 f9c3 1.........
Listing:
31 D2 XOR DX, DX ; clear output value
CHRLOOP:
AC LODSB ; load next char into AL
D0 E8 SHR AL, 1 ; CF = LSb of ASCII char
11 D2 ADC DX, DX ; shift CF left into result
E2 F9 LOOP CHRLOOP ; loop until end of string
C3 RET ; return to caller
Callable function, input string in [SI]
length in CX
. Result in DX
.
Example test program I/O:
Answered by 640KB on October 27, 2021
INPUT B$WHILE""<B$N=N*2+VAL(SHIFT(B$))WEND?N
Another program of the same size:
INPUT B$WHILE""<B$N=N*2OR"0"<SHIFT(B$)WEND?N
Answered by 12Me21 on October 27, 2021
: x 2 base ! bl parse s>number drop decimal . ;
: x
- define new word with name 'x'
2 base !
- set base to binary
bl parse
- read line until a space (bl) or EOL
s>number
- try to convert the string to number
drop
- we only want the converted number and not the success flag
decimal
- set base to decimal
.
- print value on top of stack
;
- end of definition
Test cases:
x 1 1 ok
x 10 2 ok
x 101010 42 ok
x 1101111111010101100101110111001110001000110100110011100000111 2016120520371234567 ok
Answered by 2xsaiko on October 27, 2021
@(a)dot(int2str(a)-'0',2.^(floor(log10(a)):-1:0))
Anonymous function that splits the input into an array with int2str(a)-'0'
, then does a dot product with powers of 2. Has rounding error for the last test case, will update the solution when I figure out a fix.
Answered by hwm on October 27, 2021
Answered by user56344 on October 27, 2021
f=foldl(a b->2*a+(read$b:[]))0
Takes input in string format (e.g. "1111"
). Produces output in integer format (e.g. 15
).
:[]
Converts from an element to an array -- in this chase from Char
to [Char]
(String
).
read
Converts from string to whatever context it's in (in this case the context is addition, so converts to Num
)
so (read$b:[])
converts b
from Char
to Num
.
a
is the accumulator, so multiply that by two and add the Num
version of b
.
If input in the format [1,1,1,1]
was allowed, the 18 byte
f=foldl((+).(2*))0
would work, but since it's not, it doesn't.
Answered by Joshua David on October 27, 2021
(++⊢)/⌽⍎¨⍞
⍞
get string input
⍎¨
convert each character to number
⌽
reverse
(
...)/
insert the following function between the numbers
++⊢
the sum of the arguments plus the right argument
ngn shaved 2 bytes.
Answered by Adám on October 27, 2021
-4 bytes thanks to @Dada
Run with -F -p
(including the extra space after the F
). Pipe values to the function using echo -n
$+=$_+$for@F}{
Run as echo -n "101010" | perl -F -pE '$+=$_+$for@F}{'
I feel this is sufficiently different from @Dada's answer that it merits its own entry.
Explanation:
-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 $
This uses my personal algorithm of choice for binary-to-decimal conversion. Given a binary number, start your accumulator at 0, and go through its bits one by one. Double the accumulator each bit, then add the bit itself to your accumulator, and you end up with the decimal value. It works because each bit ends up being doubled the appropriate number of times for its position based on how many more bits are left in the original binary number.
Answered by Gabriel Benamy on October 27, 2021
-+:
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.
,
,
Push the ascii code value of the next input character to the stop of the stack, or push -1 if EOF._48
pushes 48 to the top of the stack-
Pop y, pop x, push x-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, push x+y
.:
Duplicate the top of the stack+
This and the previous instruction have the effect of multiplying the current value by 2So 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.
If the top of the stack is negative (meaning EOF was found), the code will turn left at the junction (going towards the semicolon).
)
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 *2
from 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).
Answered by Robert Hickman on October 27, 2021
d(s,v)char*s;{return*s?d(s,v+=v+*s++-48):v;}
Use as follows :
int main(){
printf("%in", d("101010",0));
}
Remove two bytes and an unused parameter thanks to Steadybox
Answered by Charles Paulet on October 27, 2021
@(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.
Answered by Jonas on October 27, 2021
/i:1+?!v$2*$2%+!| !
/0| ;n~<
Edit 1: Forgot to put the output in the original. Added output and used MOD 2 instead of minus 48 to convert ascii to decimal to save the extra bytes lost. (no change in bytes)
Edit 2: Changed the algorithm completely. Each loop now does this; times current value by 2, then add the mod of the input. (saving of 8 bytes)
Try it Online! - This works with bigger numbers than the above link.
Answered by Teal pelican on October 27, 2021
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
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
Answered by djhurio on October 27, 2021
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?
Answered by Leo on October 27, 2021
Takes a string as input
(defun f(s)(reduce(lambda(a d)(+ d(* a 2)))(map'list #'digit-char-p s)))
Ungolfed:
(defun bin-to-dec (bin-str)
(reduce (lambda (acc digit) (+ digit (* acc 2)))
(map 'list #'digit-char-p bin-str)))
Answered by Bart van Nierop on October 27, 2021
n6ZrI[2%2i;*1R]$+N.
n gets input in the form of a number
6Z converts to string (so that it is split into an array)
r reverses it
I gets the stack length
[ ] for loop with the stack's length as the number of iterations
2% gets the modulo of the ascii value
1 =(string conversion)> 49 =(after modulo)> 1
0 =(string conversion)> 48 =(after modulo)> 0
2i; raises 2 to the power of the loop counter
* multiplies it by the modulo
1R rotates stack 1 time
$+ sums everything
N. outputs as number and exit
Answered by user41805 on October 27, 2021
(fn[x](reduce #(+(* 2 %)(int %2))x))
or
#(reduce(fn[a n](+(* 2 a)(int n)))%)
The straightforward reduction. Takes a string as input.
Answered by MattPutnam on October 27, 2021
아빟뱐썩러숙
뎌반뗘희멍파퍄
Accepts a string composed of 1s and 0s.
To try online
Since the online Aheui interpreter does not allow arbitrary-length strings as inputs, this alternative code must be used (identical code with slight modifications):
Add the character 벟
at the end of the first line (after 우
) length(n)-times.
어우
우어
뱐썩러숙
번댜펴퍼망희땨
If the input is 10110
, the first line would be 어우벟벟벟벟벟
.
When prompted for an input, do NOT type quotation marks. (i.e. type 10110
, not "10110"
)
Answered by JungHwan Min on October 27, 2021
Answered by Dennis on October 27, 2021
ruby -e 'o=0;gets.each_byte{|i|o+=o+i%2};p o/2'
1234567890123456789012345678901234567
This depends on the terminating n
(ASCII decimal 10) being zero modulo 2 (and on ASCII 0 and 1 being 0 and 1 mod two, respectively, which thankfully they are).
Answered by DepressedDaniel on October 27, 2021
Input must be terminated with EOF rather than EOL (this lets us save a couple of bytes)
>+~:0`v
^*2%2_$.@
Explanation
> The stack is initially empty, the equivalent of all zeros.
+ So the first pass add just leaves zero as the current total.
~ Read a character from stdin to the top of the stack.
:0` Test if greater than 0 (i.e. not EOF)
_ If true (i.e > 0) go left.
%2 Modulo 2 is a shortcut for converting the character to a numeric value.
Swap to bring the current total to the top of the stack.
*2 Multiply the total by 2.
^ Return to the beginning of the loop,
+ This time around add the new digit to the total.
...on EOF we go right...
$ Drop the EOF character from the stack.
. Output the calculated total.
@ Exit.
Answered by James Holderness on October 27, 2021
f=([...n])=>n+n&&+n.pop()+2*f(n)
Recursion saves the day again! Though the parameterization seems a little long...
Answered by ETHproductions on October 27, 2021
s=>[...s].map(c=>r+=+c+r,r=0)|r
Edit: Shorter but less sweet: 2 bytes saved thanks to @ETHproductions.
Answered by Neil on October 27, 2021
Fold[#+##&]
Accepts a List
of bits as input (e.g. {1, 0, 1, 1, 0}
-- Mathematica's binary representation of the number 22
)
Answered by JungHwan Min on October 27, 2021
f=([c,...b],n=0)=>c<2?f(b,+c+n+n):n
For c='1'
and c='0'
, c<2
returns true.
If b
is empty, c
will be undefined in the next recursion and c<2
will be false
.
Answered by Titus on October 27, 2021
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
Answered by Luis Mendo on October 27, 2021
DḤ+¥/
D
is a monad (single argument function): digits, turning 1234
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.
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 with f
, and evaluates the result.)
The final chain looks like [D, fold(dyad(Ḥ+))]
, two monads.
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 with 1∗0∗1∗0∗1∗0
, where ∗
is the dyad Ḥ+
.
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 now 2x
.
+
, 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 yields 2x + y
as the final working value, which is returned.
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
Answered by Lynn on October 27, 2021
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
Answered by FlipTack on October 27, 2021
Byte count assumes ISO 8859-1 encoding.
+%`B
¶$`:
1
Alternative solution:
+1`B
:$`:
1
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 1
s at the end, we don't even need to distinguish between 0
s and 1
s 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 1
s 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 1
s 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 1
s.
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)?
Answered by Martin Ender on October 27, 2021
2^Range[Length[d=IntegerDigits@#]-1,0,-1].d&
Unnamed function taking an integer argument (interpreted as a base-10 integer, but will only have the digits 0 and 1) and returning an integer. d
is set equal to the set of digits, and then the dot product of d with the appropriate sequence of powers of 2 generates the value.
Answered by Greg Martin on October 27, 2021
v(char*s){int v=0,c;while(c=*s++)v+=v+c-48;return v;}
Same as my javascript answer
Test Ideone
Answered by edc65 on October 27, 2021
(Using, as usual, the morphett.info rule table syntax)
0 * * l B
B * * l C
C * 0 r D
D * * r E
E * * r A
A _ * l 1
A * * r *
1 0 1 l 1
1 1 0 l 2
1 _ * r Y
Y * * * X
X * _ r X
X _ _ * halt
2 * * l 2
2 _ _ l 3
3 * 1 r 4
3 1 2 r 4
3 2 3 r 4
3 3 4 r 4
3 4 5 r 4
3 5 6 r 4
3 6 7 r 4
3 7 8 r 4
3 8 9 r 4
3 9 0 l 3
4 * * r 4
4 _ _ r A
AKA "Yet another trivial modification of my earlier base converter programs."
Try it online, or you can also use test it using this java implementation.
Answered by SuperJedi224 on October 27, 2021
Simple is better
s=>eval("for(i=v=0;c=s[i++];)v+=+c+v")
Test
f=s=>eval("for(i=v=0;c=s[i++];)v+=+c+v")
console.log("Test 0 to 99999")
for(e=n=0;n<100000;n++)
{
b=n.toString(2)
r=f(b)
if(r!=n)console.log(++e,n,b,r)
}
console.log(e+" errors")
Answered by edc65 on October 27, 2021
f=n=>parseInt(n,2)
f=n=>n.split('').reverse().reduce(function(x,y,i){return(+y)?x+Math.pow(2,i):x;},0)
Demo
f=n=>n.split('').reverse().reduce(function(x,y,i){return(+y)?x+Math.pow(2,i):x;},0)
document.write(f('1011')) // 11
Answered by Oliver on October 27, 2021
long b(long n)=>n>0?n%2+2*b(n/10):0;
Answered by Yytsi on October 27, 2021
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.
Answered by Titus on October 27, 2021
DLḶ2*U,DPS
You know your Jelly code is still golfable when it's above 7 bytes...
It basically consists of two parts
2* generate a list of the powers of two
LḶ for all the powers of 2 from 0 to the length of the binary input
D Convert the binary string into a list to get its length with L
U Then upend that list (for '101010', we now have a list of [32, 16, 8, 4, 2, 1]
, Combine this list
D with the individual digits of the input
P multiply them with eah other [32*1, 16*0, 8*1, 4*0, 2*1, 1*0]
S And sum the result 42 = 32 + 0 + 8 + 0 + 2 + 0
Answered by steenbergh on October 27, 2021
-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
Answered by Dada on October 27, 2021
1QY_%0m@s
QY_ - reverse digits input
1 % - get indecies with a value of 1
0m@ - map(set_nth_bit(0, i), ^)
s - sum(^)
Also 9 bytes
Y_'XltV}+
Y_ - reverse digits
'Xlt - splat(^), len(^)-1
V - repeat length times:
}+ - double and add to stack
Answered by Blue on October 27, 2021
-22 bytes thanks to @cliffroot. Since digit
is a character, it can be converted to it's code via int
, then have 48 subtracted from it to get the actual number. The map was also factored out. I don't know why it seemed necessary.
#(reduce(fn[a d](+(* a 2)(-(int d)48)))%)
(fn[s](reduce #(+(* %1 2)%2)(map #(Integer/parseInt(str %))s)))
-42 bytes (!) by peeking at other answers. My "zipping" was evidently very naïve. Instead of raising 2 to the current place's power, then multiplying it by the current digit and adding the result to the accumulator, it just multiplies the accumulator by 2, adds on the current digit, then adds it to the accumulator. Also converted the reducing function to a macro to shave off a bit.
Thanks to @nimi, and @Adnan!
Ungolfed:
(defn to-dec [binary-str]
(reduce (fn [acc digit]
(+ (* acc 2) digit))
(map #(Integer/parseInt (str %)) binary-str)))
#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range)(reverse %)))
-9 bytes by reversing the string so I don't need to create an awkward descending range.
Well, I'm certainly not winning! In my defense, this is the first program I've ever written that converts between bases, so I had to learn how to do it. It also doesn't help that Math/pow
returns a double that requires converting from, and Integer/parseInt
doesn't accept a character, so the digit needs to be wrapped prior to passing.
#(reduce(fn[a[p d]](+ a(*(Integer/parseInt(str d))(long(Math/pow 2 p)))))0(map vector(range(dec(count %))-1 -1)%))
Zips the string with a descending index representing the place number. Reduces over the resulting list.
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)))
Answered by Carcigenicate on October 27, 2021
Answered by DJMcMayhem on October 27, 2021
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>"))
Answered by Shaun H on October 27, 2021
Reverses a binary string, then adds each digit's value to the sum.
n=>[...n].reverse().reduce((s,d,i)=>s+d*2**i,0)
Demo
f=n=>[...n].reverse().reduce((s,d,i)=>s+d*2**i,0)
document.write( f('101010') ) // 42
Answered by darrylyeo on October 27, 2021
long c(String b){int a=b.length()-1;return a<0?0:b.charAt(a)-48+2*c(b.substring(0,a));}
For some reason I always go straight to recursion. Looks like an iterative solution works a bit nicer in this case...
Answered by Poke on October 27, 2021
Changed to long
/48 bytes:
s->{long x=0;for(char c:s)x=c-48l+x*2;return x;}
Did some golfing/46 bytes:
s->{int x=0;for(char c:s)x=c-48+x*2;return x;}
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;}
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;}
Answered by Roman Gräf on October 27, 2021
Same method as the Haskell answer above.
{y+2*x}/
Example:
{y+2*x}/1101111111010101100101110111001110001000110100110011100000111b
2016120520371234567
Answered by skeevey on October 27, 2021
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.
Answered by Digital Trauma on October 27, 2021
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.
Answered by Xanderhall on October 27, 2021
([]){{}({}<>({}){})<>([])}<>
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.
<>
Answered by DJMcMayhem on October 27, 2021
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:
So for the 101010 case, the following is calculated:
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!
Answered by Adnan on October 27, 2021
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
Answered by Nelson on October 27, 2021
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))
Answered by Kade on October 27, 2021
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.
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
Answered by AdmBorkBork on October 27, 2021
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.
Answered by nimi on October 27, 2021
Converts from binary to unary, then unary to decimal.
1
01
+`10
011
1
Answered by mbomb007 on October 27, 2021
Answered by Emigna on October 27, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP