35
\$\begingroup\$

Take a string of binary characters separated by a space, and convert it to an ASCII string.

For example...

1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100

Would convert to...

Hello World

This is a code-golf challenge so the shortest solution wins.

\$\endgroup\$
3
  • 21
    \$\begingroup\$ +1 for making a challenge without story and other fripperies, straight to the point \$\endgroup\$
    – bebe
    Jul 25, 2014 at 18:21
  • 17
    \$\begingroup\$ @bebe Fictitious fantastical fripperies form half the fun. \$\endgroup\$
    – qwr
    Jul 25, 2014 at 23:59
  • 1
    \$\begingroup\$ Hello. Let's imagine that your technology is so advanced that it does not support ASCII. Would it be allowed to convert to the native character encoding, or would it have to convert ASCII to the native character encoding? I'm thinking ZX81 here. \$\endgroup\$ Apr 16, 2019 at 14:50

69 Answers 69

12
\$\begingroup\$

JavaScript (ES6) 49 55 56 64

s.replace(/\d+./g,x=>String.fromCharCode('0b'+x))

Edit Accepting @bebe suggestion - thanks
Edit2 Didn't know about binary numeric literal - thanks @kapep
Edit3 Wow 6 not 4 bytes saved thx @ETHproductions

Explanation as requested in comments

String.replace can take 2 arguments:

  • regular expression /\d+./g : one or more digits followed by one different character - the g flag specify to search the pattern more than once
  • a function, here specified in arrow format, where the argument (x) wil be the found string (the sequence of digits eventually followed by a space) and the value of the function is what is replaced (in this case, the single character from the code).

It's worth noting that the at the end of the string the regexp matches the sequence of digits without a trailing space, in this case the dot matches the last digit. Try '123'.match(/(\d+)./) to verify.

(Still) one of the more verbose pieces of javascript ever...
(Assignment to string s not counted)

var s='1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100'
var x=
s.replace(/\d+./g,x=>String.fromCharCode('0b'+x))

console.log(x)

\$\endgroup\$
10
  • 2
    \$\begingroup\$ s.replace(/\d+./g,x=>String.fromCharCode(parseInt(x,2))) 56 \$\endgroup\$
    – bebe
    Jul 25, 2014 at 22:35
  • 2
    \$\begingroup\$ s.replace(/\d+./g,x=>String.fromCharCode(eval("0b"+x))) 55 \$\endgroup\$
    – kapex
    Jul 26, 2014 at 4:02
  • \$\begingroup\$ Can you please explain what the /\d+./g,x=>does? \$\endgroup\$
    – izlin
    Jul 28, 2014 at 5:38
  • 1
    \$\begingroup\$ @izlin I added some explanation to the answer \$\endgroup\$
    – edc65
    Jul 28, 2014 at 6:59
  • \$\begingroup\$ I know this is an old answer, but you can change eval('0b'+x) to '0b'+x-0 to save 4 bytes. \$\endgroup\$ Jan 12, 2017 at 19:49
10
\$\begingroup\$

Ruby, 36 32

s.split.map{|x|x.to_i(2).chr}*""

Or 31

s.gsub(/\w+ ?/){$&.to_i(2).chr}

Optimizations thanks to Chron

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You could substitute .join"" for *"" to save a few characters. You could also do it with gsub instead of split+map+join, something like: s.gsub(/\w+ ?/){$&.to_i(2).chr} (31 chars). \$\endgroup\$ Jul 27, 2014 at 23:41
  • 2
    \$\begingroup\$ s.gsub(/\d+./){$&.to_i(2).chr} works and it's 30 chars, I have no idea why it works though. The . shouldn't match the last time but it does. \$\endgroup\$
    – addison
    Jul 30, 2014 at 4:58
8
\$\begingroup\$

Bash+common linux utils, 25 bytes

dc<<<2i$s[Pz0\<m]dsmx|rev

dc explanation

  • push 2 to the stack; pop and use as input radix
  • push input string to stack (all values at once)
  • Define recursive macro m to:
    • pop, then print value as ASCII
    • push stack depth to stack
    • push 0 to stack
    • pop top 2 stack values; compare and call m macro if stack non-empty
  • duplicate top of stack (macro definition)
  • pop and save macro to m register
  • pop and execute macro

Because we push the whole binary string to the stack first, when we pop each value, we end up with the string reversed. So we use the rev utility to correct that.

Example usage:

$ s="1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100"
$ dc<<<2i$s[Pz0\<m]dsmx|rev
Hello World
$ 
\$\endgroup\$
7
\$\begingroup\$

PowerShell, 49

-join(-split$s|%{[char][convert]::toint32($_,2)})

EDIT: Didn't see the other PowerShell answer. But there is essentially only one way of solving this.

\$\endgroup\$
7
\$\begingroup\$

C - 57 43 38/31

38 Byte version:

for(int*x=s;putchar(strtol(x,&x,2)););

Or only 31 bytes if s is a pointer:

while(putchar(strtol(s,&s,2)));

I don't think this is exactly how for and while loop are supposed to be used... but it works.

\$\endgroup\$
6
\$\begingroup\$

Mathematica, 52 bytes

Ah, Mathematica's lovely function names

f=FromCharacterCode[#~FromDigits~2&/@StringSplit@#]&
\$\endgroup\$
6
\$\begingroup\$

Pyth, 12

smCv+"0b"dPZ

Note that s is not a legal variable in Pyth, so I used Z instead.

Explanation:

        print(
s             sum(
m                 map(lambda d:
C                     chr(
v                         eval(
+"0b"d                         "0b"+d)),
P                     split(
Z                           Z))))

Example:

=Z"<the binary string from above>"smCv+"0b"dPZ
Hello World
\$\endgroup\$
6
  • \$\begingroup\$ The fact it does not use whitespace in the formatting (here's looking at you Python) is a major +1 \$\endgroup\$
    – Pharap
    Jul 27, 2014 at 17:08
  • \$\begingroup\$ @Pharap Yeah, one way of looking at Pyth is it's Python with all of the elements that make it take more characters removed, like whitespace, parenthesis, multi-character tokens, etc. \$\endgroup\$
    – isaacg
    Jul 27, 2014 at 20:37
  • \$\begingroup\$ I don't know Pyth, but would it not save 4 characters to use id2 in place of v+"0b"d? In any case, this is both unreadable and cool. \$\endgroup\$
    – DLosc
    Oct 5, 2014 at 3:10
  • \$\begingroup\$ @DLosc I added that function to Pyth after this question was asked, in large part due to this question. It would be shorter with present day Pyth, but present day Pyth is not allowed for this challenge. \$\endgroup\$
    – isaacg
    Oct 5, 2014 at 3:38
  • \$\begingroup\$ I see. I wondered if it might be something like that. \$\endgroup\$
    – DLosc
    Oct 5, 2014 at 3:40
6
\$\begingroup\$

x86 machine code on DOS - 22 bytes

00000000  30 d2 b4 08 cd 21 2c 30  72 06 d0 e2 08 c2 eb f2  |0....!,0r.......|
00000010  b4 02 cd 21 eb ea                                 |...!..|

Since there are no real string variables in machine code (and in particular, no variables named "s") I settled for stdin as input.

NASM input:

    org 100h

section .text

start:
    xor dl,dl
loop:
    mov ah,8
    int 21h
    sub al,'0'
    jb print
    shl dl,1
    or dl,al
    jmp loop
print:
    mov ah,2
    int 21h
    jmp start
\$\endgroup\$
6
\$\begingroup\$

Powershell (52 49)

-join(-split$s|%{[char][convert]::ToInt16($_,2)})

Simple loop over binary string in $s. Having to include the [convert] kills my score though.

EDIT: There really is only one way of pulling this off in Powershell, wowie. Joey and I both got pretty much the same answer working independently!

Input:

1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100

Output:

Hello World
\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can use the unary split operator, saving three characters (at which point our answers are identical ... big surprise ;-)). \$\endgroup\$
    – Joey
    Jul 25, 2014 at 22:06
  • \$\begingroup\$ @Joey Ohh, good point! Can't believe I missed that. You get the +1 from me for catching that, thanks! \$\endgroup\$
    – fuandon
    Jul 26, 2014 at 2:53
5
\$\begingroup\$

Perl 33 32

Edit: Updated solution, 32.

say$s=~s/\d+ ?/chr oct"0b$&"/rge

Previous solution (33):

$_=$s;say map{chr oct"0b$_"}split

or

say map{chr oct"0b$_"}split/ /,$s

Test:

perl -E '$s="1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100";$_=$s;say map{chr oct"0b$_"}split'
\$\endgroup\$
5
\$\begingroup\$

J (23)

u:;(#.@:("."0))&.>cut s

Test:

   s=:'1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100'
   u:;(#.@:("."0))&.>cut s
Hello World

Explanation:

                  cut s    NB. split S on spaces
   (          )&.>         NB. for each element
        ("."0)             NB. evaluate each character
      @:                   NB. and
    #.                     NB. convert bitstring to number
  ;                        NB. unbox each number
u:                         NB. convert to ASCII
\$\endgroup\$
4
\$\begingroup\$

Golfscript - 21

' '/{1/{~}%2base}%''+

You can test it here.

\$\endgroup\$
4
\$\begingroup\$

Python shell  44  40 chars

''.join(chr(int(x,2))for x in s.split())

Thanks for the help Griffin.

\$\endgroup\$
1
  • \$\begingroup\$ ''.join(chr(int(x,2))for x in s.split()) \$\endgroup\$
    – Griffin
    Jul 25, 2014 at 17:55
4
\$\begingroup\$

APL (15)

⎕UCS{2⊥⍎¨⍕⍵}¨⍎s

Test:

      s←'1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100'
      ⎕UCS{2⊥⍎¨⍕⍵}¨⍎s
Hello World

Explanation:

  • ⍎s: evaluate s, turning it into an array of integers. Arrays are written as numbers separated by spaces, so this splits s.
  • {...: for each element:
    • ⍕⍵: turn the number back into a string
    • ⍎¨: evaluate each individual digit, giving a bitstring
    • 2⊥: base-2 decode, giving the numbers
  • ⎕UCS: get the character for each number
\$\endgroup\$
3
4
\$\begingroup\$

PHP (61)

<?=join(array_map('chr',array_map('bindec',explode(' ',$s))))
\$\endgroup\$
2
  • \$\begingroup\$ foreach(str_split($s,8)as$v)echo chr(bindec($v)); \$\endgroup\$ Mar 29, 2017 at 11:15
  • \$\begingroup\$ @JörgHülsermann the encoding may skip leading zeros therefore str_split($s,8) won't work. foreach(explode(' ',$s)as$v)echo chr(bindec($v)); would be valid but I don't plan to edit one of my first PPGC answers that clearly isn't really golfed anyway. Thank you anyway! \$\endgroup\$
    – Christoph
    Mar 29, 2017 at 12:46
4
\$\begingroup\$

Bacchus, 25 bytes

S,' 'j:A=(Ö,2,10b:c),A¨

Explanation:

S,' 'j split the String S by the empty space and converts it to a block (some sort of array).

:A= get the previous Block and assing it to A variable.

(),A¨ for Each element in A

Ö,2,10b Read the current element (represent by Ö) in base 2 and transform it to base 10.

:c get the previous value and print as char

\$\endgroup\$
3
\$\begingroup\$

GolfScript 23

' '/{[{49=}/]2base}%''+

Online test here.

\$\endgroup\$
3
\$\begingroup\$

C - 63

since C has no base 2 converter in standard library: test here
edit: there is, i'm just too stupid to know about it

r;f(char*s){for(;*s;(*s|32)-32||(putchar(r),r=0))r=2*r|*s++&1;}
\$\endgroup\$
3
\$\begingroup\$

Run Length Encoded Brainfuck, 49 bytes

Since there are no variables in Brainfuck, I just used standard input and output instead.

The code 32+ should be interpreted as 32 +s by the interpreter. Just replace them manually if your interpreter doesn't support RLE.

>,[32->+<[16-<[>++<-]>[<+>-]>-<]>[<<.[-]>>-]<,]<.

Expanded (non-RLE) version: (91 bytes)

>,[-------------------------------->+<[----------------<[>++<-]>[<+>-]>-<]>[<<.[-]>>-]<,]<.

The code assumes that EOF is encoded as 0.

Explanation

The following layout is used:

+---+---+------+
| x | a | flag |
+---+---+------+

Where x is the ASCII byte to be printed, a is the a character from standard input and flag is 1 if a was a space.

>,            Read a character a into the second cell
[             While not EOF: 
  32-           Decrease a by 32 (a -= ' ')
  >+<           Set the flag to 1 
  [             If a was not a space:
    16-           Decrease by 16 more ('0' == 32+16)
    <[>++<-]      a += 2*x
    >[<+>-]       Move it back (x = a)
    >-<           Reset the flag, it was not a space.
  ]>
  [             If a was a space (flag == 1):
    <<.[-]        Print and reset x
    >>-           Reset the flag
  ]
  <,            Read the next caracter a
]
<.            Print the last character x
\$\endgroup\$
2
  • 1
    \$\begingroup\$ +1 Because everything should have a brainfuck implementation. \$\endgroup\$
    – Pharap
    Jul 27, 2014 at 17:09
  • \$\begingroup\$ Is "Run Length Encoded Brainfuck" an actual separate language? I can't find an interpreter. \$\endgroup\$
    – mbomb007
    Mar 29, 2017 at 15:31
3
\$\begingroup\$

Java 8 : 60 bytes

Using lambdas in Java 8 (75 bytes):

Arrays.stream(s.split(" ")).reduce("",(a,b)->a+(char)Byte.parseByte(b,2));

And if you allow static imports (which some here used) it is (61 bytes):

stream(s.split(" ")).reduce("",(a,b)->a+(char)parseInt(b,2))

A tiny bit shorter version using for loop (60 bytes):

for(String n:s.split(" ")){out.print((char)parseInt(n,2));}
\$\endgroup\$
2
  • 2
    \$\begingroup\$ What, they actually made a replacement for the monstrosity known as anonymous class? Awesome. \$\endgroup\$
    – seequ
    Jul 28, 2014 at 8:53
  • \$\begingroup\$ @Sieg yes Java has lambdas/closures now as well, but it is mostly synthetic sugar on top of anonymous classes... (obviously) \$\endgroup\$ Jul 28, 2014 at 12:39
3
\$\begingroup\$

Clojure 63 (or 57)

The all-Clojure impl:

(apply str(map #(char(read-string(str"2r"%)))(re-seq #"\d+"s)))

With Java interop:

(apply str(map #(char(Long/parseLong % 2))(.split s" ")))

REPL session:

golf> (def s "1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100")
#'golf/s
golf> (apply str(map #(char(read-string(str"2r"%)))(re-seq #"\d+"s)))
"Hello World"
golf> (apply str(map #(char(Long/parseLong % 2))(.split s" ")))
"Hello World"
\$\endgroup\$
3
\$\begingroup\$

QBasic, 103

s$=s$+" ":FOR i=1 TO LEN(s$):c$=MID$(s$,i,1):IF c$=" "THEN n=0:r$=r$+CHR$(n)ELSE n=n*2+VAL(c$)
NEXT:?r$

What? We have no fancy binary-to-decimal functions here. Do it yourself!

I'm counting the newline (which I think is necessary to get the if-then-else without an END IF) as one byte, per this meta post. I don't know whether QB64 on Windows would accept a code file that way or not. Probably doesn't much matter.

\$\endgroup\$
2
\$\begingroup\$

NodeJS62

Buffer(s.split(' ').map(function(a){return parseInt(a,2)}))+''

PHP75

array_reduce(explode(' ', $b),function($a,$b){return $a.chr(bindec($b));});
\$\endgroup\$
4
  • \$\begingroup\$ how do you run nodejs with es6 compatibility? the latest one still does not support lambda functions for me \$\endgroup\$
    – bebe
    Jul 26, 2014 at 14:35
  • \$\begingroup\$ @bebe Arrow functions are implemented in v8 but they aren't integrated with node yet. I'll edit my post. \$\endgroup\$
    – c.P.u1
    Jul 26, 2014 at 15:05
  • \$\begingroup\$ @c.P.u1 they work for me \$\endgroup\$ Jan 12, 2017 at 21:03
  • \$\begingroup\$ -16 bytes suggested by an anonymous user \$\endgroup\$ Apr 7, 2021 at 6:26
2
\$\begingroup\$

JavaScript 111

This does the number conversion without parseInt or eval. Reading the string backwards and counting bits it set's bit x if it's a one. When a space is found a the number is converted to a char and a new 0 number is started for setting bits.

x=n=0,w='',s=' '+s
for(i=s.length;i--;){m=s[i]
if(m==1)n|=1<<x
x++
if(m==' ')w=String.fromCharCode(n)+w,n=x=0
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ +1 for doing it the old-fashioned way--inspired me to write a QBasic version, too. \$\endgroup\$
    – DLosc
    Oct 5, 2014 at 3:29
  • \$\begingroup\$ Invalid, needs to be a function or full program (one that takes input) \$\endgroup\$
    – ASCII-only
    Jan 4, 2019 at 0:46
2
\$\begingroup\$

Groovy 64

{it.split(" ").collect{Integer.parseInt(it,2) as char}.join("")}
\$\endgroup\$
2
\$\begingroup\$

CJam, 11 bytes

NS/{:~2bc}/

s isn't a legal variable name in CJam, so I chose N instead.

Try it online.

Example run

$ cjam <(echo '
> "1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100"
> :N;
> NS/{:~2bc}/
> '); echo
Hello World

How it works

NS/            " Split N at spaces.                            ";
   {     }/    " For each chunk:                               ";
    :~         "   Evaluate each character ('0' ↦ 0, '1' ↦ 1). ";
      2b       "   Convert from base 2 array to integer.       ";
        c      "   Cast to character.                          ";
\$\endgroup\$
2
\$\begingroup\$

Haskell -- 48 (+13 imports (?))

Here's my first golf attempt in Haskell.

map(chr.foldl1((+).(*2)).map digitToInt)$words s

You need to import Data.Char

usage (in ghci):

Prelude> :m +Data.Char
Prelude Data.Char> let s = "1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100"
Prelude Data.Char> map(chr.foldl1((+).(*2)).map digitToInt)$words s
"Hello World"

Explanation:

map(chr.foldl1((+).(*2)).map digitToInt)$words s
                                        $words s -- split s on spaces into a list
                         map digitToInt          -- convert each digit in input string to int
              ((+).(*2))                         -- a function that multiplies its first 
-- argument by 2, then adds the second argument
        foldl1((+).(*2)).map digitToInt          -- fold the above over the list of ints: 
-- in other words this is a function that reads strings as binary and gives the value as int
   (chr.foldl1((+).(*2)).map digitToInt)         -- cast to character
map(chr.foldl1((+).(*2)).map digitToInt)$words s -- map our function over the list of words
\$\endgroup\$
1
  • \$\begingroup\$ Hopefully I've followed scoring conventions correctly regarding imports. Feel free to edit in a correction if I haven't. I treated the ":m +Data.Char" needed to import in ghci as 13. \$\endgroup\$
    – ballesta25
    Jul 26, 2014 at 2:30
2
\$\begingroup\$

Vyxal s, 3 bytes

vBC

Try it Online!

How?

vBC
vB   # Vectorized convert to decimal
  C  # Convert character codes to list of characters
     # S flag concatenates result

If we have to receive input separated by spaces, then:

Vyxal s, 4 bytes

⌈vBC

Try it Online!

\$\endgroup\$
2
\$\begingroup\$

Zsh, 27 26 22 bytes

-1 from roblogic, -4 from a new strategy using an array and ${a/b/c} replacement.

printf %s ${(#)@/#/2#}

Try it online! Try it online! Try it online!

The (#) flag causes arithmetic expansion to be done to the contents of the parameter. Flags are parsed after the replacement. # matches the start of a string when at the start of a ${ / / } pattern. So each parameter is # prefixed with 2#, which Zsh recognizes as a base 2 number when (#) arithmetic expansion is done.


This relies on flexible I/O, each group of bits in its own parameter. This is what the pure bash answer does as well. To parse a single string, +4 bytes are needed: (Example)

printf %s ${(#)${=1}/#/2#}
\$\endgroup\$
1
  • \$\begingroup\$ use printf and you dont need to append \\c, saving 1 byte \$\endgroup\$
    – roblogic
    Sep 3, 2019 at 0:29
1
\$\begingroup\$

GNU Sed, 19 bytes

Inspired by an excellent @Digital Trauma answer.

Golfed

s/\w*/dc -e2i&P;/eg

Test

echo 1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100|\
sed 's/\w*/dc -e2i&P;/eg'

Hello World
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.