# 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

## Transcript

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

7. ### rubyconf 2019 COMPLEXITY 0 1 2 3 4 5 6

7 8 9 10 11 12 13 14 15 O(1) a 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

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

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

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

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

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)

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)

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/