540

# Implementing the LHC on a Whiteboard

A survival guide for passing coding interviews. May 05, 2016

## Transcript

1. Art and photos by Summer Gray
Implementing the
LHC on a Whiteboard
How to survive
coding interviews
of all shapes and sizes

2. Why Coding Interviews?

3. This Mismatch…
❖ Is keeping programmers from getting jobs
❖ Is likely due to a lack of interview training (especially
compared to the other training we do in our industry)
❖ Is ﬁxable

4. What Is a Coding Interview?
❖ Take homes
❖ With or without time limits
❖ Technical interviews
❖ “Pairing”
❖ Auditions

❖ I work for NoRedInk
❖ We get a lot of applicants
❖ Roughly 75% of the candidates fail our “take home”
❖ Around 30% of the rest fail their ﬁrst technical interview
❖ I see a lot of what doesn’t work

6. We’re hiring
It’s In My Interest To
Improve How You Do
The better candidates do,
the faster we hire and
the less I interview

7. What This Talk Is Not?
❖ Guaranteed
❖ A moral judgement
❖ All-knowing

8. How Can You Prepare?

9. Study
❖ Interviews commonly focus on a certain subset of
programming knowledge
❖ This probably isn’t knowledge that you use daily
❖ Ensuring it’s fresh in your brain can help

10. Concepts Data Structures Algorithms
Big O Notation Hash Tables Binary Search
Dynamic Programming/
Memoization
Trees/Tries/Graphs
Depth-First Search
Merge Sort/
Quicksort
Bit Manipulation Heaps
Stacks and Queues

11. Concepts Data Structures Algorithms
Big O Notation Hash Tables Binary Search
Dynamic Programming/
Memoization
Trees/Tries/Graphs
Depth-First Search
Merge Sort/
Quicksort
Bit Manipulation Heaps
Stacks and Queues

12. http://bigocheatsheet.com/

13. Big O Notation
❖ A metric used to describe an upper bound on algorithm
efﬁciency
❖ Can be used for time or space
❖ Drops constants and non-dominant terms
❖ Adds independent work; multiplies dependent work
problems faster and easier!

14. def sum_and_product(nums)
{ sum: nums.inject(0, :+),
product: nums.inject(1, :*) }
end
p sum_and_product(1..10)

15. def sum_and_product(nums)
{ sum: nums.inject(0, :+),
product: nums.inject(1, :*) }
end
p sum_and_product(1..10)
O(n)

16. def sum_and_product(nums)
{ sum: nums.inject(0, :+),
product: nums.inject(1, :*) }
end
p sum_and_product(1..10)
O(n)

17. module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
end
p Fib.recursive(10)

18. module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
end
p Fib.recursive(10)
O(2n)

19. module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
end
p Fib.recursive(10)
O(branchesdepth)
O(2n)

20. def shared_count(a, b)
sorted = b.sort
a.count { |i|
sorted.bsearch { |j| j >= i } == i
}
end
p shared_count(
[35, 55, 13, 49, 40, 59, 27],
[39, 40, 60, 17, 55, 58, 35]
)

21. def shared_count(a, b)
sorted = b.sort
a.count { |i|
sorted.bsearch { |j| j >= i } == i
}
end
p shared_count(
[35, 55, 13, 49, 40, 59, 27],
[39, 40, 60, 17, 55, 58, 35]
)
O(b log b + a log b)

22. def shared_count(a, b)
sorted = b.sort
a.count { |i|
sorted.bsearch { |j| j >= i } == i
}
end
p shared_count(
[35, 55, 13, 49, 40, 59, 27],
[39, 40, 60, 17, 55, 58, 35]
)
O(b log b + a log b)

23. def shared_count(a, b)
sorted = b.sort
a.count { |i|
sorted.bsearch { |j| j >= i } == i
}
end
p shared_count(
[35, 55, 13, 49, 40, 59, 27],
[39, 40, 60, 17, 55, 58, 35]
)
O(b log b + a log b)

24. A: 13, 27, 35, 40, 49, 55, 59
B: 17, 35, 39, 40, 55, 58, 60
Given two sorted arrays, ﬁnd the elements
in common. The arrays are the same length
and each has all distinct elements.

25. A Brute Force Solution
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
shared = a.select { |n| b.include?(n) }
p shared

26. A Brute Force Solution
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
shared = a.select { |n| b.include?(n) }
p shared

27. Bungling Towards Ideal
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
i = 0
shared = b.each_with_object([ ]) do |n, array|
while i < a.size && a[i] < n
i += 1
end
array << n if a[i] == n
end
p shared

28. Bungling Towards Ideal
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
i = 0
shared = b.each_with_object([ ]) do |n, array|
while i < a.size && a[i] < n
i += 1
end
array << n if a[i] == n
end
p shared

29. Bungling Towards Ideal
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
i = 0
shared = b.each_with_object([ ]) do |n, array|
while i < a.size && a[i] < n
i += 1
end
array << n if a[i] == n
end
p shared

30. Straightforward Linear
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
c = b.each_with_object({ }) do |n, hash|
hash[n] = true
end
shared = a.select { |n| c.include?(n) }
p shared

31. Straightforward Linear
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
c = b.each_with_object({ }) do |n, hash|
hash[n] = true
end
shared = a.select { |n| c.include?(n) }
p shared

32. Ruby Can Sometimes Help
❖ Minitest::Benchmark supports:
❖ assert_performance_constant()
❖ assert_performance_exponential()
❖ assert_performance_linear()
❖ assert_performance_logarithmic()
❖ assert_performance_power()

33. Analyzing Algorithms
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
def memoized(i)
cache = Hash.new { |hash, n| hash[n] = n < 2 ? n : hash[n - 2] + hash[n - 1] }
cache[i]
end
def dynamic(i)
return i if i < 2
a, b = 0, 1
(i - 2).times do a, b = b, a + b end
a + b
end
end

34. Analyzing Algorithms
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
def memoized(i)
cache = Hash.new { |hash, n| hash[n] = n < 2 ? n : hash[n - 2] + hash[n - 1] }
cache[i]
end
def dynamic(i)
return i if i < 2
a, b = 0, 1
(i - 2).times do a, b = b, a + b end
a + b
end
end

35. Analyzing Algorithms
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
def memoized(i)
cache = Hash.new { |hash, n| hash[n] = n < 2 ? n : hash[n - 2] + hash[n - 1] }
cache[i]
end
def dynamic(i)
return i if i < 2
a, b = 0, 1
(i - 2).times do a, b = b, a + b end
a + b
end
end

36. Analyzing Algorithms
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
def memoized(i)
cache = Hash.new { |hash, n| hash[n] = n < 2 ? n : hash[n - 2] + hash[n - 1] }
cache[i]
end
def dynamic(i)
return i if i < 2
a, b = 0, 1
(i - 2).times do a, b = b, a + b end
a + b
end
end

require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibRecursiveBench < Minitest::Benchmark
def self.bench_range
[1, 3, 30]
end
def bench_recursive_fib
assert_performance_exponential do |n|
Fib.recursive(n)
end
end
end

require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibRecursiveBench < Minitest::Benchmark
def self.bench_range
[1, 3, 30]
end
def bench_recursive_fib
assert_performance_exponential do |n|
Fib.recursive(n)
end
end
end

require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibRecursiveBench < Minitest::Benchmark
def self.bench_range
[1, 3, 30]
end
def bench_recursive_fib
assert_performance_exponential do |n|
Fib.recursive(n)
end
end
end

require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibMemoizedBench < Minitest::Benchmark
def self.bench_range
bench_exp(1, 1_000)
end
def bench_memoized_fib
assert_performance_linear do |n|
Fib.memoized(n)
end
end
end

require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibMemoizedBench < Minitest::Benchmark
def self.bench_range
bench_exp(1, 1_000)
end
def bench_memoized_fib
assert_performance_linear do |n|
Fib.memoized(n)
end
end
end

require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibMemoizedBench < Minitest::Benchmark
def self.bench_range
bench_exp(1, 1_000)
end
def bench_memoized_fib
assert_performance_linear do |n|
Fib.memoized(n)
end
end
end

require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibDynamicBench < Minitest::Benchmark
def bench_dynamic_fib
assert_performance_linear do |n|
Fib.dynamic(n)
end
end
end

require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibDynamicBench < Minitest::Benchmark
def bench_dynamic_fib
assert_performance_linear do |n|
Fib.dynamic(n)
end
end
end

45. The classic “Nine Balls” interview brainteaser
You have nine balls. Eight are the same weight and
one is heavier. You are given a balance which tells
you only wether the left side or right side is heavier.
Find the heavy ball in just two uses of the scale.

46. Practice
❖ Work code challenges
❖ http://exercism.io/
❖ http://rubyquiz.com/
❖ You need to be able to consistently solve Exercism size
problems in one hour

47. More Study and Practice

48. Have Some Open Source
❖ Be able to point to a published gem
❖ It barely matters what it does
❖ The most important details are a strong README, clean
code, tests, and documentation
❖ A small gem is ﬁne

49. What To Do While Coding?

50. Goals
❖ Not the same as normal on the job programming
❖ You need to avoid being seen as a bad hire
❖ If you can avoid major mistakes, you’re ahead

51. Tip #1
And/or ask as many clarifying questions
as needed

52. Tip #2
Many candidates do not do this

53. Tip #3
Stop and Think
You don’t have time not to do this

54. Tip #4
Think Out Loud
Magic words:
• “My ﬁrst thought is…”
• “I might circle back to this…”
• “I don’t know.”

55. Tip #5
Don’t Make
Show that you have personality and
a little bit of humor,
but keep it appropriate

56. Tip #6
Start at the
Hard Part
• Don’t begin by designing objects
• Jump straight to the interesting bit
• Fake input as needed
• Ignore UI completely

57. Tip #7
Test the Core
Pretty much no one tests anything,
so just a little, at the key place, is a win

58. Tip #8
Avoid Dependencies
And don’t recreate them manually

59. Tip #9
Write Less Code
Don’t “gold plate”

60. Tip #10
Ignore “Bonus”
Challenges
Seriously, it’s just not worth it

61. Tip #11
Consider Time
Limits Soft
Submit on time,
but resubmit later if needed

62. Tip #12
Show Off Your
Text Editing Skills
• Know ﬁve editing shortcuts
• Make one multiple cursors or macros

63. Maximizing for Success
❖ You probably won’t nail all of my tips every time
❖ That’s ﬁne
❖ Interviews are hard for everyone and everyone makes
mistakes
❖ Hit as many of the points we’ve discussed as you can
❖ Those you get will help

64. Thanks and
I hope you ace your interviews!