The title says it all; Given a number in the binary (base-2) number system, output the same number expressed in unary (base-1).
You should take the binary number as a string (optionally with a separator), list, or equivalent structure of digits, using any number or digit you like for the digits. The unary output can use any aforementioned format, and it should use a single-digit throughout the number but does not have to be consistent for different input values. You may choose to assume that the binary number will have no more than 8 bits, and/or that it will always be left-padded with zero bits to a certain length.
One method you may use to achieve this task is documented at this esolangs.org article:
- Replace all
1
s with0*
(Using*
as the unary digit; you may use any character.) - Replace all
*0
s with0**
. - Remove all
0
s.
Here are some examples, using 0
and 1
for the binary digits and *
for the unary digit:
1001
→*********
1010
→**********
00111111
→***************************************************************
00000
→ (empty output)
This is code-golf, so the shortest answer in each language wins.
43 Answers 43
TypeScript's Type System, (削除) 130 (削除ここまで) 128 bytes
//@ts-ignore
type R<S,F,X>=S extends`${infer A}${F}${infer B}`?R<`${A}${X}${B}`,F,X>:S;type B<S>=R<R<R<S,1,"02">,20,"022">,0,"">
Try it at the TypeScript Playground!
Uses 2 as the unary digit. Defines a utility type to recursively remove all occurrences of a given string with a different string, and then defines the main type which is a series of nested calls to the utility type.
-
1\$\begingroup\$ Do you need
//@ts-ignore
? Seems like there's a warning, but not an error, given that it works with and without that ignore comment. Related: Untyped functions in static languages "As code compiles just fine without them, there is no need to add them in." \$\endgroup\$Samathingamajig– Samathingamajig2023年08月14日 03:45:35 +00:00Commented Aug 14, 2023 at 3:45 -
\$\begingroup\$ @Samathingamajig This is the standard for TS submissions but it might make sense to change it \$\endgroup\$noodle person– noodle person2023年08月14日 13:05:49 +00:00Commented Aug 14, 2023 at 13:05
Vyxal, 2 bytes
BI
Try it Online! or see it with asterisks instead
Same as my Thunno 2 answer.
Explanation
BI # Implicit input
B # From binary
I # That many spaces
# Implicit output
-
2\$\begingroup\$ Power
BI
, I guess. \$\endgroup\$The Empty String Photographer– The Empty String Photographer2023年08月11日 16:57:01 +00:00Commented Aug 11, 2023 at 16:57 -
\$\begingroup\$ @The Thonnu : why not just make a new custom byte mapping and call it "implicit solution" ? \$\endgroup\$RARE Kpop Manifesto– RARE Kpop Manifesto2024年05月06日 20:53:50 +00:00Commented May 6, 2024 at 20:53
-
\$\begingroup\$ You’ve got another rude commenter on your post... \$\endgroup\$The Empty String Photographer– The Empty String Photographer2024年05月07日 18:20:41 +00:00Commented May 7, 2024 at 18:20
Excel, 20 bytes
=REPT(9,BIN2DEC(A1))
Input in cell A1
.
Haskell, 26 bytes
f l=10^foldl((+).(2*))0l-1
Input is a list of 0/1
, output is a number like 9999999999
made of the digit 9
.
Haskell is interesting for this challenge because it lacks base-conversion built-ins without imports, so we have to do it ourselves. This answer folds the operation \n b->n*2+b
over the list of bits to get a number k
, then computes 10^k-1
to get a number made of k
9-digits. The 9's trick is shorter than more natural methods like replicate k 1
or 1<$[1..k]
or take k[0,0..]
.
It's slightly longer to do the power-of-10 within the fold and decrement after:
27 bytes
pred.foldl(\n b->n^2*10^b)1
though if we bend the rules and represent bits as 1
or decimal 10
, we can do
21 bytes
pred.foldl((*).(^2))1
Haskell, 26 bytes
foldl(\s b->s++s++[1|b])[]
Input is list of Booleans, output is a list of 1's. This iterates over the list of Booleans, each time doubling the current string then appending an additional 1
if the bit is True
.
-
\$\begingroup\$ I think using other things to represent the digits should be okay, so your 21 byte version is valid. \$\endgroup\$noodle person– noodle person2023年08月12日 06:29:10 +00:00Commented Aug 12, 2023 at 6:29
APL (Dyalog Extended), 3 bytes
Anonymous tacit prefix function. Takes list of binary digits and returns list of 1
s
⊥⍴≡
⊥
the base-2 evaluation
⍴
reshapes
≡
the depth (nesting level, which is always 1 for a list)
TypeScript Type System, 79 bytes
type B<S>=S extends`${infer Q}${infer V}`?`${B<V>}${B<V>}${Q extends"1"?Q:""}`:S
Try it on the Typescript Playground!
Note: This works with little-endian binary, not big-endian.
While the algorithm in the post allows simply performing replacements, we can take advantage of Typescript's ability to anchor string matches for a much simpler algorithm.
Essentially, S extends`${infer Q}${infer V}`
matches the first character Q
and the rest of the string V
. We recurse on V
twice, and append a 1 if Q
is a 1.
-
\$\begingroup\$ Wow, nice, good job! I totally missed this \$\endgroup\$noodle person– noodle person2023年08月12日 18:45:58 +00:00Commented Aug 12, 2023 at 18:45
-
\$\begingroup\$ I can’t use the TS playground on the device I have access to right now, could you confirm this doesn’t hit the recursion limit for any 8-bit binary numbers? Thanks \$\endgroup\$noodle person– noodle person2023年08月12日 18:48:22 +00:00Commented Aug 12, 2023 at 18:48
-
2\$\begingroup\$ @noodleman While this has time complexity proportional to the size of the output, the recursive calls only go log(n) layers deep, so it wouldn't hit the recursion limit until 50-bit binary numbers (and it'd take multiple years to do that anyway) \$\endgroup\$emanresu A– emanresu A2023年08月12日 20:49:33 +00:00Commented Aug 12, 2023 at 20:49
x86+MMX machine code, 10 bytes
Despite the question only saying the input has to be "binary", comments seem to imply they're thinking of a text string of base-2 digits, not 1-bit digits packed into an integer which a computer can already use directly as an unsigned integer. If that's allowed, see my 7-byte answer on Output / Convert to unary number.
This is that answer plus conversion from 8 bytes to an 8-bit integer, by extracting the high bit of each input. Input is in mm0
, an MMX vector register, with the lowest element being the least significant. (If stored to memory, this would be opposite of standard printing order where the most significant goes first, at the lowest address of a string.)
; machine code | NASM source
; RDI or ES:EDI = output buffer of size n+1
binary_to_unary:
; pslld mm0, 7 ; 4 bytes. For input digits '0' / '1', shift the low bit to high
0FD7C8 pmovmskb ecx, mm0 ; pack the binary digits into an integer in ECX
; memset(dst, '1', n)
B031 mov al, '1'
F3AA rep stosb
880F mov byte [rdi], cl ; terminate the C-style string
C3 ret
For ASCII '0'
/ '1'
input, we'd start with pslld mm0, 7
to shift the low bit to the high position of each byte. Also, if the digit-string was loaded from a string in memory in printing order (most significant at lowest address), we'd need to byte-reverse. In that case scalar code to read input would be smaller than movbe
or load+bswap
in an integer register + movq mm0, rax
, or psufb
with an 8-byte vector constant.
In this current version, our input string in an MMX register is effectively big-endian, most significant digit in the highest element number (on the left when writing it in the notation Intel manuals use to document vector instructions).
x86 scalar machine code, 14 bytes, input from a C string in printing order
- RDI or ES:EDI points to an input buffer of base-2 ASCII digits, terminated by a
0
byte (or any byte below ASCII'0'
), padded to at least 32 digits. - RSI or ES:ESI points to an output buffer of size n+1, will be filled with
'0'
digits and terminated with a0
.
Callable from C with the x86-64 System V calling convention as void binary_string_to_unary(const char *binary_src, char *unary_dst);
. Use the x32 ABI for 32-bit pointers, or change the mov edi, esi
to push rsi
/pop rdi
to copy a 64-bit register with the same code size. (Or use the same binary machine code in 32-bit mode.)
binary_string_to_unary:
B030 mov al, '0' ; input digit to compare against, also the output digit
.loop:
11C9 adc ecx, ecx ; ECX = 2*ECX + CF
AE scasb ; set FLAGS like cmp al, [rdi] then increment RDI. CF=1 for digit='1', CF=0 for digit='0'.
76FB jbe .loop ; while('0' <= digit); i.e. while digit >= '0', false for digit = 0 terminator
89F7 mov edi, esi ; x32 ABI, or for 32-bit mode. For full 64-bit pointers, push rsi / pop rdi
F3AA rep stosb ; memset(rdi, al='0', rcx)
880F mov [rdi], cl ; terminate the C-style string
C3 ret
Note that we don't xor ecx,ecx
before the loop. Instead we rely on the input string being '0'-padded to at least 32 digits, so the previous contents get shifted out.
There might be a way (with same code size) to take the input pointer in RSI like you'd expect from the traditional meanings of those registers, perhaps with lodsb
/ cmp al, '0'
(3 bytes instead of 1 for scasb, but avoiding the 2-byte mov edi, esi
after the loop). Change the branch conditions accordingly for comparing in the other direction. Except that would get CF=0 for digit='1'. So maybe add al, 255-'0'
so '1' produces a carry-out but '0' doesn't? And the terminator is a value that results in some FLAGS condition that the other two don't, perhaps a signed overflow and/or the sign flag.
-
\$\begingroup\$ Ah yes, this is what I came here for! \$\endgroup\$Galaxy– Galaxy2023年08月14日 06:44:43 +00:00Commented Aug 14, 2023 at 6:44
-
\$\begingroup\$ The question allows different unary characters for different inputs, but for implicit-length string output we need to avoid AL=0 for non-zero input. So I don't see a way to save the
mov al, '1'
or reduce it to 1 byte. Taking another input there and doingxchg eax, edi
would be 1 byte, but would just swap in whatever garbage is there.salc
with non-zero CF could work, orlahf
to get non-zero AH if we were usingstosw
UTF-16 strings in 16-bit mode. (stosw
takes 2 bytes in other modes.) \$\endgroup\$Peter Cordes– Peter Cordes2023年08月14日 17:04:15 +00:00Commented Aug 14, 2023 at 17:04 -
brainfuck, 53 bytes
Takes a string of 0
and 1
characters, outputs a string of 1
s.
>,[>-[<->-----]<+++<[->++<]>>,]>-[<+>-----]<--<[->.<]
Explaination
>,[ read a character
>-[<->-----]<+++ subtract 48 to turn it into 0/1
<[->++<] double the existing sum and add it to the new digit
>>,] read another character and repeat if not EOF
>-[<+>-----]<-- make 49
<[->.<] print 49 the necessary number of times
-
\$\begingroup\$ Welcome to Code Golf, and nice answer! \$\endgroup\$2023年08月16日 04:10:50 +00:00Commented Aug 16, 2023 at 4:10
Mathematica, 14 bytes
As a list of '1's:
Table[1,2^^#] &
Anonymous function. Would probably be 10 bytes in the hypothetical mthmca golfing language.
-
\$\begingroup\$ The output can be a list. Also, the character doesn't have to be "*" if using, say, a digit, would be shorter. \$\endgroup\$noodle person– noodle person2023年08月11日 16:37:10 +00:00Commented Aug 11, 2023 at 16:37
-
\$\begingroup\$ @noodleman Thanks. Revised accordingly and saving 13 bytes. \$\endgroup\$Michael Stern– Michael Stern2023年08月11日 16:40:20 +00:00Commented Aug 11, 2023 at 16:40
-
\$\begingroup\$ What version does this work in? AFAIK
^^
only works in number literals. \$\endgroup\$att– att2023年09月03日 07:55:02 +00:00Commented Sep 3, 2023 at 7:55
TI-Basic, 15 bytes
1 or rand(.5sum(Ans2^cumSum(1 or Ans
Input is taken as a list of 0
s and 1
s in little-endian binary in Ans
. Output is a list of 1
s.
Perl 5, 15 bytes
$_=9x oct"0b$_"
Outputs 9 (my chosen char) the number of times given in the input binary number.
R, 22 bytes
\(x)rep(1,strtoi(x,2))
Convert from binary and repeat 1
that many times.
Unfortunately shorter than the more-interesting (I think):
R, (削除) 36 (削除ここまで) 34 bytes
Edit: -2 bytes thanks to pajonk
\(x)Reduce(\(a,b)c(a,a,b[b]),x,{})
Input is a vector of binary digits; fold over (Reduce
) this from the left, starting with an empty vector (NULL
), at each step duplicating whatever we've got so far, and appending the new digit if it's a 1
.
-
\$\begingroup\$ -2 on the second one by using
{}
for the empty vector. \$\endgroup\$pajonk– pajonk2023年08月12日 12:43:28 +00:00Commented Aug 12, 2023 at 12:43 -
\$\begingroup\$ @pajonk - Ah, yes, thanks! \$\endgroup\$Dominic van Essen– Dominic van Essen2023年08月12日 13:23:00 +00:00Commented Aug 12, 2023 at 13:23
Ruby, 20 bytes
->(b){?**b.to_i(2)}
It goes from binary to a decimal integer, and becomes a factor by which an asterisk char is multiplied.
(Idea to switch to char from string was suggested by Travis. Thanks!)
Ruby, 21 bytes | (old)
->(b){"*"*b.to_i(2)}
Same as the upper one, but the upper one has been improved.
-
\$\begingroup\$ Welcome to Code Golf, and nice answer! \$\endgroup\$2023年08月12日 17:47:07 +00:00Commented Aug 12, 2023 at 17:47
-
\$\begingroup\$ Thank you! Glad to be here :) \$\endgroup\$kait0u– kait0u2023年08月12日 18:03:14 +00:00Commented Aug 12, 2023 at 18:03
-
1\$\begingroup\$ You can remove a byte by using
?*
for"*"
instead of quotes. \$\endgroup\$Travis– Travis2023年08月14日 16:28:35 +00:00Commented Aug 14, 2023 at 16:28
C (clang), (削除) 60 (削除ここまで) 58 bytes
i;f(char*s){for(i=0;*++s;i+=i+*s-48);i&&printf("%0*d",i);}
-
\$\begingroup\$ It feels like there should be a way to omit the
,0
arg to printf and just have it print whatever garbage was left. Or just spaces? Butprintf("%*c",i)
prints a byte of garbage at the end, and we probably can't consider that a "terminator". Perhapsfor(;i--;)puts("");
to use newline as the unary character? \$\endgroup\$Peter Cordes– Peter Cordes2023年08月14日 22:44:17 +00:00Commented Aug 14, 2023 at 22:44 -
\$\begingroup\$ Or if you want to write a function that returns a string instead of printing, perhaps
memset(s,7,i);s[i]=0;
to replace the input string with that many ASCII "BEL" characters and a terminator, but that might not be shorter. Ormemset(...); return i;
for an explicit-length string. (And relies on the caller to allocate a large enough buffer without having parsed the string of binary digits, so only a larger fixed-size buffer could work.) \$\endgroup\$Peter Cordes– Peter Cordes2023年08月14日 22:47:20 +00:00Commented Aug 14, 2023 at 22:47 -
1\$\begingroup\$ @PeterCordes Good ideas, but I only managed to get the first one to work (leaving off
,0
). Thanks anyways! \$\endgroup\$corvus_192– corvus_1922023年08月16日 18:11:36 +00:00Commented Aug 16, 2023 at 18:11 -
\$\begingroup\$ Doesn't seem to work anymore; 58 byte with spaces as digits \$\endgroup\$Mukundan314– Mukundan3142024年05月06日 14:51:39 +00:00Commented May 6, 2024 at 14:51
-
\$\begingroup\$ 55 bytes with Peter's suggestion of newline as unary char \$\endgroup\$Mukundan314– Mukundan3142024年05月06日 14:56:10 +00:00Commented May 6, 2024 at 14:56
J, 4 or 5 bytes
#.##
Uses the length of the input digit list for the unary digit.
Like 05AB1E, uniformity is one extra byte, with alternatives.
Uiua, (削除) 6 (削除ここまで) 4 bytes
⊚°⋯⇌
Convert from binary, use ⊚
where to change this to an array of N 0s.
Before I knew about °⋯
:
Uiua, 13 bytes
×ばつn:2⇌⇡⧻.
Multiply by powers of 2, sum, range, multiply each by 0.
Binary Lambda Calculus: 81 bits = 10.125 bytes
Lambda calculus has no standard encoding for binary numbers. I chose the conversion from my favorite base 2 encoding to unary Church numerals.
Mogensen's general encoding for arbitrary base b is defined by
$$ \langle n\rangle_b=\lambda^{S(b)}(d_0\circ\dots\circ d_{\lfloor\log_b(n)\rfloor}\ b) $$ $$ \text{where de Bruijn index }\ d_i=\frac{n}{b^i}\pmod{b} $$
E.g. $$\langle6\rangle_2=\lambda^3(0\ (1\ (1\ 2)))$$
Conversion from b=2 to Church numerals follows by applying $$(\langle n\rangle_2\ \langle0\rangle_u\ (\mathrm{succ}_u\circ(\mathrm{mult}_u\ \langle2\rangle_u))\ (\mathrm{mult}_u\ \langle2\rangle_u))$$
Which golfs down to a function of 81 bits length:
000101011000001000000001110010111101100101111011010000000010111101100101111011010
I wasn't able to share the two curried multiplication functions completely since additional abstractions/indices actually increased the size. Maybe someone else here has some better ideas?
Trying-to-be-clever 84 bit alternative:
000100010101110000010000000011100101011111011101101010000000010111101100101111011010
-
1\$\begingroup\$ Nice solution. I’ve edited in the fractional byte count. \$\endgroup\$noodle person– noodle person2024年04月12日 13:49:46 +00:00Commented Apr 12, 2024 at 13:49
Thunno 2, 2 bytes
Ḃṣ
Try it online! or see it with asterisks instead
Uses spaces.
Explanation
Ḃṣ # Implicit input
Ḃ # From binary
ṣ # That many spaces
# Implicit output
Charcoal, 3 bytes
⍘S2
Try it online! Link is to verbose version of code. Outputs a string of -
s. Explanation:
S Input string
⍘ Convert from base
2 Literal integer `2`
Print as row of `-`s
Unfortunately BaseString(2, InputString())
performs a different operation, which means I can't use implicit input to save a byte.
Arturo, 23 bytes
$=>[@.of:from.binary&1]
Returns a list of digits.
$=>[ ; a function where input is assigned to &
from.binary& ; convert input from binary string to decimal integer
@.of: _ 1 ; create list of that many 1s
] ; end function
Retina 0.8.2, 16 bytes
1
01
+`10
011
0
Try it online! Link includes test cases. Explanation: A direct interpretation of the method given in the question, except using 1
instead of *
for obvious reasons. Note that the method in Retina's own tutorial is slightly different preferring to use ^0+
presumably for a slight performance improvement.
MathGolf, 3 bytes
Some different alternatives are available:
- Output as
*
s:å⌂*
;åÄ⌂
;å{⌂
. - Output as spaces:
å *
;åÄ
;å{
. - All six above should have been also possible with a binary-list instead of binary-string as input, replacing the
å
withä
, but unfortunately there seems to be a bug with leading0
s apparently.. - Tryä⌂*
online.
Explanation:
å # Convert the (implicit) input binary-string to a base-10 integer
⌂* # Repeat that many "*" as string
* # Or alternatively, repeat that many spaces as string
# (after which the entire stack is output implicitly as result)
å # Convert the (implicit) input binary-string to a base-10 integer
Ä # Pop and loop that many times, using the following character as inner code-block:
{ # Or alternatively, use everything after it as code-block:
⌂ # Push an "*" to the stack every iteration
# Or alternatively, push a space character to the stack every iteration
# (after which the entire stack is joined together and output implicitly as result)
05AB1E, 3 bytes
Since outputting the unary as a single character is required, there are a couple of 3 bytes alternatives:
- Output as spaces:
×ばつ
- Try it online or verify all test cases; - Output as 1s:
×ばつ
- Try it online or verify all test cases; - Output as 0s:
×ばつ
- Try it online or verify all test cases; - Output as any digit (as a list of characters):
CÅ9
(where the9
could be any other digit) - Try it online or verify all test cases.
If a mixture of multiple characters for the unary output would have been allowed, since only the length matters in unary, it could have been 2 bytes with:
C∍
Outputs a mixture of 1
s and 0
s (depending on the input) for its unary output.
Try it online or verify all test cases.
Explanation:
C # Convert the (implicit) input binary-string to a base-10 integer
×ばつ # Pop and push a string with that many spaces
# (after which the result is output implicitly)
$ # Push 1 and the input binary-string×ばつ
Î # Or alternatively, push 0 and the input binary-string
C # Convert the binary-string to a base-10 integer
×ばつ # Repeat the 1 or 0 that many times as string
# (after which the result is output implicitly)
C # Convert the (implicit) input binary-string to a base-10 integer
Å9 # Pop and push a list with that many 9s (or any other digit)
# (after which the result is output implicitly)
C # Convert the (implicit) input binary-string to a base-10 integer
∍ # Extend/shorten the (implicit) input binary-string to that length
# (after which the result is output implicitly)
///, 18 bytes
/1/0*//*0/0**//0//
I didn't write this, I borrowed it from the esolangs wiki. Here's how it works:
Let's start with the string 10101
, which represents 21.
/1/0*/
replaces 1
s with 0*
. The string becomes 0*00*00*
. In this, each *
represents a sort of place value - for example, the first *
has 4 0
s after it, so it represents 24 = 16.
/*0/0**/
replaces each *
before a zero with two copies of it after the zero, each with half the place value. The first replacement this would do would be replacing 0*00*00*
with 00**0*00*
, replacing a *
representing 16 with 2 *
s each representing 8.
In ///
, replacements are repeated until nothing is left to replace, so this will eventually result in a string with some amount of 0s at the start, followed by 21 *
s each representing 1.
Finally, /0//
removes the leading zeros, leaving just 21 *
s, which is the output in unary.
any reasonable input & output format
I'm guessing taking the input as an integer is not acceptable, but it would be good to state it explicitly. \$\endgroup\$unsigned
int); that's a good way to store binary! \$\endgroup\$