Discussion, Questions, and Resources for Part 2 (JavaScript Basic Algorithms, Object-Oriented, and Functional Programming - April 2018 Cohort)

Discussion, Questions, and Resources for Part 2 (JavaScript Basic Algorithms, Object-Oriented, and Functional Programming - April 2018 Cohort)
0

#1

TOPIC INFORMATION

See the full schedule for the April 2018 JavaScript Algorithms and Data Structures cohort.

This topic is for those of us who are participating in the April 2018 JavaScript Algorithms and Data Structures cohort. Even though this topic is mainly for those participating in the cohort, it’s totally ok for others to participate as desired. All are welcome! :national_park:

This topic covers the following sections of the fCC beta curriculum:

DEADLINE: 5/31/2018 11:59PM PST

RESOURCES


April 2018 fCC Cohort - JavaScript Algorithms and Data Structures
April 2018 fCC Cohort - JavaScript Algorithms and Data Structures
#2

MEMBERS

@camper, @angelinalblyth, @yoizfefisch, @NariRoh, @gilvarry, @emilio12345, @wmooney1984, @verde79, @Asjas, @kevin0110w, @bushbass, @ecmonzon, @reginabfly, @Gigahood, @zaynaib


#3

MEMBERS CONTINUED …

@suzannekinyenje, @nickoless, @lbeth, @ddcas, @RobGoelz, @KatFrog, @coderati, @RReddVar, @vagrahb, @wade1928, @webdevdjm, @Poojabedur, @uzorjchibuzor, @RHoneyman87, @Techne3


#4

MEMBERS CONTINUED …

@smsguy927, @Foo_Dog, @nvrqt03, @Saddam, @clickingmouse, @brityank, @OllL, @wesam-mustafa, @jgsimmerman, @davemowery, @vbartolomei1, @catherinewoodward, @Johnrose, @mohamedkhaledyousef


#5

hey guys,

i’m on the Basic Data Structures: Iterate Through All an Array’s Items Using For Loops. I’m not sure why, but it looks like I have an extra array around my solution which is throwing it off.

function filteredArray(arr, elem) {
  let newArr = [];
  // change code below this line
 for (let i = 0; i < arr.length; i++) {
        if (arr[i].indexOf(elem) !== -1) {
        arr.splice(i, 1);
        newArr.push(arr);
      }  
    }
  // change code above this line
  return newArr;
}

// change code here to test different cases:
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));

any ideas where I’m off?


#6

@nvrqt03 I think your logic in the code above is to determine if elem is in the subArray (arr[i]) and if it is, remove arr[i] from the original arr. When the loop finishes going through each subArray, you return what’s left in arr since all of the matching subArrays have been removed. Is this correct?

The way I thought about this one was to only add subArrays to newArr that don’t have elem in them. So, if elem is not in arr[i] then add that arr[i] to newArr. Does that make sense? I find it easier to reason through it this way as opposed to modifying the array I’m looping through and keeping track of how that works.

Here’s how I did it in case it helps to see my logic:

function filteredArray(arr, elem) {
  let newArr = [];
  // change code below this line

  for (let indexArr = 0; indexArr < arr.length; indexArr++) {

    // Create subArr variable to reuse as needed
    let subArr = arr[indexArr];

    // Check to see if elem is in subArr, if not, it will return -1
    if (subArr.indexOf(elem) === -1) {

      // Since elem is not in subArr, add subArr to newArr.
      newArr.push(subArr);
    }
  }
  // change code above this line
  return newArr;
}

I’m not sure how to complete the challenge using the logic you present. If you figure it out, please share it here so I (and others) can learn from it. :sunny:


#7

@nvrqt03 I was able to pass the exercise using splice().

function filteredArray(arr, elem) {
    let newArr = [];
    // change code below this line
    
   for (let i = 0; i < arr.length; i++) {
        if (arr[i].indexOf(elem) !== -1) {
        arr.splice(i, 1);
        i--; // account for array modification
      }  
    }
      
    newArr = arr;
    // change code above this line
    return newArr;
  }
  
  // change code here to test different cases:
  console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));

#8

great solutions guys! glad to see someone got splice to work. basically I was trying to say that if the element does NOT exist in the array -

if (arr[i ].indexOf(elem) !== -1 

then to splice them from the array. they will make their own new array of uh… undesirables? then we will push what’s left to the newArr and return that. however I noticed @smsguy927 you didn’t push to the new array, and I’m not sure how i- - ; works in this situation.

sorry for the late reply, I code early in the morning. usually I can get some coding in after work as well, or respond during work. It was busy yesterday though.


#9

splice() modifies the array it is called on and it shifts the indexes of the array when no elements are replaced after splicing. i-- accounts for this modification and ensures that arr[i] will point to the next element in the array in the next iteration. Then I assign what’s left in the initial array to the result array.


#10

if (arr[i].indexOf(elem) !== -1)

@nvrqt03 This will return true if elem is in arr[i].

indexOf(elem) either returns the index of the item in the array that matches elem or returns -1 if there is no match.

In the above, you’re returning true if arr[i].indexOf(elem) does not equal !== -1, i.e. return true if arr[i].indexOf(elem) returns an index of a matched item in the array, or return true if it returns anything other than -1.

The following returns true if elem is NOT in arr[i]:

if (arr[i].indexOf(elem) === -1)

That’s how I’m reading this. Let me know if I’m wrong.


#11

if (arr[i].indexOf(elem) === -1)
if that returns true, then the element is not in the current sub-index. that is exactly what we’re looking for. so from here, you can skip all the slicing and splicing and just:
newArr.push(arr[i])

for (let i = 0; i < arr.length; i++) {
if (arr[i].indexOf(elem) === -1) {
newArr.push(arr[i]);
}
}


#12

Here are my solutions for the first three algorithms:

Convert Celsius to Fahrenheit
function convertToF(celsius) {
  return (celsius * (9/5)) + 32;
}
Reverse a String

I came up with the following, which splits the string into an array of letters and then adds the letters to a new string using the map() function.

function reverseString(str) {
  let newStr = "";
  return str.split('').map(letter => newStr = letter + newStr)[newStr.length-1];
}

However, after looking through the freeCodeCamp Algorithm Challenge Guide: Reverse a String topic, I realized that I overcomplicated this and should’ve looked to built-in functions instead:

function reverseString(str) {
  return str.split('').reverse().join('');
}
Factorialize a Number

I started with the following, using a for loop to loop through the range between num and one and then multiply the counter by the current result:

function factorialize(num) {
  let result = 1;
  for (let numIndex=num; numIndex > 0; numIndex--) {
    result *= numIndex;
  }
  return result;
}

However, after looking at the freeCodeCamp Algorithm Challenge Guide: Factorialize A Number topic, and watching the video on recursion listed in the guide and this part of another video on recursion, I came up with this, which is more difficult to understand, but cleaner overall:

function factorialize(num) {
  if (num === 0) return 1;
  return num * factorialize(num-1);
}

The following is another version shared by @Kagerjay (freeCodeCamp Algorithm Challenge Guide: Factorialize A Number) that I like the best, once I wrap my head around recursion:

function factorialize(num) {
  return num === 0 ? 1 : num * factorialize(num-1);
}

This Recursion and Recursive Functions video does a great job of explaining how the above recursive factorialize function works.

Any thoughts on the above solutions? Did anyone do anything different or find helpful resources to learn more about these? :sunny:


#14

for the first one, converting celsius to fahrenheit, I essentially got the same as you. I only let fahrenheit equal the celsius conversion, and returned fahrenheit.

reversing a string - i got your second solution.

factorialize - slightly different -

```function factorialize(num) {
if (num === 0 || num === 1)
return 1;
for (let i = num - 1; i >= 1; i–) {
num *= i;
}
return num;
}

I’ll definitely check out that recursion video!

Here are a couple others:

find the longest word in a string:

```function findLongestWordLength(str) {
let largestWord = 0;
str = str.split(’ ');
for (let i = 0; i < str.length; i++) {
if (str[i].length > largestWord) {
largestWord = str[i].length;
}
}
return largestWord;
}

return largest numbers in arrays:

```function largestOfFour(arr) {
let largestNumber = [0,0,0,0];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] < 0) {
arr[i].sort(function (a, b) {
return a - b;
});
largestNumber[i] = arr[i][0];
}
if (arr[i][j] > largestNumber[i])
largestNumber[i] = arr[i][j];
}
}
return largestNumber;
}

I’m working on the Confirm the Ending challenge. I think I"m close, but its inconsistent. its finding anything, not just at the end.

function confirmEnding(str, target) {
// “Never give up and good luck will find you.”
// – Falcor
if (str.lastIndexOf(target) > 0) {
return true;
}
else {
return false;
}
}


#15

@nvrqt03 Thanks for sharing! Anyone else want to share or have comments on any of the solutions shared so far?

Here are my solutions for the next three algorithms.

Find the Longest Word in a String

For Of Loop
I like this one the best at this point in my understanding of JavaScript because it’s straightforward and there’s no unseen things happening.

function findLongestWordLength(str) {
  let longest = 0;
  let wordsArr = str.split(' ');

  for (let word of wordsArr) {
    if (word.length > longest) {
      longest = word.length;
    }
  }
  return longest;
}

Filter()
This is similar to the For Of Loop, but it uses filter() instead. I’m not sure if there are benefits to doing it this way.

function findLongestWordLength(str) {
  let longest = 0;
    str.split(' ').filter(word => {if (word.length > longest) longest = word.length});
  return longest;
}

In the Javascript Coding Challenge #4: Find Longest Word (Freecodecamp), they mention using the sort() method. In the fCC Guide, they recommend two other ways, one using reduce() and Math.max and the other way is to solve this with recursion.

Return Largest Numbers in Arrays

filter() and map()
My first attempt returned the following:

function largestOfFour(arr) {
  
  let largestArr = [];
  
    // Apply (i.e. map) the following filter to each sub array within the array
    arr.map(function(subArr) {
  
        let largest = 0;

        /*
          Filter the largest number from each sub array
          if the number is greater than the previous largest number 
          OR the number is less than zero and the previous largest number is zero
          then set largest to num
        */
        subArr.filter(num => {if (num > largest || (num < 0 && largest === 0)) largest = num});


        // Push the largest number of the sub array to the largestArr array
        largestArr.push(largest);
    
    });
  
  return largestArr;
}

map() and reduce()
I was able to break it down more, which is close to the example in the Return Largest Numbers in Arrays fCC guide entry and less complicated than my first attempt:

function largestOfFour(arr) {
  
  let largestArr = [];
  
    arr.map(subArr =>
            largestArr.push(subArr.reduce((previous, current) =>
                                          previous > current ? previous : current)));
      
  return largestArr;
}
Confirm the Ending

slice()
This is what I ended up with for my first attempt.

function confirmEnding(str, target) {
  return str.slice(str.length - target.length, str.length) === target;
}

substr()
The Confirm the Ending fCC Guide entry suggests another (better) way to do this using substr(). Again, I need to remember to look for better, more appropriate built-in methods:

function confirmEnding(str, target) {
    return str.substr(-target.length) === target;
}

Hopefully, the more I do this the more likely it’ll be that I’ll pick more appropriate methods for my solutions. What do you all think? Does anyone have solutions that aren’t shown or mentioned above? :sunny:


#16

My solution for Return Largest Numbers in Arrays.

I use map() and ES6 spread operator (the 3 dots! … :smile:)

function largestOfFour(arr) {
  return arr.map(chunk => Math.max(...chunk));

  // arr.map() grabs subarrays (I call it chuck here) and call the Math.max function on it to find the largest number in each subarray. 
}

Hope this helps!


#17

I found a great tool for debugging your JavaScript code. It also offers other languages like Python and Ruby.
Basically, it visualizes every single execution of the code to help you debugging.
Not only debugging, I got tons of help to understand JS functions better and faster while solving the Basic Algorithm Scripting section.

The link :point_down:
http://pythontutor.com/visualize.html#mode=edit


#18

@NariRoh Yes! That is a very elegant solution and it’s backed up by the curriculum in the ES6: Use the Spread Operator to Evaluate Arrays In-Place challenge. :fireworks: Thank you!

Here’s a link showing your solution in action using the pythontutor.com service you recommend above. Thank you for that recommendation!


#19

Here are my solutions for the next three algorithms:

Repeat a String Repeat a String

My first attempt looked like the following:

function repeatStringNumTimes(str, num) {
  let returnStr = '';
  
  for (let numCount=0; numCount < num; numCount++) {
    if (num > 0) {
      returnStr += str;
    }
  }
  
  return returnStr;
}

In thinking about it further and attempting to figure out a recursive way to accomplish this, I figured this out:

function repeatStringNumTimes(str, num) {
  return num <= 0 ? "" : str + repeatStringNumTimes(str, num-1);
}

The Repeat a String Repeat a String fCC guide shows a while loop solution, recursive solution, and a solution that uses the repeat() method, which the challenge says not to use. I think the while loop solution is more straightforward and easier to understand than my for loop solution above:

function repeatStringNumTimes(str, num) {
  var accumulatedStr = '';

  while (num > 0) {
    accumulatedStr += str;
    num--;
  }

  return accumulatedStr;
}
Truncate a String

This was what I came up with:

function truncateString(str, num) {
  return str.length > num ? `${str.slice(0, num)}...` : str;
}

Interestingly, I think the Truncate a String fCC guide makes it more complicated than it has to be, at least with the current test cases. For instance, line 5 of the advanced code solution is:

return str.slice(0, num > 3 ? num - 3 : num) + '...';

If one uses the following instead, it’ll still pass all of the tests without the need to use another ternary operator:

return str.slice(0, num) + '...';

The advanced solution then becomes very similar to my solution above, except I use a template literal.

I may submit a suggested change to the guide entry if I get the time and energy.

Finders Keepers

My first attempt looked like this:

function findElement(arr, func) {
    for (let num of arr) {
        if (func(num)) return num;
    }
}

Then, I refactored using filter() to get this:

function findElement(arr, func) {
  return arr.filter(item => func(item) ? item : undefined)[0];
}

That’s not too bad, a little awkward maybe. However, according to the Finders Keepers fCC Guide, there’s a much better way to do this using the filter() method:

function findElement(arr, func) {
  filterArr = arr.filter(func);
  return filterArr[0];
}

Which can be refactored even further to:

function findElement(arr, func) {
  return arr.filter(func)[0];
}

Any suggestions for improvement on the above solutions?

How’s everyone doing so far? I’ve noticed that the algorithms tend to take me longer to work on and figure out, especially if I take into account the research I do after I come up with a working solution in order to make that solution better. Anyone else experiencing this? :sunny:


#20

I got this for Finders Keepers

function findElement(arr, func) {
  return arr.find(func);
}

This was my first pass

function findElement(arr, func) {
  for(let i = 0; i < arr.length; i++){
    if(func(arr[i])){
      return arr[i]
    }
  }
}

#21

Thanks @camper!

I usually use ‘Live Programming Mode’ I think it’s better :slight_smile:

Link here: http://pythontutor.com/live.html#mode=edit