Skip to content

Latest commit

 

History

History
1265 lines (1021 loc) · 33.6 KB

File metadata and controls

1265 lines (1021 loc) · 33.6 KB

Javascript

#22 popular tasks

at a Javascript interview

Tasks

Solutions, Language Methods


Author: Kirill Ostapenko @khbfr


Introduction

Any problem is solved by using a construction - a solution template:

For loop

for ([start]; [condition]; [step]) expressions

And the logical part is the If __ Else conditions

if (condition)
   instruction1
else
   instruction2

Let's take a look at the given problem and apply this pattern to it.


Task: duplicate encoder

The goal of this exercise is to convert a string to a new string, where each character in the new string is "(" if that character occurs only once in the source string, or ")" if that character occurs more than once in the source string. Capitalization must be ignored when determining if a character is a duplicate.

Required result

"din" => "((("
"recede" => "()()()"
"Success" => ")())())"
"((@" => "))(("

Solution by for loop

function duplicateEncode(word){
    let unique='';
    word = word.toLowerCase();
    for(let i=0; i<word.length; i++){
        if(word.lastIndexOf(word[i]) == word.indexOf(word[i])){
            unique += '(';
        }
        else{
            unique += ')';
        }
    }
    return unique;
}

Great, but for any task there are many solutions. Let's try to use map, the method creates a new array with the result of calling the specified function for each element of the array.

Solution via map

function duplicateEncode(word){
  return word
    .toLowerCase()
    .split('')
    .map( function (a, i, w) {
      return w.indexOf(a) == w.lastIndexOf(a) ? '(' : ')'
    })
    .join('');
}

And this solution is loved by novice developers - the so-called one line

One line solution

function duplicateEncode(word) {
  word = word.toLowerCase();
  return word.replace(/./g, m => word.indexOf(m) == word.lastIndexOf(m) ? '(' : ')');
}

OK, a start has been made - let's try to solve other problems


Challenge: find the missing letter

Write a method that takes an array of consecutive (increasing) letters as input and returns the missing letter in the array. You will always get a valid array. And there will always be exactly one letter missing. The length of the array will always be at least 2. The array will always contain letters in only one case.

Required result

["a","b","c","d","f"] -> "e"
["O","Q","R","S"] -> "P"

(Use the English alphabet of 26 letters!)

Solution

function findMissingLetter(array) {
  let first = array[0].charCodeAt(0)
  for (let i = 1; i < array.length; i++) {
    if (first + i !== array[i].charCodeAt(0)) {
      return String.fromCharCode(first + i)
    }
  }
  throw new Error("Invalid input")
}
  • The charCodeAt() method returns the Unicode numeric value for the character at the specified index
  • The static method String.fromCharCode() returns a string created from the specified sequence of UTF-16 code unit values

Solution via slice

const findMissingLetter = (array) => {
  const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
  const start = alphabet.indexOf(array[0]);
  return alphabet.slice(start, start + array.length).find(el => !array.includes(el));
};
  • The slice() method returns a new array containing a copy of a portion of the original array
  • The find() method returns the value of the first element found in the array
  • The includes() method determines if the array contains a certain element, returning true or false depending on this

Solution using filter

function findMissingLetter(str) {
    let alphabet = 'abcdefghijklmnopqrstuvwxyz';
    if(str[0] == str[0].toUpperCase()) {
      alphabet = alphabet.toUpperCase(); }
    alphabet = alphabet.split('');
    let index = alphabet.indexOf(str[0]);
    let strip = alphabet.slice(index, index + str.length)
    return strip.filter(x => !str.includes(x))[0];
}
  • The filter() method creates a new array with all elements that pass the test specified in the passed function.

Task: moving zeros to the end

Write an algorithm that takes an array and moves all zeros to the end, preserving the order of the rest of the elements.

Required result

moveZeros([false,1,0,1,2,0,1,3,"a"])
// returns[false,1,1,2,1,3,"a",0,0]

Pattern decision For .. if _ else

const moveZeros = function (arr) {
  let result = [];
  let zeros = [];
  for (let i in arr) {
    if (arr[i] === 0) {
      zeros.push(arr[i]);
    } else if (arr[i] !== 0) {
      result.push(arr[i]);
    }
  }
  return result.concat(zeros);
}
  • The push() method adds one or more elements to the end of the array and returns the new length of the array.
  • The concat() method returns a new array consisting of the array it was called on, concatenated with other arrays and/or values ​​passed as arguments.

Battery solution

const moveZeros = function (arr) {
  return arr. reduceRight(function(prev, curr) {
    if (curr !== 0) {
      prev unshift(curr);
    }
    else {
      prev push(curr);
    }
    returnprev;
  }, []);
}
  • The reduceRight() method applies a function to the accumulator and each array value (from right to left), reducing it to a single value.
  • The unshift() method adds one or more elements to the beginning of the array and returns the new length of the array.

Task: convert string to camel case

Complete the method so that it converts dash/underscore separated words to camel case. The first word in the output should only be capitalized if the original word was capitalized (known as upper camel case, also often called Pascal case).

Required result

"the-stealth-warrior" gets converted to "theStealthWarrior"
"The_Stealth_Warrior" gets converted to "TheStealthWarrior"

Although this task can be solved with the For .. if _ else template, we’d better delve into the language methods.

Solution via RegExp

function toCamelCase(str){
      letregExp=/[-_]\w/ig;
      return str.replace(regExp,function(match){
            return match.charAt(1).toUpperCase();
       });
}
  • The RegExp constructor creates a regular expression object to match text against a pattern.
  • The match() method returns the resulting matches when matching a string against a regular expression.
  • The replace() method returns a new string with some or all of the pattern matches replaced by the replacement. The pattern can be a string or regular expression, and the placeholder can be a string or a function called on each match.
  • The toUpperCase() method returns the value of the string it was called on, converted to upper case.

Solution For .. if _ else

Ok - ok, if you need it, then so be it.

function toCamelCase(str){
  let arr = str.split('');
  for(i = 0; i < arr.length; i++){
    let letter = arr[i];
    if(letter == '_' || letter == '-') {
      arr[i + 1] = arr[i + 1].toUpperCase();
      arr[i] = '';
    }
  }
  return arr.join('');
}
  • The split() method splits a String object into an array of strings by splitting the string with the specified substring.

Task: sum of digits / digital root

Given n, take the sum of the digits of n. If this value has more than one digit, keep decreasing in this way until you get a single digit. The input will be a non-negative integer.

Required result

    16 --> 1 + 6 = 7
   942 --> 9 + 4 + 2 = 15 --> 1 + 5 = 6
132189 --> 1 + 3 + 2 + 1 + 8 + 9 = 24 --> 2 + 4 = 6
493193 --> 4 + 9 + 3 + 1 + 9 + 3 = 29 --> 2 + 9 = 11 --> 1 + 1 = 2

For .. if _ else solution and recursion

function digital_root(n) {
  if (n < 10)
    return n;

  for (let sum = 0, i = 0, n = String(n); i < n.length; i++)
    sum += Number(n[i]);
   
  return digital_root(sum);
}

Among the functions, recursive functions can be distinguished separately. Their essence is that the function calls itself.

Decision with eval

Don't use eval unnecessarily!

function digital_root(n){
    n = eval(n.toString().split('').join('+'));
    if (n > 9) {
        return digital_root(n);
    }
    return n;
}
  • The eval() method executes the JavaScript code represented by the string.
  • The join() method concatenates all the elements of an array (or array-like object) into a string.

Solution with reduce

function digital_root(n) {
  while (n > 9) { n = (''+n).split('').reduce(function(s,d) {return +s + +d;}); }
  return n;
}
  • The reduce() method applies the reducer function to each element of the array (left to right), returning a single resulting value.

Task: build a tower

Construct a pyramid-shaped tower, given a positive integer number of floors. The tower block is represented by the symbol "*".

Required result

For example, a tower with 3 floors looks like this:

  "*",
  "***",
  "*****"

Solution with repeat

function towerBuilder(n) {
  return Array.from({length: n}, function(v, k) {
    const spaces = ' '.repeat(n - k - 1);
    return spaces + '*'.repeat(k + k + 1) + spaces;
  });
}
  • The repeat() method constructs and returns a new string containing the specified number of concatenated copies of the string on which it was called.

Template decision

function towerBuilder(nFloors) {
  let arrTower = [],
      blocks;
  function buildFlour(blocks) {
    let maxSize = nFloors == 1 ? 1 : nFloors * 2 - 1,
        floor = '';
    for(let i = 0; i < maxSize; i++) {
      let space = (maxSize - blocks) / 2;
      if(maxSize - blocks !== 0) {
          if((i + 1) <= space || (i + 1) > blocks + space) {
            floor += ' ';
          } else {
            floor += '*';
          }
      } else {
        floor += '*';
      }
    }
    return floor;
  }
  for(var i = 0; i < nFloors; i++) {
    var blocks = i == 0 ? 1 : blocks + 2;
    arrTower.push(buildFlour(blocks));
  }
  return arrTower;
}

Looks like a monster, doesn't it ;)


Challenge: deep array count

Array.prototype.length will give you the number of top level elements in the array. Your task is to create a deepCount function that returns the number of ALL elements in the array, including any inside the inner-level arrays.

Required result

deepCount([1, 2, 3]);
//>>>>> 3
deepCount(["x", "y", ["z"]]);
//>>>>> 4
deepCount([1, 2, [3, 4, [5]]]);
//>>>>> 7

Template decision

function deepCount(a){
  let count = a.length;
  for (let i=0; i<a.length; i++) if (Array.isArray(a[i])) count += deepCount(a[i]);
  return count;
}
  • The length property of an object that is an instance of type Array sets or returns the number of elements in this array.

c while solution

function deepCount(arr) {
  const stack = [...arr]
  let size = 0
  while (stack length) {
    const next = stack.pop()
    size += 1
    if (Array.isArray(next)) {
      stack.push(...next)
    }
  }
  return size
}
  • The while statement creates a loop that executes the given statement while the condition being checked is true. The logical value of the condition is evaluated before the loop body is executed.
  • The pop() method removes the last element from the array and returns its value.
  • The Array.isArray() method returns true if the object is an array and false if it is not an array.

Solution with JSON

function deepCount(a) {
  return JSON.stringify(a).replace(/[^[,]|\[]/g, '').length;
}
  • The JSON.stringify() method converts a JavaScript value to a JSON string, possibly replacing values ​​if a replacement function is specified, or including only certain properties if a replacement array is specified.

Task: Permutations

In this task, you must create all permutations of a non-empty input string and remove duplicates, if any. This means that you have to shuffle all the letters from the input in all possible orders.

Required result

* With input 'a'
* Your function should return: ['a']
* With input 'ab'
* Your function should return ['ab', 'ba']
* With input 'aabb'
* Your function should return ['aabb', 'abab', 'abba', 'baab', 'baba', 'bbaa']

Template decision

function permutations(string) {
  let arr = string.split(''), tmp = arr.slice(), heads = [], out = [];
  if(string.length == 1) return [string];
  arr.forEach(function(v, i, arr) {
    if(heads.indexOf(v) == -1) {
      heads.push(v);
      tmp.splice(tmp.indexOf(v), 1);
      permutations(tmp.join('')).forEach(function(w) {out.push(v + w);});
      tmp.push(v);
    }
  });
  return out;
}
  • The slice() method returns a new array containing a copy of a portion of the original array.
  • The forEach() method executes the specified function once for each element in the array.
  • The splice() method modifies the contents of an array by removing existing elements and/or adding new ones.

Solution c substring

function permutations(str) {
 return (str.length <= 1) ? [str] :
         Array.from(new Set(
           str.split('')
              .map((char, i) => permutations(str.substr(0, i) + str.substr(i + 1)).map(p => char + p))
              .reduce((r, x) => r.concat(x), [])
         ));
}
  • The Array.from() method creates a new Array instance from an array-like or iterable object.
  • The substring() method returns a substring of a string between two indices, or from one index to the end of the string.
  • The concat() method returns a new array consisting of the array it was called on, concatenated with other arrays and/or values ​​passed as arguments.

Solution with yield

function permutations(chs) {
    return [...new Set(
        Array.from( heapsPerms((chs+'').split('')),
        str => str.join('') )
    )];
}
function *heapsPerms(chs, n = chs.length) {
    if (n <= 1) yield chs.slice();
    else for (let i = 0; i < n; i++) {
        yield *heapsPerms(chs, n-1);
        swap(chs, (n % 2 !== 0) ? 0 : i, n-1);
    }
}
function swap(iterable, i, j) {
    [iterable[i], iterable[j]] = [iterable[j], iterable[i]];
}
  • The yield keyword is used to stop and resume generator functions (function* or legacy generator function).
- [rv] = yield [[expression]];
- expression
Return expression. If not specified, undefined is returned.
- rv
Returns an optional value that is passed to the next() of the generator to resume its execution.

Task: flatten nested map

Write a function that takes a hierarchical property map and converts it into a single flat map with different levels separated by a slash ('/').

Required result

For example, with this input:

{
  'a': {
    'b': {
      'c': 12
      'd': 'Hello World'
    },
    'e': [1,2,3]
  }
}

return a new card:

  'a/b/c': 12,
  'a/b/d': 'Hello World',
  'a/e': [1,2,3]

Solution with Object

function flattenMap(map) {
  let di = {}
  function recur(d,prev=''){
      if (d.constructor!=object) return
      for (let [i,j] of Object.entries(d)){
          if (j!=null && j.constructor==Object) recur(j,prev+(prev?'/':'')+i)
          else{
            if (j==null || j.constructor != Function) di[(prev+'/'+i).replace(/^\/+/,'')] = j
          }
      }
  }
  recur(map)
  return di
}
  • constructor is a special method used to create and initialize objects created using class.
  • The Object constructor creates a wrapper object.
// Object initializer or literal
{ [ nameValuePair1[, nameValuePair2[, ...nameValuePairN] ] ] }

// Call as constructor
new Object([value])

Another solution with Object

function flattenMap(map) {
    let result = {};
    function recurse(cur, prop) {
        if (Object(cur) !== cur || Array.isArray(cur)) {
            return result[prop] = cur;
        }
        for (let p in cur) {
            recurse(cur[p], prop ? prop+"/"+p : p);
        }
    }
    recurse(map, "");
    return result;
}

Unfortunately, this problem cannot be solved with our template.


Task: sum of intervals

Write a function that takes an array of intervals and returns the sum of all interval lengths. Overlapping intervals should only be counted once. The intervals are represented by a pair of integers as an array. The first interval value will always be less than the second value.

  • Interval example: [1, 5] is an interval from 1 to 5. The length of this interval is 4.

Required result

sumIntervals( [
   [1,2],
   [6, 10],
   [11, 15]
] ); // => 9

sumIntervals( [
   [1,4],
   [7, 10],
   [3, 5]
] ); // => 7

sumIntervals( [
   [1,5],
   [10, 20],
   [16],
   [16, 19],
   [5, 11]
] ); // => 19

Template decision

function sumIntervals(intervals) {
  let sum = 0, max = -Infinity;
  const sortedIntervals = intervals.sort(([a, b], [c, d]) => a == c ? b - d : a - c);
  for (const [start, stop] of sortedIntervals) {
    if (max < start)
      max = start;
    if (max < stop)
      [max, sum] = [stop, sum + stop - max]
  }
  returnsum;
}
  • The sort() method sorts the elements of an array in place and returns the sorted array.
  • The global property Infinity is a numeric value representing infinity.

Solution with multiple functions

function sumIntervals(intervals) {
  intervals = intervals.sort((a, b) => a[0] - b[0]);
  let merged = merge(intervals);
  return merged.reduce((sum, int) => sum + int[1] - int[0], 0);
}
merge(ints) {
  let m = [ints.shift()];
  while(ints.length) {
    m = m.concat(sum(m.pop(), ints.shift()));
  }
  return m;
}
function sum(a, b) {
  if ((Math.max(...a) < Math.min(...b)) === (Math.max(...b) > Math.min(...a))) {
    return a[0] < b[0] ? [a, b] : [b, a];
  }
  return [[Math.min(a[0], b[0]), Math.max(a[1], b[1])]];
}
  • The shift() method removes the first element from the array and returns its value. This method changes the length of an array.
  • The Math.max() method returns the largest of zero or more numbers.
  • The Math.min() method returns the smallest of zero or more numbers.

Task: difference in anagram

Given two words, how many letters must be removed from them to make anagrams? A word is an anagram of another word if they have the same letters (usually in a different order).

Required result

First word : c od e w ar s (4 letters removed)
Second word : ha c k er r a nk (6 letters removed)
result : 10

Template decision

function anagramDifference(w1,w2){
  let ww1=w1.split('');
  let ww2=w2.split('');
  for (let i=0; i<ww1.length; ++i)
  {
    if (ww2.indexOf(ww1[i])!=-1)
    {
      ww2.splice(ww2.indexOf(ww1[i]),1)
      ww1.splice(i,1);
      i--;
    }
  }
  return ww1.length+ww2.length
}
  • The splice() method modifies the contents of an array by removing existing elements and/or adding new ones.

Solution with Object

function anagramDifference(w1,w2){
  return Object.values([w1,"",w2].reduce((a,c,j) => {
    c.split("").forEach(e => {
      (a[e] || a[e]===0) ? a[e] += j-1 : a[e] = j-1;
    });
    return a
  }, {})).reduce((a,c) => a + Math.abs(c), 0)
}
  • The reduce() method applies the reducer function to each element of the array (left to right), returning a single resulting value.
  • The Math.abs() method returns the absolute value of a number.

Task: sum of pairs

Given a list of integers and one sum value, return the first two values ​​(parse from the left) in order of occurrence that add up to form the sum.

Required cutltat

sum_pairs([11, 3, 7, 5], 10)
# ^--^ 3 + 7 = 10
== [3, 7]

sum_pairs([4, 3, 2, 3, 4], 6)
# ^-----^ 4 + 2 = 6, indices: 0, 2 *
# ^-----^ 3 + 3 = 6, indices: 1, 3
# ^-----^ 2 + 4 = 6, indices: 2, 4
#* the whole pair before, and hence this is the correct answer
== [4, 2]

Template decision

const sum_pairs=function(ints, s){
    let cache = new Set(), c, v;
    for( v of ints ){
      if( cache.has(c=s-v) ) return [c,v]
      cache.add(v)
    }
    return undefined
}
  • Set objects allow you to store unique values ​​of any type, both primitives and other types of objects.

Solution with WeakMap

const sum_pairs = (arr, sum) => {
  const map = new WeakMap();
  for (let i = 0; i < arr.length; ++i) {
    if (map[arr[i]]) {
      return [sum - arr[i], arr[i]];
    }
    map[sum - arr[i]] = true;
  }
  return [][0];
};
  • The WeakMap object is a collection of key-value pairs. Only objects can be used as keys, and values ​​can be of arbitrary types.

Task: valid brackets

Write a function that takes a string of parentheses and determines if the parentheses order is valid. The function must return true if the string is valid and false if it is not valid.

Required result

"()" => true
")(()))" => false
"(" => false
"(())((()())())" => true

Template decision

function validParentheses(parens){
  varn = 0;
  for (var i = 0; i < parens.length; i++) {
    if (parens[i] == '(')n++;
    if (parens[i] == ')') n--;
    if (n < 0) return false;
  }
  return n == 0;
}

One line solution

function validParentheses(parens){
    return [...parens].reduce((a,c) => (a+c).replace("()",'') ) == ""?true:false;
}
  • The replace() method returns a new string with some or all of the pattern matches replaced by the replacement. The pattern can be a string or regular expression, and the placeholder can be a string or a function called on each match.

Task: product of consecutive Fibonacci numbers

The Fibonacci numbers are the numbers in the following integer sequence (Fn): 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ... such as F(n) = F(n-1) + F(n-2), where F(0) = 0 and F(1) = 1. Given a number, say prod (for the product), we look for two Fibonacci numbers F(n) and F(n+1) by checking F(n) * F(n+1) = product. Your productFib function takes an integer (prod) and returns an array: [F(n), F(n+1), True] or {F(n), F(n+1), 1} or (F(n), F(n+1), True) depending on the language, if F(n) * F(n+1) = prod. If you don't find two consecutive F(n) confirming F(n) * F(n+1) = prod, you will return [F(n), F(n+1), False] or {F(n), F(n+1), 0} or (F(n), F(n+1), False) F(n) is the smallest such as F(n) * F(n+1) > prod.

Required result

productFib(714) # should return (21, 34, true),
                # since F(8) = 21, F(9) = 34 and 714 = 21 * 34

productFib(800) # should return (34, 55, false),
                # since F(8) = 21, F(9) = 34, F(10) = 55 and 21 * 34 < 800 < 34 * 55
-----
productFib(714) # should return [21, 34, true],
productFib(800) # should return [34, 55, false],

Template decision

function productFib(prod){
  let n = 0;
  let n Plus = 1;
  while(n*nPlus < prod) {
    n Plus = n + n Plus;
    n = n Plus - n;
  }
  return [n, nPlus, n*nPlus===prod];
}
  • The while statement creates a loop that executes the given statement while the condition being checked is true. The logical value of the condition is evaluated before the loop body is executed.

Mathematical solution

function productFib( prod ) // mathy way
{
  const r = ( 1 + Math.sqrt(5) ) / 2;
  let fib1 = Math.round( Math.sqrt( prod / r ) ),
  fib2 = Math.round( fib1 * r );
  if ( fib1 * fib2 === prod ) return [ fib1, fib2, true ];
  for ( [fib1, fib2] = [0, 1]; fib1 * fib2 < prod; [fib1, fib2] = [fib2, fib1 + fib2] );
  return [ fib1, fib2, false ];
}
  • The Math.round() method returns the number rounded to the nearest integer.
  • The Math.sqrt() method returns the square root of a number

Challenge: where are my anagrams?

What is an anagram? Well, two words are anagrams of each other if they both contain the same letters. For example: 'abba' and 'baab' == true 'abba' and 'bbaa' == true 'abba' and 'abba' == false 'abba' and 'abka' == false Write a function that will find all the anagrams of a word from a list. You will be given two inputs a word and an array with words. You must return an array of all anagrams, or an empty array if there are none.

Required result

anagrams('abba', ['aabb', 'abcd', 'bbaa', 'dada']) => ['aabb', 'bbaa']
anagrams('racer', ['crazer', 'carer', 'racar', 'caers', 'racer']) => ['carer', 'racer']
anagrams('laser', ['lazing', 'lazy', 'lacer']) => []

Template decision

function anagrams(word, words) {
  let result = [];
  let test = word.split("").sort().join("");
  
  for (let i=0;i<words.length;i++){
    if(words[i].split("").sort().join("") == test) {
      result.push(words[i]);
    }
  }
  return result;
}

Explanation .split("").sort().join("")

The split() method is used to split a String object into an array of strings by splitting the string into substrings. console.log('32243'.split("")); Output: ["3", "2", "2", "4", "3"]

The sort() method is used to sort the elements of an array in place and returns an array. console.log(["3", "2", "2", "4", "3"].sort()); Output: ["2", "2", "3", "3", "4"]

The join() method is used to join all the elements of an array into a string. console.log(["2", "2", "3", "3", "4"].join("")); Output: "22334"

Two liner solution ;)

function anagrams(word, words) {
  const sword = [...word].sort().join('');
  return words.filter(w => [...w].sort().join('') === sword);
}
  • The filter() method creates a new array with all elements that pass the test specified in the passed function.

Task: snail

Given an n x n array, return the elements of the array from the outermost elements to the middle element, moving clockwise.

Required result

array = [[1,2,3],
         [8,9,4],
         [7,6,5]]
snail(array) #=> [1,2,3,4,5,6,7,8,9]

Template decision

const snail = function(array) {
  let maxx = array[0].length,
    maxy=maxx,
    minx=-1, miny=0,
    x=0, y=0,
    result = [], dir = "r";
  
  for(let i = maxx*maxx;i>0;i--){
    result.push(array[y][x]);
    switch (dir){
      case "u": y--; break;
      case "l": x--; break;
      case "d": y++; break;
      case "r": x++; break;
    }
    if(x==maxx-1 && y==miny){ dir="d"; minx++; }
    else if(x==maxx-1 && y==maxy-1){ dir="l"; miny++; }
    else if(x==minx && y==maxy-1){ dir="u"; maxx--; }
    else if(x==minx && y==miny){ dir="r"; maxy--; }
  }
  return result;
}
  • The switch statement compares the expression against the cases listed within it, and then executes the corresponding statements.
switch (expression) {
  case value1:
    //The instructions are executed here if the result of the expression is equal to value1
    [break;]
  case value2:
    //Instructions corresponding to value2
    [break;]
  ...
  case valueN:
    //Instructions corresponding to valueN
    //statementsN
    [break;]
  default:
    //Here are instructions that are executed in the absence of a corresponding value
    //statements_def
    [break;]
}

Solution c array

function snail(array) {
  let vector = [];
  while (array.length) {
    vector.push(...array.shift());
    array.map(row => vector.push(row.pop()));
    array.reverse().map(row => row.reverse());
  }
  return vector;
}
  • The reverse() method reverses the order of the array elements in place. The first element of the array becomes the last element, and the last element becomes the first.

Task: adding large numbers

Write a function that returns the sum of two numbers. The input numbers are strings and the function must return a string.

Required result

add("123", "321"); -> "444"
add("11", "99"); -> "110"

Template decision

function add(a, b) {
 let zrx = /^0+/;
  a = a.replace(zrx, '').split('').reverse();
  b = b.replace(zrx, '').split('').reverse();
  let result = [], max = Math.max(a.length, b.length);
  for (let memo = 0, i = 0; i < max; i++) {
    let res = parseInt(a[i] || 0) + parseInt(b[i] || 0) + memo;
    result[i] = res % 10;
    memo = (res - result[i]) / 10;
  }
  if (memo) {
    result.push(memo);
  }
  return result.reverse().join('');
}
  • The parseInt() function takes a string as an argument and returns an integer according to the specified base

Solution with arguments

function add(a, b) {
  const sum = +a.slice(-1) + +b.slice(-1) + +(arguments[2] || '').slice(0, 1);
  if (a.length <= 1 && b.length <= 1) return sum + (arguments[2] || '').slice(1);
  let acc = '' + ~~(sum / 10) + sum % 10 + (arguments[2] || '').slice(1);
  return add(a.slice(0, -1), b.slice(0, -1), acc)
}
  • The arguments object is an array-like object that contains the arguments passed to the function.

Task: simple pig in Latin

Move the first letter of each word to the end, and then add "ay" to the end of the word. Leave the punctuation marks intact.

Required result

pigIt('Pig latin is cool'); // igPay atinlay siay oolcay
pigIt('Hello world!'); // elloHay orldway !

Solution with substring

function pigIt(str){
  //Code here
  return str.split(' ').map(word => {
    return word.substring(1) + word[0] + 'ay';
  }).join(' ');
}
  • The substring() method returns a substring of a string between two indices, or from one index to the end of the string.

One liner and RegExp solution

function pigIt(str){
  return str.replace(/\w+/g, match => match.slice(1) + match.charAt(0) + "ay");
}
  • The charAt() method returns the specified characterfrom a line.

Task: concatenate two arrays

Write a function that concatenates two arrays by taking elements from each array in turn.

Required result

[a, b, c, d, e], [1, 2, 3, 4, 5] becomes [a, 1, b, 2, c, 3, d, 4, e, 5]
[1, 2, 3], [a, b, c, d, e, f] becomes [1, a, 2, b, 3, c, d, e, f

Template decision

function mergeArrays(a, b) {
  varres = [];
  let i=0;
  while ((i<a.length) || (i<b.length) ) {
    if (i<a.length) res.push(a[i]);
    if (i<b.length) res.push(b[i]);
    i++;
  }
  return res;
}

Solution with lodash

const _ = require('lodash')

function mergeArrays(a, b) {
  return _.compact(_.flatten(_.zip(a, b)))
}
  • lodash - A modern JavaScript utility library that provides modularity, performance, and additional features. https://lodash.com/

Challenge: trees - maximum sum

You are given a binary tree. Implement the maxSum method, which returns the maximum sum of the route from root to leaf. For example, for the following tree: 17 /
3-10 / /
2 16 1 / thirteen The method should return 23 because [17,-10,16] is the root-to-leaf route with the maximum sum.

Required result

The TreeNode class is available to you:

let TreeNode = function(value, left, right) {
  this value = value;
  this.left = left;
  this.right = right;
};

Template decision

function maxSum(root) {
  if(root == null || root == undefined) return 0;
  let left = maxSum(root.left);
  let righ = maxSum(root.right);
  let sum = Math.max(left,right) + root.value;
  returnsum}
  • The Math.max() method returns the largest of zero or more numbers.

One line solution

maxSum=root=>!root?0:root.value+Math.max(maxSum(root.left),maxSum(root.right))

Task: linked lists - sorted insertion

Write a SortedInsert() function that inserts a node at the correct location in a pre-sorted linked list sorted in ascending order. SortedInsert takes the title of the linked list and the data used to create the node as arguments. SortedInsert() must also return the title of the list.

Required result

sortedInsert(1 -> 2 -> 3 -> null, 4) === 1 -> 2 -> 3 -> 4 -> null)
sortedInsert(1 -> 7 -> 8 -> null, 5) === 1 -> 5 -> 7 -> 8 -> null)
sortedInsert(3 -> 5 -> 9 -> null, 7) === 3 -> 5 -> 7 -> 9 -> null)

Solution with recursion

function Node(data) {
  this.data = data;
  this.next = null;
}
function sortedInsert(head, data) {
  return (head == null || head.data > data)
    ? push(head, data)
    : push(sortedInsert(head.next, data), head.data);
}
  • The push() method adds one or more elements to the end of the array and returns the new length of the array.

Solution with new Node

function Node(data) {
  this.data = data;
  this.next = null;
}

function sortedInsert(head, data) {
  if (head == null) {
    return new node(data);
  }
  let previous, current = head;
  while(data > current data) {
    previous = current;
    current = current.next;
    if (!current) break;
  }
  let node = new Node(data);
  node.next = current;
  if (previous) {
    previous.next = node;
  } else {
    return node
  }
  return head;
}
  • A linked list is a data structure in which one object refers to the next in sequence, storing its address. Each object is called a node. In addition to a reference to the next object in the sequence, each object carries some data (such as an integer value, a reference to a string, etc.)

Task: tic-tac-toe

If we were to set up a tic-tac-toe game, we would like to know if the current state of the board is resolved. Our goal is to create a function that checks this for us!

Required result

Suppose the board is in the form of a 3x3 array, where the value is 0 if the cell is empty, 1 if it is an "X", or 2 if it is an "O", for example:

[[0, 0, 1],
 [0, 1, 2],
 [2, 1, 0]]

We want our function to return:

-1 if the board is not over yet AND no one has won yet (there are empty spaces), 1 if "X" won, 2 if "O" wins, 0 if it's a cat game (i.e. a draw). You can assume that the board passed is valid in the context of a game of tic-tac-toe.

Template decision

function isResolved(board) {
  let row = board;
  let col = [0,1,2].map((i) => [0,1,2].map((h)=>board[h][i]));
  let di1 = [[0,1,2].map((i) => board[i][i])];
  let di2 = [[0,1,2].map((i) => board.reverse()[i][i])];
  let all = row.concat(col,di1,di2);
  if (all.some(x=>""+x=="1,1,1")){return 1;}
  else if (all.some(x=>""+x=="2,2,2")){return 2;}
  else if (all.some(x => x.includes(0))){return -1;}
  else{return 0;};
}
  • The some() method checks if any element of the array satisfies the condition specified in the passed function.
  • The concat() method returns a new array consisting of the array it was called on, concatenatedthis with other arrays and/or values ​​passed as arguments.