freeCodeCamp Challenge Guide: DNA Pairing

Dna Pairing


Problem Explanation

  • You will get a DNA strand sequence and you need to get the pair and return it as a 2D array of the base pairs. Keep in mind that the provided strand should be first always.

  • Another way to interpret the problem: there are four potential characters that exist in DNA: “A”, “T”, “G”, and “C”. “A” and “T” are always paired together, and “G” and “C” are always paired together.
    This problem presents you with an input, e.g. “ATCGA”. Each of those five characters are missing their pairs.
    E.g. the first character “A” needs to be paired with “T” to give the array element [“A”, “T”].
    The second character “T” needs to be paired with “A” to give the array element [“T”, “A”].
    The number of elements in the final output equals the number of characters in the input.

This problem does not involve rearranging the input into different combinations or permutations.

Relevant Links


Hints

Hint 1

  • There are two pairs of values, A-T and C-G.

Hint 2

  • A switch would be a natural option here, because each character in the string has 4 possible values.

Hint 3

  • The result must be an array of arrays.

Solutions

Solution 1 (Click to Show/Hide)
function pairElement(str) {
  // Function to match each character with the base pair
  const matchWithBasePair = function(char) {
    switch (char) {
      case "A":
        return ["A", "T"];
      case "T":
        return ["T", "A"];
      case "C":
        return ["C", "G"];
      case "G":
        return ["G", "C"];
    }
  };

  // Find pair for every character in the string
  const pairs = [];
  for (let i = 0; i < str.length; i++) {
    pairs.push(matchWithBasePair(str[i]));
  }

  return pairs;
}

// test here
pairElement("GCG");

Code Explanation

  • Inside of the matchWithBasePair function, a switch is used to cover all four possible characters. Using if statements is another option.
  • Create an empty array and use the matchWithBasePair function to push the right values to the array and return them.

Relevant Links

Solution 2 (Click to Show/Hide)
function pairElement(str) {
  // create object for pair lookup
  const pairs = {
    A: "T",
    T: "A",
    C: "G",
    G: "C"
  };

  // map character to array of character and matching pair
  return str
    .split("")
    .map(x => [x, pairs[x]]);
}

// test here
pairElement("GCG");

Code Explanation

  • First define an object with all pair possibilities, this allows us to easily find by key or value.
  • Split str into a characters array so we can use each letter to find its pair.
  • Use the map function to map each character in the array of individual characters to an array with the character and its matching pair, creating a 2D array.

Relevant Links

127 Likes

Just done this today with my messy code ^^ https://jsfiddle.net/ufs59ngb/

Didnt realise until i found this topic that i dont need two full arrays from WikiPedia example, could just limit it to 4 letters.

Also messy forEach and for loops instead of your flashy .map :((

4 Likes

Simple solution with map:

function pairElement(str) {
  
  return str.split("").map(function (el) {
    if (el === "A") {
      return ["A", "T"];
    } else  if (el === "T") {
      return ["T", "A"];
    } else if (el === "C") {
      return ["C", "G"];
    } else {
      return ["G", "C"];
    }
  });
}
55 Likes
function pairElement(str) {
  var pairs = {
    "A": ["A", "T"],
    "T": ["T", "A"],
    "C": ["C", "G"],
    "G": ["G", "C"]
  };
  
  return str.split("").map(function(elem) {
    return pairs[elem];
  });
}
88 Likes

This is the solution I ended up using. Very clean, very to the point.

5 Likes
function pairElement(str) {
  const characters = str.split("");
  const map = {T:'A', A:'T', G:'C', C:'G'};
  const pairs = characters.map(character => {
    return [character, map[character]];
  });
  return pairs;
}

pairElement("GCG");

Using the map array helper method, but with the object of pairs from the above solution makes for a nice clean result I think.

10 Likes

This is how I did it:

function pairElement(str) {
  var newArr = [];
  for (var i = 0; i < str.length; i++){
    if(str[i] === "C"){
      newArr.push((str[i] + "G").split(""));
    } else if (str[i] === "G"){
      newArr.push((str[i] + "C").split(""));
    } else if (str[i] === "T"){
      newArr.push((str[i] + "A").split(""));
    } else if (str[i] == ="A"){
      newArr.push((str[i] + "T").split(""));
    }  
  }
  return newArr;
}

I was wondering how to paste my code nicely here in the forums. I will research how to do it but any suggestions/help/hints would be really appreciated.

[edit] Found It!

16 Likes
function pairElement(str) {
  var dnArray = []; //creates a new array into which we will push new arrays
   for (var i=0;i<str.length;i++){ //iterates through the str
if (str.charAt(i) === "G"){ //if the current str character is a G...
dnArray.push(["G", "C"]); //...push this array into dnArray
} else if (str.charAt(i) === "C"){  //if the current str character is a C...
dnArray.push(["C", "G"]); //push this arra into dnArray
} else if (str.charAt(i) === "A"){ //and so on...
dnArray.push(["A", "T"]);
} else if (str.charAt(i) === "T"){
dnArray.push(["T", "A"]);
}
}
return dnArray; //return the, now populated, dnArray
}

pairElement("ATCGA");

This is my solution with comments. I didn’t find that using if-statements took that much more code than using the switch method.

4 Likes

Using map & switch:

function pairElement(str) {  
  return str.split("").map(function (x) {
    switch (x) {
      case "G":
       return ["G","C"];       
      case "C":   
       return ["C","G"];        
      case "T":
       return ["T","A"];       
      case "A":
       return ["A","T"];       
    }    
  });
}
16 Likes

My solution seems to be a bit different than everyone else’s.

function pairElement(str) {
 
  var thePairs = ["A", "C", "G", "T"];
  var myPairs = [];
  
  for (var i = 0, l = str.length; i < l; i++) {
    var thePair = '';
    thePair = thePairs[thePairs.length - thePairs.indexOf(str[i]) - 1];
    myPairs.push([str[i], thePair]);
  }

  return myPairs;
}
2 Likes

Short solution using map, arrow function, and object as key-value pair store:

//jshint esversion:6
function pairElement(str) {
  const mapping = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C'};
  return str.split('').map(item => [item, mapping[item]]);
}
10 Likes

I need to get more familiar with map, as well as the arrow notation. Would have saved me a few lines here:


function pairElement(str) {
  var pairs = { "A": "T", "T": "A", "C": "G", "G": "C" };
  var pArr = [];
  for(var i of str) {
    pArr.push([i, pairs[i]]);
  }
  str = pArr;
  return str;
}

4 Likes

My solution(s).

// SOLUTION #1
// function pairElement(str) {

//   function getBasePair(val){
//     switch (val) {
//       case 'A': return 'T';
//       case 'T': return 'A';
//       case 'C': return 'G';
//       case 'G': return 'C';
//     }
//   }
  
//   var output = [];

//   str.split('').map(function(val){
//     var tmp = [];
//     tmp.push(val);
//     tmp.push(getBasePair(val));
//     output.push(tmp);
//   });
   
//   return output;
// }


// SOLUTION #2
function pairElement(str) {

  function getBasePair(val){
    switch (val) {
      case 'A': return ['A','T'];
      case 'T': return ['T','A'];
      case 'C': return ['C','G'];
      case 'G': return ['G','C'];
    }
  }
  
  var output = [];

  str.split('').map(function(val){
    output.push(getBasePair(val));
  });
   
  return output;
}

pairElement("GCG");

1 Like

Probably not the most efficient solution, but for beginners like myself, it seems like possibly the easiest/simplest since I only used very basic string and array methods as well as one for loop and if statements.

function pairElement(str) {
  //set up a new array, to store the arrays you will be making for the final product
  var newArray = [];
  
  //split the string into an array in order to acces each character of the string easier
  var array = str.split('');
  
  
  //loop through your array
  //create if statements for each possible input
  //use "if statement breakpoints" to push newly paired arrays into NewArray
  for (var i = 0; i < array.length; i++)
    if (array[i] == "G"){
      newArray.push(["G","C"]);
    } else if (array[i] == "C"){
      newArray.push(["C","G"]);
    } else if (array[i] == "A"){
      newArray.push(["A","T"]);
    } else if (array[i] == "T"){
      newArray.push(["T","A"]);
    }
  
  
  //return new paired multi-dimensional array
  return newArray;
}

pairElement("GCG");
function pairElement(str) {
  str = str.split('');
  for (var i=0; i<str.length; i++) {
    str[i] = [str[i]];
    if (str[i][0]==='G') {
      str[i].push('C');
    } else if (str[i][0]==='C') {
      str[i].push('G');
    } else if (str[i][0]==='A') {
      str[i].push('T');
    } else if (str[i][0]==='T') {
      str[i].push('A');
    }
  }
  return str;
}
var basePairs = {
    'A': 'T',
    'T': 'A',
    'G': 'C',
    'C': 'G'
};
function pairElement(str) {
  return str.split('').map(function(key) {
    return [key, basePairs[key]];
  });
}
7 Likes

Noobs Unite!

function pairElement(str) {
  var pair = [];
  
  str = str.split('');
  
  for (var i = 0; i < str.length; i++) {
    if (str[i] === 'A') {
      pair.push(['A', 'T']);
    } else if (str[i] === 'T') {
      pair.push(['T', 'A']);
    } else if (str[i] === 'C') {
      pair.push(['C', 'G']);
    } else if (str[i] === 'G') {
      pair.push(['G', 'C']);
    }
  }
  
  return pair;
}
2 Likes

My solution:

function pairElement(str) {
  
  var split   = str.split(''),
      pair    = split.map(item => {
                  switch(item) {
                    case 'G':
                      return (item + 'C').split('');
                    case 'C':
                      return (item + 'G').split('');
                    case 'A':
                      return (item + 'T').split('');
                    case 'T':
                      return (item + 'A').split('');
                    default:
                      console.log('Not a valid pair');
                    return 'Not a valid pair';
                   }
                 });
 return pair;
}

pairElement("GCG");