DEV Community

Cover image for Blogging My Programming Challenges
Dell  Ward
Dell Ward

Posted on

Blogging My Programming Challenges

Lately I've been applying to dozens of developers jobs with no success. Either I would receive the infamous "we've decided not move forward with your application" email, or nothing at all. And while I know this process takes an amazing amount of patience, I'd be lying if I say I'm not pissed at my current situation. My resume is good enough dammit!

But as I think back on the denials, I start to wonder, would I have made it past first interview anyway? These startups and companies could be sparing me the embarrassment. I've been so focused building up my React portfolio, messing around with X and Y frameworks, that I've neglected to improve my problem solving and algorithm design skills.

Most of us know that white boarding isn't the best way to assess a developer/software engineer, and there are many companies don't bother with them. But the reality is, there are a lot of great companies still using this method. It is what is, for now.

Which is why I decided to do a code challenge per day and every so often document my process to share with the dev.to community. I could list all the reasons why this will be beneficial but Ali Spittel can do it better.

I don't question my ability to finally receive an interview but my chance of getting past that interview is what I'm not so sure of. It's also important because I have a master's in computer science and I feel I should be better at algorithms than I actually am. So even though I know how little a degree matters nowadays, I want to make it mean something to me.

With said lets get coding!

Between Two Sets

My first challenge was called Between Two Sets. Given two arrays, the objective is to create a function that returns an integer denoting the number of integers that are BOTH multiples of all numbers in the first array and factors of all numbers in the second array. These numbers will be between two sets

For example:

a1 = [2,4];
a2 = [16, 32, 96];
getNumbersBetween(array1, array2); // returns 3
// the three numbers, 4, 8, 16, are between the arrays a1 and a2, because they 
// are multiples of 2 and 4. And they are also factors of 16, 32 and 96.
Enter fullscreen mode Exit fullscreen mode

The way I decided to approach solving these challenges is if I can't think up a working solution in 20 minutes I'll search for the solution, because in the real world I probably would have already failed the interview. Before I approached my time limit, I at least knew that I would need to find the lowest common multiple(LCM). I just didn't know how to find them in an algorithmic way.

I saw an answer in the HackerRank discussions which completed my thought process. The solution was to find the LCM(yes, I was close!) of the first array and the greatest common divisor(GCD) of the second array.

To find the greatest common divisor:

function gcd(a, b){
    while(b > 0){
        var temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}
Enter fullscreen mode Exit fullscreen mode

This function continuously finds the remainder of two numbers, a and b. While b is greater than 0, the current value of b will become the new value of a and the remainder will be the new value of b. Once the loop breaks, the function will return the GCD, which will be the last known divisor that was used to evaluate a remainder.

Here's an example of how this function works:

gcd(35, 14):

1st loop: 35 % 14 = 7
2nd loop: 14 % 7 = 0 //loop ends because the remainder is not greater than 0;

7 is the greatest common divisor
Enter fullscreen mode Exit fullscreen mode

However, we have an array of numbers and you can't find the greatest common divisor of more than two numbers at a time. So you must create a function that takes in the array as input to iteratively find the GCD, two elements at a time:

const gcdOfArray = array => {
    result = array[0]
    for(var i = 1; i < array.length; i++){
        result = gcd(result, array[i])
    }
    return result;
}
Enter fullscreen mode Exit fullscreen mode

Now that we know how to retrieve the greatest common divisor, finding the least common multiple is less of a pain. The LCM, with respect to a and b, is just the product of a and b divided by their GCD:

const lcm = (a, b) => {
    return (a * b) / gcd(a, b);
}
Enter fullscreen mode Exit fullscreen mode

Again, we are not just dealing with two numbers so we need a function to find the LCM of an entire array:

const lcmOfArray = array => {
    result = array[0]
    for(var i = 1; i < array.length; i++){
        result = lcm(result, array[i])
    }
    return result;
}
Enter fullscreen mode Exit fullscreen mode

Now that we are able to find both the LCM and GCD, to find all the numbers in between, we need to loop through the multiples of the LCM until the last multiple is equal to or greater than the GCD:

var lcm = lcmArray(a1); //lcm of first array
var gcd = gcdArray(a2); //gcd of second array

for(var i = 1; i*lcm <= gcd; i++){
    /*
        loop though multiples of our least common multiples
        until it reaches the greatest common divisor
    */
}
Enter fullscreen mode Exit fullscreen mode

Using this loop, we can check if the current multiple is a factor of the GCD by performing a modulo expression. If this statement is true then count it as a number that is between two sets:

var lcm = lcmArray(a1); //lcm of first array
var gcd = gcdArray(a2); //gcd of second array
var count = 0;

for(var i = 1; lcm * i <= gcd; i++){
    if(gcd % (lcm * i) == 0){
        count++
    }
}
return count // the number of integers between two sets
Enter fullscreen mode Exit fullscreen mode

Voilà!

And that's it, you can check the entire function at my gist here. Looking at the entire code in full was hard to grasp for me, at first. But once broken down, it actually got pretty simple. If you've seen any mistakes or know of a better algorithm, I'd love to know! Until the next challenge...✌️🏾

Top comments (2)

Collapse
 
dwd profile image
Dave Cridland

Now, my problem would have been that I have, after two decades of experience working with code, no idea how to do this - but more importantly, no idea why I'd ever need to know.

Honestly, it's like this for me:

Interviewer: "Can you describe how a Red Black tree works?"
Me: "Nope. I just use std::map<> or {} or whatever and the nice programming language or library does it for me. But I can list the properties of the tree, the operations I can perform, and the complexity of them."

I can also tell you that while std:map is normally a Red Black tree in C++, it needn't be, and it's instead a weird hybrid thing in quite a few implementations in order to improve the iteration performance, which in a traditional RB tree really sucks.

Of course, none of this is very useful for the traditional dev interview, leading me to believe there's no way I could get an entry-level developer job nowadays...

Collapse
 
dellward profile image
Dell Ward

This is what makes it so frustrating. Forget experience and the projects you've done, if you can't think of algorithm within 30-45 minutes, you're not good enough. Smh. But I'm gonna keep cracking at this thing. Don't give up, man!