Intermediate Algorithm Scripting

Just for the record, my solutions for these exercises.

Sum numbers in a range.

function sumAll(arr) {
  let newArr = arr.sort((a,b) => a - b); 
  let start = newArr[0]; //assumes that only two numbers are passed but not
  let end = newArr[1]; // necessarily in the right order
  let result = 0;
  for (let i = start; i <= end; i++) {
    result += i;
  }
  return result;
}
console.log(sumAll([12, 4]));
1
2
3
4
5
6
7
8
9
10
11

Diff two arrays

The function I came up with does not deal with duplicates - if either array had more than one copy of an element which does not appear in the other, then those duplicates would be passed into the output, but the question did not ask for deduplication.

function diffArray(arr1, arr2) {
  let onlyInArr1 = arr1.filter(n => !arr2.includes(n));
  let onlyInArr2 = arr2.filter(n => !arr1.includes(n));
  return onlyInArr1.concat(onlyInArr2);
}
console.log(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]));
console.log(diffArray(["andesite", "grass", "dirt", "pink wool", "dead shrub"], ["diorite", "andesite", "grass", "dirt", "dead shrub"]));
1
2
3
4
5
6
7

Seek And Destroy

Remove elements from an array which match any number of following arguments.

function destroyer(arr) {
  let args = Array.from(arguments); //arguments is not a true Array
  let destroyedArr = args[0]; // first argument is the input array, arguments[0] also works
  args.shift(); //remove the input array so only have the targets for removal
  let result = destroyedArr.filter(n => !args.includes(n)); //just leave the ones that don't match
  return result;
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3)); //[1,1]
console.log(destroyer(["possum", "trollo", 12, "safari", "hotdog", 92, 65, "grandma", "bugati", "trojan", "yacht"], "yacht", "possum", "trollo", "safari", "hotdog", "grandma", "bugati", "trojan")); //[12,92,65]
1
2
3
4
5
6
7
8
9

Wherefore art thou

Some sloppy typing hindered me here. Here is the challenge.

Here is my solution:

function whatIsInAName(collection, source) {
  var arr = [];
  // Only change code below this line
  let searchArr = arr.concat(collection);               //
  let keysToFind = Object.keys(arguments[1]);           // get array, e.g. ["apple","bat"]
  let valuesToFind = Object.values(arguments[1]);       // get array, e.g. [1,2]
  let allMatched = true;                                // object has to contain all the targets
  searchArr.forEach(function(c) {                       // loop through collection
    allMatched = true;                                  // 
    for (let i = 0; i < keysToFind.length; i++){        // inner loop of targets
      if (!(c[keysToFind[i]] == valuesToFind[i])) {     // if any match fails
        allMatched = false;                             // reject it
      }
    }
    if (allMatched){                                    // only push to result if all matched
      arr.push(c);
    }
  });
  // Only change code above this line
  return arr;
}
console.log(whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" })); // [{ first: "Tybalt", last: "Capulet" }].
//whatIsInAName([{ "apple": 1 }, { "apple": 1 }, { "apple": 1, "bat": 2 }], { "apple": 1 }) should return [{ "apple": 1 }, { "apple": 1 }, { "apple": 1, "bat": 2 }].
//whatIsInAName([{ "apple": 1, "bat": 2 }, { "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "bat": 2 }) should return [{ "apple": 1, "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }].
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Intermediate Algorithm Scripting: Spinal Tap Case

Could not use split here because there is not always a separator between words, sometimes the words are separated by a non alphabetic character, but other times the next word simply begins with a capital Letter and no space.

function spinalCase(str) {
  let strArr = str.trim().split("");        //gets each character in the string to loop over
  let wordStarted = true;                   //assume that the first word begins with the first character
  let words = [];
  let word = "";
  let alpha = /[a-zA-Z]/;
  let capitalLetter = /[A-Z]/;
  strArr.forEach(function(letter){                          //loop over all characters in the string
    if(wordStarted){                                        //am building a word
      if(alpha.test(letter)){                               //if its alphabetic going to append
        if(capitalLetter.test(letter) && word.length > 0){  //if a capital letter will also start new
          words.push(word);
          word = "";
        }
        word += letter;
      }
      else{                                                 //not alpha
        wordStarted = false;                                //so word is finished
        words.push(word);                                   //add to result
        word = "";                                          //reset
      }
    }
    else{                                                   //not building a word
      if(alpha.test(letter)){
        wordStarted = true;                                 //only start new word on alphabetic char
        word += letter;
      }
    }
  });
  if (word.length > 0) {words.push(word);}                  //capture last word
  const reducer = (strSoFar, currentWord) => strSoFar + "-" + currentWord;
  return words.map(word => word.toLowerCase()).reduce(reducer);
}
console.log(spinalCase('This Is   ,,   Spinal Tap')); //"this-is-spinal-tap"
console.log(spinalCase("thisIsSpinalTap")); //"this-is-spinal-tap"
console.log(spinalCase("AllThe-small Things")); //"all-the-small-things"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Translate word to pig latin

function translatePigLatin(str) {
  let vowel = /[aeiou]/;
  let consonants = /^[^aeiou]*/; // 0 or more consonants at the beginning.
  let cluster = str.match(consonants).toString();
  if (cluster.length === 0){
    return str + "way";     //words that begin with vowel just get way on the end
  }
/*
take the consonant cluster and put it at the end and add 'ay' - this also works 
if there are no vowels as the slice returns an empty string, slice without the optional
second argument takes string from the start point to the end of the string
*/
  return str.slice(cluster.length) + cluster + "ay";
}
console.log(translatePigLatin("glove")); //oveglay
console.log(translatePigLatin("cymry")); //cymryay
console.log(translatePigLatin("albacore")); //albacoreway
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Search and Replace

Preserving the capitalisation of the original string replaced.

function myReplace(str, before, after) {
  let regex = new RegExp(before,'g');   // => regex /Sleeping/g
  let capitalLetter = /^[A-Z]/;         // ^ not necessary really
  if (capitalLetter.test(before)){
    after = after.charAt(0).toUpperCase() + after.slice(1);
  }
  return str.replace(regex, after);
}
console.log(myReplace("He is Sleeping on the couch", "Sleeping", "sitting")); //He is Sitting on the couch
1
2
3
4
5
6
7
8
9

DNA Pairing

Input is a string of letters made up from ACGT, return is a nested array with each letter paired with its opposite, A with T, C with G and so on.

function pairElement(str) {
  const bases = ["A", "C", "T", "G"];
  const pairs = ["T", "G", "A", "C"];
  let elems = str.split("");
  return elems.map( elem => [elem, pairs[bases.indexOf(elem)]]);
}
pairElement("ATCGA"); //[["A","T"],["T","A"],["C","G"],["G","C"],["A","T"]]
1
2
3
4
5
6
7

Missing Letters

Find the missing letter in a string of consecutive letters and return it, if no missing letter return undefined.

function fearNotLetter(str) {
  const alphabet = 'abcdefghijklmnopqrstuvwxyz';
  let start = alphabet.indexOf(str[0]);
  for (let i = 0; i < str.length; i++){
    if (str[i] !== alphabet[i+start]){
      return alphabet[i+start];
    }
  }
  return;
}
console.log(fearNotLetter("abcdefghjklmno")); //i
console.log(fearNotLetter("stvwx")); //u
1
2
3
4
5
6
7
8
9
10
11
12

Unite unique

The coding challenge here is to return a single array from a number of input arrays but only to include each number once in whatever order they were originally. The code I submitted passed the test but is incomplete as it only accounts for one level of nesting, and if for example 5 and [5] were both included it would not skip whichever came second. Adding that in would be complicated in this structure.

function uniteUnique(arr) {
  let arrs = Array.from(arguments);
  let result = [];
  arrs.forEach(function(elem){
    elem.forEach(function(inner){
      //console.log(Array.isArray(inner));
      if(!result.includes(inner)){
        result.push(inner);
      }
    })
  });
  return result;
}
console.log(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1])); //[1, 3, 2, 5, 4]
console.log(uniteUnique([1, 3, 2], [1, [5]], [2, [4]])); //[1, 3, 2, [5], [4]]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Equivalent of the PHP htmlentities function

This is just a matter of stringing replaces together.

function convertHTML(str) {
  let colonRegex = /:/g;
  let colon = '&colon;';
  let ampRegex = /&/g;
  let amp = '&amp;';
  let lessRegex = /</g;
  let less = '&lt;';
  let greaterRegex = />/g;
  let greater = '&gt;';
  let doubleRegex = /\"/g;
  let double = '&quot;';
  let singleRegex = /\'/g;
  let single = '&apos;';
  return str.replace(ampRegex, amp).replace(colonRegex, colon).replace(lessRegex, less).replace(greaterRegex, greater).replace(doubleRegex,double).replace(singleRegex, single);
}
console.log(convertHTML('Stuff in "quotation marks"'));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Sum All Odd Fibonacci Numbers

function sumFibs(num) {
  let fibs = [1,1];
  let a = 1;
  let b = 1;
  let c = 1;
  do {
    c = a+b;
    fibs.push(c);
    a = b;
    b = c;
  }
  while (c < num);
  if(c>num){fibs.pop();}
  return fibs.filter(x => x % 2).reduce((acc, curr) => acc + curr);
}
console.log(sumFibs(75024)); // 60696
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Sum all Primes

function sumPrimes(num) {
  let primes = [];
  let isPrime = false;
  for (let i=2; i<=num; i++){ //loop integers from 1st prime
    isPrime = true;
    for (let j=2; j<=(i/2); j++ ){  //look for factors
      if(i % j === 0){              //if a factor
        isPrime = false;            //this number not a prime
        break;                      //stop looking
      }
    }
    if(isPrime){primes.push(i);}    //if it was prime..
  }
  return primes.reduce((acc, curr) => acc + curr);
}
console.log(sumPrimes(977)); //73156
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Small Common Multiplier

Of a sequence of numbers, for example input is [1,5] have to find the lowest common multiple of 1 and 5 which is also divisible by 2,3,and 4, which is 60.

function smallestCommons(arr) {
  let sortedArr = arr.sort((a,b) => a - b);
  let sequence = []
  for (let i = sortedArr[0]; i<= sortedArr[1]; i++){
    sequence.push(i);
  }
  let allDivisors = false;
  let candidate = 0;
  let multiplier = 1;
  do {
    candidate = sortedArr[0] * sortedArr[1] * multiplier;     //try each multiple of the two numbers
    allDivisors = true;
    sequence.forEach(function(i){
      if(!(candidate % i === 0)){                             //if any of the sequence is not a divisor
        allDivisors = false;                                  //then this is not a candidate
      }                                                       //cannot break from a foreach loop
    });                                                       //so should use a for loop instead !
    multiplier += 1;
  }
  while (allDivisors == false);
  return candidate;
}
smallestCommons([13,1]); //360360
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23