Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Implementing the LHC on a Whiteboard

jeg2
May 05, 2016

Implementing the LHC on a Whiteboard

A survival guide for passing coding interviews.

jeg2

May 05, 2016
Tweet

More Decks by jeg2

Other Decks in Programming

Transcript

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

    View Slide

  2. Why Coding Interviews?

    View Slide

  3. View Slide

  4. 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 fixable

    View Slide

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

    View Slide

  6. What Do I Know About This?
    ❖ 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 first technical interview
    ❖ I see a lot of what doesn’t work

    View Slide

  7. 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

    View Slide

  8. What This Talk Is Not?
    ❖ Guaranteed
    ❖ A moral judgement
    ❖ All-knowing
    ❖ Respectful of your time

    View Slide

  9. How Can You Prepare?

    View Slide

  10. 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

    View Slide

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

    View Slide

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

    View Slide

  13. http://bigocheatsheet.com/

    View Slide

  14. Big O Notation
    ❖ A metric used to describe an upper bound on algorithm
    efficiency
    ❖ Can be used for time or space
    ❖ Drops constants and non-dominant terms
    ❖ Adds independent work; multiplies dependent work
    ❖ Not just an academic curiosity! It can help you solve
    problems faster and easier!

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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)

    View Slide

  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(2n)

    View Slide

  20. 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)

    View Slide

  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]
    )

    View Slide

  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)

    View Slide

  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)

    View Slide

  24. 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)

    View Slide

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

    View Slide

  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

    View Slide

  27. 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

    View Slide

  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

    View Slide

  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

    View Slide

  30. 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

    View Slide

  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

    View Slide

  32. 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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  37. 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

    View Slide

  38. Almost Helpful
    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

    View Slide

  39. Almost Helpful
    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

    View Slide

  40. Almost Helpful
    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

    View Slide

  41. More Helpful
    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

    View Slide

  42. More Helpful
    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

    View Slide

  43. More Helpful
    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

    View Slide

  44. The Most Helpful
    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

    View Slide

  45. The Most Helpful
    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

    View Slide

  46. 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.

    View Slide

  47. View Slide

  48. View Slide

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

    View Slide

  50. More Study and Practice

    View Slide

  51. 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 fine

    View Slide

  52. What To Do While Coding?

    View Slide

  53. 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

    View Slide

  54. Tip #1
    Read Carefully
    And/or ask as many clarifying questions
    as needed

    View Slide

  55. Tip #2
    Follow Directions
    Many candidates do not do this

    View Slide

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

    View Slide

  57. View Slide

  58. Tip #4
    Think Out Loud
    Magic words:
    • “My first thought is…”
    • “I’m considering the tradeoffs…”
    • “I might circle back to this…”
    • “I don’t know.”

    View Slide

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

    View Slide

  60. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  67. Maximizing for Success
    ❖ You probably won’t nail all of my tips every time
    ❖ That’s fine
    ❖ 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

    View Slide

  68. Thanks and
    I hope you ace your interviews!

    View Slide