27
\$\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

The binary string will be stored in a variable called s.

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

\$\endgroup\$
  • 15
    \$\begingroup\$ +1 for making a challenge without story and other fripperies, straight to the point \$\endgroup\$ – bebe Jul 25 '14 at 18:21
  • 9
    \$\begingroup\$ @bebe Fictitious fantastical fripperies form half the fun. \$\endgroup\$ – qwr Jul 25 '14 at 23:59
  • \$\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\$ – Shaun Bebbers Apr 16 at 14:50

56 Answers 56

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\$
  • 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\$ – Paul Prestidge Jul 27 '14 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 '14 at 4:58
10
\$\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\$
  • 2
    \$\begingroup\$ s.replace(/\d+./g,x=>String.fromCharCode(parseInt(x,2))) 56 \$\endgroup\$ – bebe Jul 25 '14 at 22:35
  • 2
    \$\begingroup\$ s.replace(/\d+./g,x=>String.fromCharCode(eval("0b"+x))) 55 \$\endgroup\$ – kapex Jul 26 '14 at 4:02
  • \$\begingroup\$ Can you please explain what the /\d+./g,x=>does? \$\endgroup\$ – izlin Jul 28 '14 at 5:38
  • 1
    \$\begingroup\$ @izlin I added some explanation to the answer \$\endgroup\$ – edc65 Jul 28 '14 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\$ – ETHproductions Jan 12 '17 at 19:49
9
\$\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\$

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\$
  • \$\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 '14 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 '14 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 '14 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 '14 at 3:38
  • \$\begingroup\$ I see. I wondered if it might be something like that. \$\endgroup\$ – DLosc Oct 5 '14 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\$
  • 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 '14 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 '14 at 2:53
5
\$\begingroup\$

Mathematica, 52 bytes

Ah, Mathematica's lovely function names

f=FromCharacterCode[#~FromDigits~2&/@StringSplit@#]&
\$\endgroup\$
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\$
  • \$\begingroup\$ ''.join(chr(int(x,2))for x in s.split()) \$\endgroup\$ – Griffin Jul 25 '14 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\$
4
\$\begingroup\$

PHP (61)

<?=join(array_map('chr',array_map('bindec',explode(' ',$s))))
\$\endgroup\$
  • \$\begingroup\$ foreach(str_split($s,8)as$v)echo chr(bindec($v)); \$\endgroup\$ – Jörg Hülsermann Mar 29 '17 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 '17 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\$
  • 1
    \$\begingroup\$ +1 Because everything should have a brainfuck implementation. \$\endgroup\$ – Pharap Jul 27 '14 at 17:09
  • \$\begingroup\$ Is "Run Length Encoded Brainfuck" an actual separate language? I can't find an interpreter. \$\endgroup\$ – mbomb007 Mar 29 '17 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
    \$\begingroup\$ What, they actually made a replacement for the monstrosity known as anonymous class? Awesome. \$\endgroup\$ – seequ Jul 28 '14 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\$ – Roy van Rijn Jul 28 '14 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\$
  • \$\begingroup\$ how do you run nodejs with es6 compatibility? the latest one still does not support lambda functions for me \$\endgroup\$ – bebe Jul 26 '14 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 '14 at 15:05
  • \$\begingroup\$ @c.P.u1 they work for me \$\endgroup\$ – username.ak Jan 12 '17 at 21:03
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\$
  • 1
    \$\begingroup\$ +1 for doing it the old-fashioned way--inspired me to write a QBasic version, too. \$\endgroup\$ – DLosc Oct 5 '14 at 3:29
  • \$\begingroup\$ Invalid, needs to be a function or full program (one that takes input) \$\endgroup\$ – ASCII-only Jan 4 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\$
  • \$\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 '14 at 2:30
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\$
1
\$\begingroup\$

Pyth, 7 bytes (non-competing)

smCid2c

Takes input as string.

Try it!

\$\endgroup\$
  • \$\begingroup\$ Marked non-competing because the language is newer than the challenge. \$\endgroup\$ – mbomb007 Mar 29 '17 at 15:24
1
\$\begingroup\$

05AB1E, 4 bytes (non-competing)

Saved 3 bytes thanks to @Emigna

#CçJ

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ #CçJ also works. Although in both this and your version you need ð¡ instead of # if the input can be only 1 char. \$\endgroup\$ – Emigna Jan 12 '17 at 14:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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