freeCodeCamp Challenge Guide: Binary Agents

Binary Agents


Problem Explanation

This problem is very straight forward - you start with a string that represents a sentence in binary code, and you need to translate that into words. There is not a direct way to do this so you will have to translate twice.

Relevant Links


Hints

Hint 1

You should first convert from binary to decimal before translating those values into characters.

Hint 2

Things are easier when focusing on smaller parts, divide the input to focus on one letter at a time.

Hint 3

Make sure that each time you transcode a character from binary to decimal, you reset whatever variable you used to keep track of the ones. Also do not forget to turn everything back into one string.


Solutions

Solution 1 (Click to Show/Hide)
function binaryAgent(str) {
  var biString = str.split(" ");
  var uniString = [];

  /*using the radix (or base) parameter in parseInt, we can convert the binary
      number to a decimal number while simultaneously converting to a char*/

  for (var i = 0; i < biString.length; i++) {
    uniString.push(String.fromCharCode(parseInt(biString[i], 2)));
  }

  // we then simply join the string
  return uniString.join("");
}

// test here
binaryAgent(
  "01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111"
);

Code Explanation

  • Separate the string into an array of strings separated by whitespace.
  • Create some variables that you will use along the way - the names are self explanatory for the most part.
  • Iterate through each binary string in the new array.
  • Convert to decimal by using parseInt(_binary_, 2). Use the second parameter to specify the base of the input numbers.
  • At the end, return the converted message.

Relevant Links

Solution 2 (Click to Show/Hide)
function binaryAgent(str) {
  // Separate the binary code by space.
  str = str.split(" ");
  var power;
  var decValue = 0;
  var sentence = "";

  // Check each binary number from the array.
  for (var s = 0; s < str.length; s++) {
    // Check each bit from binary number
    for (var t = 0; t < str[s].length; t++) {
      // This only takes into consideration the active ones.
      if (str[s][t] == 1) {
        // This is quivalent to 2 ** position
        power = Math.pow(2, +str[s].length - t - 1);
        decValue += power;

        // Record the decimal value by adding the number to the previous one.
      }
    }

    // After the binary number is converted to decimal, convert it to string and store
    sentence += String.fromCharCode(decValue);

    // Reset decimal value for next binary number.
    decValue = 0;
  }

  return sentence;
}

// test here
binaryAgent(
  "01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111"
);

Code Explanation

  • For each of these binary strings, check for the ones and ignore the zeroes.
  • For those that are one or active then convert them to decimal, this takes into account the position and the right power it needs to be raised to.
  • Store the power into the power variable by adding it to any previous ones on the variable decValue. This variable will add and add the powers of the active ones until the end of the loop and then return the decimal number.
  • Convert the final decimal outside of the inner loop and then convert it to ASCII and saving it to sentence along with any other text string already converted and stored.
  • Reset the variable decValue to avoid getting wrong decimals before continuing to the outer loop.

Relevant Links

Solution 3 (Click to Show/Hide)
function binaryAgent(str) {
  return String.fromCharCode(
    ...str.split(" ").map(function(char) {
      return parseInt(char, 2);
    })
  );
}

// test here
binaryAgent(
  "01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111"
);

Code Explanation

  • First we use split() to be able to work on each character as an Array element
  • Then use map() to process each element from binary to decimal using pareseInt()
  • Last we can use String.fromCharCode() to convert each ASCII number into the corresponding character
  • However fromCharCode() expects a series of numbers rather than an Array! We can use ES6 Spread Operator to pass in an Array of numbers as individual numbers. See here for more info; Spread Operator

Relevant Links

Alternative Advanced Code Solution:

  const binaryAgent = str => str.replace(/\d+./g, char => String.fromCharCode(`0b${char}`));
       
  binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");

Code Explanation

  • Find all groups of one or more digits followed by one other character
  • Replace with a string created from the specified sequence of UTF-16 code units
  • Use 0b to lead the code unit to express that a binary integer literal is being converted.

Relevant Links

12 Likes

My solution which is quite simple :

function binaryAgent(str) {
  let array = str.split(' ');
  array = array.map(item=>{return String.fromCharCode(parseInt(item,2));});
return array.join('');
}
binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");
15 Likes
function binaryAgent(str) {

  var binaryArray = str.split(" "); // ["01000001", "01110010",....]

  var charCodeArray = binaryArray.map(function(x){ return parseInt(x, 2);} ); // [65, 114,...]

  var charArray = charCodeArray.map(function(x){ return String.fromCharCode(x);}); // ["A", "r",...] 

  var charString = charArray.join(""); 

 return charString;
}

binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110     01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");
2 Likes

Here is my version of the basic answer including explanatory comments:

function binaryAgent(str) {
  var binaryArr=str.split(" "); //Splits the string into separate arrays, breaking at the white spaces
  var uniString = [];//creates a uniString variable
  for(var i=0;i<binaryArr.length;i++){ //for loop that runs through the binaryArr array
uniString.push //pushes the result of the following code into uniString
(String.fromCharCode //returns the created character Code numbers as strings e.g the first character code is 129 which makes the capital letter A
 (parseInt(binaryArr[i], 2))); /*Analyses each element
 of binaryArr and converts it from Binary Code into
 Decimal character Codes by multiplying each element
 from end to beginning by the power of 2 and adding
 the results.  E.g. the first array element of 01000001 
 = 129 because the last element is 2 to the power of
 0 which is 1 multiplied by 1 so it remains 1.  The
 one before last is 2 to the power of 1 which is 2
 but this is multiplied by 0 so it becomes 0.  Most 
 of the numbers in this code are 0 so return 0 even though the power of 2 is increasing: 2pow2 = 4,
 2pow3 = 8 etc.  The only other element of this code
 which is a 1 is the 7th from last which is 2pow7=128.
 This means that we need to add 128+1 = 129.*/ 
  }
  return uniString.join(''); //Join all the elements of uniString with no white spaces between.
}

binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");

I am curious as to why key elements of these solutions (String.prototype.split and parseInt) are not mentioned either on the original challenge page or in the hints. I spent ages trying to work out how to do this without ever finding a reference to either of these two methods. Admittedly .split has come up before and I should have considered using it myself but parseInt has not come up before. I feel that I am force to “cheat” by looking at the answers because I am given insufficient information to work it out by myself.

6 Likes

For the advanced response, why use fromCharCode and the spread operator? Is it more efficient? This seemed to accomplish the same result?

function binaryAgent(str) {

  //split, convert the binary, and join the result
  return str.split(' ').map(function(bi) {
    return String.fromCharCode(parseInt(bi, 2)); 
  }).join(''); 
}
binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");
4 Likes

Using regular expressions:

function binaryAgent(str) {
  return str.replace(/[0-9]\w+\s|[0-9]\w+\S/g, function(b){
    return String.fromCharCode(parseInt(b, 2));    
  }); 
}
4 Likes
function binaryAgent(binaryString) {
  return string = binaryString.split(" ").map(function(value) {
    return String.fromCharCode(parseInt(value, 2));
  }).join('');
}
1 Like

Hello! I recently did this challenge and I have a minor critique:
Under “Helpful Links” we have the following:

String.prototype.charCodeAt()
String.fromCharCode()

Why wasn’t parseInt() included? As far as I can tell the curriculum hadn’t introduced parseInt up to this point and its use is necessary to complete this challenge. I had to Google convert binary to decimal which felt like cheating :confounded:

26 Likes

Well, I feel like an idiot for not knowing about parseInt() but anyway this is what I did:


function binaryAgent(str) {
  var arr = str.split(" ");
  var asciiFromBinary = function(twine) {
    var len = twine.length;
    var ascii = 0;
    for (var j = 0, k = len - 1; j < twine.length; j++, k--) {
      ascii += twine.charAt(j) * (2 ** k);
    }
    return ascii;
  };
  for (var i = 0; i < arr.length; i++) {
    arr[i] = String.fromCharCode(asciiFromBinary(arr[i]));
  }
  str = arr.join("");
  return str;
}

this is my solution :slight_smile:

    function binaryAgent(str) {
      var arr = str.split(" "),newArr=[];

      for(var a in arr){
        newArr.push(String.fromCharCode(parseInt(arr[a],2)));
      }
      
      return newArr.join("");
    }
2 Likes

My solution:

function binaryAgent(str) {
  return str.split(' ')
    .map( i => String.fromCharCode(parseInt(i,2)))
    .join("");
}

is it better to use spread operator as in advanced solution? why?

1 Like

Basic solution.

function binaryAgent(str) {
  var x=str.split(" ");
  var y=[128,64,32,16,8,4,2,1];
  var z=[];
  var a;
  
  for(k=0;k<x.length;k+=1){
    z.push(0);
  }
  
  for(i=0;i<x.length;i+=1){
    for(j=0;j<y.length;j+=1){
      if(x[i][j]==1){
        z[i]+=y[j];  
      }
    }
  }
  
  for(l=0;l<x.length;l+=1){
    a = String.fromCharCode.apply(String,z); 
  }
  return a;
}

binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");

function binaryAgent(str) {
  str = str.split(' ');
  for (var i = 0; i<str.length; i++) {
    str[i]=str[i].split('');
    for (var j=0; j<str[i].length; j++) {
      str[i][j] = parseInt(str[i][j]) * Math.pow(2, str[i].length-j-1);   
    }
    str[i] = String.fromCharCode(str[i].reduce(function(a,b) {
      return a+b;
    }));
  }
  
  return str.join('');
}
function binaryAgent(str) {
  let strArr = str.split(' ');

  str = '';
  strArr.forEach(function(element) {
    str += String.fromCharCode(parseInt(element, 2));
  })
  console.log(str);
  return str;
}

Because I was trying to pass this algorithm with information that we’d learned (and we hadn’t learned about parseInt), here’s my solution using a recursion to parse a binary element.

function binaryAgent(str) {  
  return str.split(' ').map(function(bin) { return String.fromCharCode(parseBinary(bin));}).join('');
}

function parseBinary(str)
{
  if (str.length === 0)
    return 0;
  
  return str[0] * (2 ** (str.length - 1)) + parseBinary(str.slice(1));
}
2 Likes

First of all, the think way is important, so just divide a big problem into step by step way to solve.

function binaryAgent(str) {
  // Step1: split this string into some single word
  // Step2: change the 01 to number
  // Step3: use fromCharCode(num) to get the single word
  // Step3: Combine these single word

  // In action, this line secStr.push(String.fromCharCode((parseInt(newStr[i], 2))));
  // I have think of parseInt(newStr[i], 2), but above that part, I don't know good.
  // In general, my think way is right, that is good for me 
  var newStr = str.split(' ');
  var secStr = [];

  for (i=0;i < newStr.length; i++) {
    secStr.push(String.fromCharCode((parseInt(newStr[i], 2))));
  }

  return secStr.join('');
  // return str.charCodeAt();
}

binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 
01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 
01110101 01101110 00100001 00111111");
function binaryAgent(str) {
  
  var ar = str.split(' ');
  
  for(var x in ar){
    ar[x] = ar[x].split("");
  }
  

  var st = ar.reduce(function(a, b, i){
    var bn = b.reduce(function(c, d){
      return  (c*2) + parseInt(d);
    }, 0);
    a.push(String.fromCharCode(bn));
    return a;
  }, []).join("");
  

  return st;
}

didn’t pay attention that parseInt can convert between bases with radix :disappointed_relieved:

  • cool how all this stuff is built in to javascript
  • i just make an array using split then map each element first turning it to ascii code then calling the string constructor fromCharCode on that ascii code
  • all thats left is to use join and then we have our english
  • if you didn’t already know parseInt takes a second argument of radix - which i only recently learned about…2 is binary
1 Like