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

Algorithms: CLRS in Ruby

listrophy
November 19, 2019

Algorithms: CLRS in Ruby

One of the most celebrated books in Computer Science academia is "Introduction to Algorithms," also known as "CLRS" after its 4 authors. It's the go-to (pun!) textbook for many intermediate college courses, and this talk will introduce some of its many wonderful algorithms in Ruby form, including: various sorting techniques, dynamic programming, and some fun graph techniques. If you want a theory-heavy lecture, this talk is NOT for you!

listrophy

November 19, 2019
Tweet

More Decks by listrophy

Other Decks in Programming

Transcript

  1. ALGORITHMS
    CLRS IN RUBY

    View full-size slide

  2. rubyconf 2019
    BRAD GRZESIAK
    ‣ 2002 ICPC WORLD FINALS:
    11TH PLACE
    ‣ FORMER AEROSPACE
    ENGINEER
    ‣ FOUNDER/CEO OF
    BENDYWORKS
    ‣ PORTED matrix TO ruby
    @LISTROPHY

    View full-size slide

  3. rubyconf 2019
    SYLLABUS
    ‣ COMPLEXITY
    ‣ INSERTION SORT
    ‣ QUICK SORT
    ‣ BUCKET SORT
    ‣ LONGEST COMMON SUBSEQUENCE
    ‣ MINIMUM SPANNING TREE
    ‣ SHORTEST PATH
    ‣ MAX FLOW

    View full-size slide

  4. rubyconf 2019
    INTRODUCTION TO
    ALGORITHMS
    ‣ CORMEN
    ‣ LEISERSON
    ‣ RIVEST
    ‣ STEIN

    View full-size slide

  5. rubyconf 2019
    COMPLEXITY

    View full-size slide

  6. rubyconf 2019
    COMPLEXITY
    hNoHereComes
    ( _ )
    O
    thing(s)!

    View full-size slide

  7. rubyconf 2019
    COMPLEXITY
    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    O(1)
    a[4]
    O(n)
    a.map
    O(log n)
    a.bsearch
    V
    D T X
    B F N R U W Y
    P
    H
    L
    J
    A C E G I K M O Q S U V W X Y Z

    View full-size slide

  8. rubyconf 2019
    COMPLEXITY
    O(1)
    O(log n)
    O(n)
    O(n log n)
    O(n²)
    great!
    ok
    hmmm
    uffda
    oh no

    View full-size slide

  9. rubyconf 2019
    SORTING

    View full-size slide

  10. rubyconf 2019
    INSERTION SORT

    View full-size slide

  11. rubyconf 2019
    SORTING
    INSERTION SORT
    (1...length).each do |right|
    subject = self[right]
    left = right - 1
    while left > -1 && self[left] > self[right]
    self[left + 1] = self[left]
    left += 1
    end
    self[left + 1] = subject
    end

    View full-size slide

  12. rubyconf 2019
    INSERTION SORT DEMO

    View full-size slide

  13. rubyconf 2019
    INSERTION SORT
    COMPLEXITY
    O(n²)

    View full-size slide

  14. rubyconf 2019
    QUICK SORT

    View full-size slide

  15. rubyconf 2019
    SORTING
    QUICK SORT
    def quicksort
    qsort_help(0, self.length - 1)
    end
    def qsort_help(p, r)
    return unless p < r
    q = partition(p, r)
    qsort_help(p, q - 1)
    qsort_help( q + 1, r)
    end
    def partition(p, r)
    x = self[r]
    i = p - 1
    (p...r).each do |j|
    if self[j] <= x
    i += 1
    swap(i, j)
    end
    end
    swap(i + 1, r)
    i + 1
    end

    View full-size slide

  16. rubyconf 2019
    QUICK SORT DEMO

    View full-size slide

  17. rubyconf 2019
    QUICK SORT
    COMPLEXITY
    O(n log n)

    View full-size slide

  18. rubyconf 2019
    SORTING
    TWITTER POLL

    View full-size slide

  19. rubyconf 2019
    BUCKET SORT

    View full-size slide

  20. rubyconf 2019
    SORTING
    BUCKET SORT
    def bucket_sort
    b = Array.new(length)
    each_with_index do |val, idx|
    b[val] = val
    end
    replace(b)
    end
    def bucket_sort
    b = Array.new(length)
    mx = max
    (0...length).each do |i|
    idx = length * (self[i] / mx)
    b[idx] ||= []
    b[idx] << self[i]
    end
    b.each(&:insertion_sort!)
    replace(b.flatten.compact)
    end

    View full-size slide

  21. rubyconf 2019
    BUCKET SORT DEMO

    View full-size slide

  22. rubyconf 2019
    BUCKET SORT
    COMPLEXITY
    O(n) ?

    View full-size slide

  23. rubyconf 2019
    DYNAMIC
    PROGRAMMING

    View full-size slide

  24. rubyconf 2019
    LONGEST COMMON
    SUBSEQUENCE

    View full-size slide

  25. rubyconf 2019
    DYNAMIC PROGRAMMING
    LONGEST COMMON SUBSEQUENCE
    ATCGG G
    C TTTGC
    ACCAC G
    C TAACA

    View full-size slide

  26. rubyconf 2019
    DYNAMIC PROGRAMMING
    LONGEST COMMON SUBSEQUENCE
    def command
    return @command if @command
    @command = Message::Command...
    @command ||= Message::Command...
    ...
    end
    def subject
    @subject ||= sentence
    .nouns
    .reject...
    end
    def command
    @command = Message::Command...
    @command ||= Message::Command...
    ...
    end
    def subject
    @subject ||= sentence.nouns.reject...
    end
    github.com/CoralineAda/alice

    View full-size slide

  27. rubyconf 2019
    DYNAMIC PROGRAMMING
    LONGEST COMMON SUBSEQUENCE ( ABCDEF 㱻 BDF )
    A B C D E F
    B
    D
    F
    0 1 1 1 1 1
    0 1 1 2 2 2
    0 1 1 2 2 3
    if match?(top, left)
    1 + ⬉
    else
    [‐, ‏].max
    end
    O(n∙m)

    View full-size slide

  28. rubyconf 2019
    LONGEST COMMON SUBSEQUENCE
    def lcs
    setup
    compute_matrix
    @matrix.last.last
    end
    def setup
    @matrix = Array.new(@a.length + 1) do
    Array.new(@b.length + 1, 0)
    end
    end
    def compute_matrix
    (1..(@a.length)).each do |i|
    (1..(@b.length)).each do |j|
    compute_cell(i, j)
    end
    end
    end
    def compute_cell(i, j)
    @matrix[i][j] =
    if @a[i - 1] == @b[j - 1]
    matches(i, j)
    else
    does_not_match(i, j)
    end
    end
    def matches(i, j)
    @matrix[i - 1][j - 1] + 1
    end
    def does_not_match(i, j)
    [ @matrix[i - 1][j],
    @matrix[i][j - 1]
    ].max
    end

    View full-size slide

  29. rubyconf 2019
    GRAPHS

    View full-size slide

  30. rubyconf 2019
    MINIMUM SPANNING
    TREE

    View full-size slide

  31. rubyconf 2019
    GRAPHS
    MINIMUM SPANNING TREE
    A
    H G F
    E
    I
    B C D
    8
    4
    11
    7
    1
    2
    4
    8 7
    14
    10
    9
    2

    View full-size slide

  32. rubyconf 2019
    GRAPHS
    MINIMUM SPANNING TREE (PRIM'S ALGORITHM)
    A
    H G F
    E
    I
    B C D
    8
    4
    11
    7
    1
    2
    4
    8 7
    14
    10
    9
    2
    vertices.map { |u| u.key = ∞ }
    queue = PQueue.new(vertices)
    until queue.empty?
    u = queue.extract
    u.neighbors.each do |v, w|
    if queue.has?(v) && w < v.key
    v.parent = u
    v.key = w
    end
    end
    end
    A B H G F C I D E
    O(E+V log V)

    View full-size slide

  33. rubyconf 2019
    SHORTEST PATH

    View full-size slide

  34. rubyconf 2019
    GRAPHS
    SHORTEST PATH (DIJKSTRA'S ALGORITHM)
    A
    H G F
    E
    I
    B C D
    8
    4
    11
    7
    1
    2
    4
    8 7
    14
    10
    9
    2
    queue = PQueue.new(nodes)
    until queue.empty?
    u = queue.extract_first
    adj[u.name].each_pair do |v, w|
    u.relax(v, w)
    end
    end
    class Node
    # ...
    def relax(other, w)
    if other.d > (d + w)
    other.d = d + w
    other.parent = self
    end
    end
    end
    A B H G F C I D E
    0
    8
    4
    12
    15
    9 11
    25
    21
    14
    19
    O(E+V log V)

    View full-size slide

  35. rubyconf 2019
    MAX FLOW

    View full-size slide

  36. rubyconf 2019
    GRAPHS
    MAX FLOW (FORD-FULKERSON ALGORITHM)
    loop do
    # find any path from s to t
    p = find_path(s, t,
    edges.reject {|_names, e| e.capacity == 0 })
    break if p.empty?
    # find the segement with least remaining capacity
    segs = segments(p)
    residual_capacity_p = segs.map do |uv|
    edges[uv].residual_capacity
    end.min
    segs.each do |(u, v)|
    # add that capacity to each edge
    edges[[u, v]].flow += residual_capacity_p
    # if we need to reverse the flow in the future:
    edges[[v, u]].flow = -edges[[u, v]].flow
    end
    end

    View full-size slide

  37. rubyconf 2019
    GRAPHS
    MAX FLOW (FORD-FULKERSON ALGORITHM)
    S
    D
    C
    B
    A
    T
    16
    13
    4
    10
    12
    9
    14
    7
    20
    4

    View full-size slide

  38. rubyconf 2019
    GRAPHS
    MAX FLOW (FORD-FULKERSON ALGORITHM)
    S
    D
    C
    B
    A
    T
    16
    13
    4
    10
    12
    9
    14
    7
    20
    4
    4
    4
    4

    View full-size slide

  39. rubyconf 2019
    GRAPHS
    MAX FLOW (FORD-FULKERSON ALGORITHM)
    S
    D
    C
    B
    A
    T
    16
    13
    4
    10
    12
    9
    14
    7
    20
    4
    12
    4
    4
    12
    4
    12

    View full-size slide

  40. rubyconf 2019
    GRAPHS
    MAX FLOW (FORD-FULKERSON ALGORITHM)
    S
    D
    C
    B
    A
    T
    16
    13
    4
    10
    12
    9
    14
    7
    20
    4
    12
    4
    4
    12
    7
    4
    12

    View full-size slide

  41. rubyconf 2019
    GRAPHS
    MAX FLOW (FORD-FULKERSON ALGORITHM)
    S
    D
    C
    B
    A
    T
    16
    13
    4
    10
    12
    9
    14
    7
    20
    4
    12
    11
    11
    12
    7
    4
    19

    View full-size slide

  42. rubyconf 2019
    GRAPHS
    MAX FLOW (FORD-FULKERSON ALGORITHM)
    S
    D
    C
    B
    A
    T
    16
    13
    4
    10
    12
    9
    14
    7
    20
    4
    12
    0
    0
    11
    11
    0
    12
    7
    4
    19
    O(E |f *|)

    View full-size slide

  43. rubyconf 2019
    THANK YOU
    @listrophy
    @bendyworks
    COMPLEXITY
    INSERTION SORT
    QUICK SORT
    BUCKET SORT
    LONGEST COMMON SUBSEQUENCE
    MINIMUM SPANNING TREE
    SHORTEST PATH
    MAX FLOW
    gitlab.com/listrophy/clrs-algorithms/

    View full-size slide