Algorithms: CLRS in Ruby

B4753ed732e72ff2568262c9387bbc4c?s=47 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!

B4753ed732e72ff2568262c9387bbc4c?s=128

listrophy

November 19, 2019
Tweet

Transcript

  1. ALGORITHMS CLRS IN RUBY

  2. rubyconf 2019 BRAD GRZESIAK ‣ 2002 ICPC WORLD FINALS: 11TH

    PLACE ‣ FORMER AEROSPACE ENGINEER ‣ FOUNDER/CEO OF BENDYWORKS ‣ PORTED matrix TO ruby @LISTROPHY
  3. rubyconf 2019 SYLLABUS ‣ COMPLEXITY ‣ INSERTION SORT ‣ QUICK

    SORT ‣ BUCKET SORT ‣ LONGEST COMMON SUBSEQUENCE ‣ MINIMUM SPANNING TREE ‣ SHORTEST PATH ‣ MAX FLOW
  4. rubyconf 2019 INTRODUCTION TO ALGORITHMS ‣ CORMEN ‣ LEISERSON ‣

    RIVEST ‣ STEIN
  5. rubyconf 2019 COMPLEXITY

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

  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
  8. rubyconf 2019 COMPLEXITY O(1) O(log n) O(n) O(n log n)

    O(n²) great! ok hmmm uffda oh no
  9. rubyconf 2019 SORTING

  10. rubyconf 2019 INSERTION SORT

  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
  12. rubyconf 2019 INSERTION SORT DEMO

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

  14. rubyconf 2019 QUICK SORT

  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
  16. rubyconf 2019 QUICK SORT DEMO

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

  18. rubyconf 2019 SORTING TWITTER POLL

  19. rubyconf 2019 BUCKET SORT

  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
  21. rubyconf 2019 BUCKET SORT DEMO

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

  23. rubyconf 2019 DYNAMIC PROGRAMMING

  24. rubyconf 2019 LONGEST COMMON SUBSEQUENCE

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

    TTTGC ACCAC G C TAACA
  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
  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)
  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
  29. rubyconf 2019 GRAPHS

  30. rubyconf 2019 MINIMUM SPANNING TREE

  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
  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)
  33. rubyconf 2019 SHORTEST PATH

  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)
  35. rubyconf 2019 MAX FLOW

  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
  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
  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
  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
  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
  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
  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 *|)
  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/