Skip to content

Instantly share code, notes, and snippets.

@christopher-baek
Last active February 3, 2022 17:31
Show Gist options
  • Save christopher-baek/7e3e84c3add00aafa25c7d5431912085 to your computer and use it in GitHub Desktop.
Save christopher-baek/7e3e84c3add00aafa25c7d5431912085 to your computer and use it in GitHub Desktop.
Bloc.io Full Stack Mentor - Candidate Assessment Response

Hey student,

Big O notation is a complex concept to grasp, but ironically, the point of it is actually to try simplify the description of your code! The way I like to think about Big O notation is to think about the number of lines of code that have to be executed with extremely large inputs and to visualize what this actually looks like. This is probably better explained with some examples (look along with this image: https://apelbaum.files.wordpress.com/2011/10/yaacovapelbaumbigoplot_thumb.jpg):

O(1)

def get_value(elements, index):
  return elements[index]

This is O(1) (gray line) because no matter how big the elements array is and no matter what the index value is (assuming it's valid), the time to execute the code will always be the same.

O(N)

def sum(elements):
  sum = 0

  for i in xrange(len(elements)):
    sum += elements[i]

  return sum  

This is O(n) (blue line) because this loop will take longer and longer to run in direct relation to the size of the elements array, i.e., the size of the data input.

O(N^2)

def sum(elements):
  sum = 0

  for i in xrange(len(elements)):
    for j in xrange(len(elements)):
      sum += elements[j]

  return sum

First, don't worry about what this code is doing because it's a contrived example. This is O(N^2) because of the nested loop. Let's say the size of the elements array were 1, this would only run 1 line of critical code. Let's say the size of the elements array were 2, this would now have to run 4 lines of critical code (in combos of (i, j): (0, 0), (0, 1), (1, 0), (1, 1)). If the size of the elements array were 3, this would have to run 9 lines of code. See how the number of lines of critical code that have to execute is the square of the number of input items? If you look at the graph, you can see that after a certain point, the execution time grows faster than the number of elements, whch means an O(N^2) might not perform well for large inputs.

O(log N) The typical example of an O(log N) algorithm (red line) is a tree traversal, which is a lot of code for now, but I can share with you later if you think it would be helpful. If you take a look at the graph, the important thing to see is that this is almost the opposite of an O(N^2) algorithm. Interestingly, it's slower than an O(N^2) algorithm for small inputs, but scales well for large inputs because the execution time doesn't grow as fast in relation to the number of inputs.

Hope that helps!

  • Mentor

Hey student,

Great question! Deciding when to use a library vs. a framework is a decision you will face with any project.

This is how I like to think about it:

A library is like a toolbox in that a library may offer tons of tools, but you have the freedom to pick and choose only the tools you need. In this sense, a library is considered a little more "light weight" since you're only using the pieces you want, and you have more control of what's happening and how things happen in your application. It's sort of like just picking up an external hard drive and dragging and dropping your phone's photos to the hard drive to back them up.

With a framework, you usually have to do things in the way of the framework, so some consider this a little more restrictive and "heavy weight." Sometimes you lose a little control of how things happen, but as long as you "follow the rules" of the framework, you might be able to achieve your result a little faster or easier. It's sort of like buying an iPhone, a Mac, and subscribing to iCloud in order to get your photos backed up... as long as you follow the rules, it just works!

  • Mentor
https://www.bloc.io/resources/full-stack-mentor-candidate-assessment

Hey student,

This is a really tricky problem!

Looking at your code, it looks like the div elements would normally be rendered vertically, but you got them to render horizontally by applying the tier class with the float: left property. Good job! The tricky part here is knowing how the parent elements of elements with a float property behave. In a nutshell, the height of the child elements (the ones with the float property) don't contribute to their parent element's height, so the parent element "collapses".

A quick fix would be to apply the display: inline-block property to the parent element of the div.tier elements, but there are many different (and possibly better) solutions.

Look into the following for a better understanding:

Hey student,

Let's start by rubber ducking (https://en.wikipedia.org/wiki/Rubber_duck_debugging) your code:

  • It looks like you have three button elements, each with an ID, followed by some JavaScript. Everything looks good so far.
  • In your JavaScript, it looks like you have an array called prizes followed by a loop that is doing the bulk of the work. The loop looks fine.
  • In the loop, it looks like you are iterating through the indexes of the array, and trying to use that index to display a different alert for each button.

Does that strategy sound correct?

I think the behavior you are seeing is what a lot of people consider one of the "gotchas" of JavaScript.

Let's start by verifying what value is being held in your loop variable. Instead of calling alert with the value from the array, try calling it with just the index and see what happens (or try logging the value of btnNum to the console). Are you seeing the value you expect?

Do you notice anything about the value you are seeing in relation the size of the array (or more specifically, the exit condition of the loop)?

Try assigning the onclick handler in a separate function and calling that in your loop, i.e., something like this:

function(btnNum, prizes) {
  // TODO: assign onclick handler here
}

Review variable scoping in JavaScript to really understand the behavior.

  • Mentor

Hey student,

I don't have any first hand experience with Rails (I'm a Python guy :)), but I think an example here might help since there are similar concepts in Django (the Python equivalent of Rails).

Let's say you have a RECORD table, a USER table, and an ACCOUNT table. Your classes might look something like this:

class User:
  Account account
  List<Record> records

Now let's say you wanted to retrieve the records for a particular user, Rails might do the following:

  • A query for the USER you are looking for
  • A query for the ACCOUNT associated with the USER
  • A query for the RECORDS associated with the USER

This is not necessarily bad, but you might not need the ACCOUNT information (i.e., there's an unnecessary query being run). Also, a USER is tied to a particular ACCOUNT and a set of RECORDS. Switching owners/accounts might be difficult!

What if things were restructured like this:

class User:
  Account account

class Account
  List<Record> records

Rails might do the following:

  • A query for the USER joined with the ACCOUNT table joined with the RECORD table

The query becomes a little more efficient.

The different between has_one and has_many should be synonymous with a 1:1 and 1:n relationship, respectively.

Hope that helps!

  • Mentor

Hey student,

At a high level, SQL injection is basically a type of malicious attack that might be used against your website. Here's a quick example:

Let's say you are trying to retrieve all records for a particular user. You might execute something like this:

sql = "SELECT *
FROM RECORDS
WHERE USERNAME = 'username'"

database.execute(sql)

Now let's say you want to execute for this all users based on the username. You can't write a query for every user, right? You could do something like this:

username = get_user_input()

sql = "SELECT *
FROM RECORDS
WHERE USERNAME = '" + username + "'"

database.execute(sql)

But if the user sent in something like this for their input, they might delete your entire database:

"user'; DELETE FROM RECORDS; '1' = '1"

In a nutshell, that's SQL injection. In a nutshell, you should never trust your users' input! Use parameterized queries (https://blogs.msdn.microsoft.com/sqlphp/2008/09/30/how-and-why-to-use-parameterized-queries/) and scrub your user input to protect your application and your users!

  • Mentor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment