array-sort 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +73 -0
  3. data/README.md +228 -29
  4. data/lib/array/sort.rb +5 -8
  5. data/lib/array_sort/algorithms/binary_insertion_sort.rb +41 -0
  6. data/lib/array_sort/algorithms/bubble_sort.rb +31 -0
  7. data/lib/array_sort/algorithms/bucket_sort.rb +67 -0
  8. data/lib/array_sort/algorithms/cocktail_shaker_sort.rb +42 -0
  9. data/lib/array_sort/algorithms/comb_sort.rb +33 -0
  10. data/lib/array_sort/algorithms/counting_sort.rb +50 -0
  11. data/lib/array_sort/algorithms/cycle_sort.rb +46 -0
  12. data/lib/array_sort/algorithms/gnome_sort.rb +28 -0
  13. data/lib/array_sort/algorithms/heap_sort.rb +43 -0
  14. data/lib/array_sort/algorithms/insertion_sort.rb +35 -0
  15. data/lib/array_sort/algorithms/intro_sort.rb +80 -0
  16. data/lib/array_sort/algorithms/merge_sort.rb +57 -0
  17. data/lib/array_sort/algorithms/odd_even_sort.rb +34 -0
  18. data/lib/array_sort/algorithms/pancake_sort.rb +39 -0
  19. data/lib/array_sort/algorithms/quick_sort.rb +68 -0
  20. data/lib/array_sort/algorithms/radix_sort.rb +58 -0
  21. data/lib/array_sort/algorithms/selection_sort.rb +25 -0
  22. data/lib/array_sort/algorithms/shell_sort.rb +41 -0
  23. data/lib/array_sort/algorithms/smooth_sort.rb +106 -0
  24. data/lib/array_sort/algorithms/tim_sort.rb +335 -0
  25. data/lib/array_sort/algorithms/tournament_sort.rb +53 -0
  26. data/lib/array_sort/algorithms/tree_sort.rb +96 -0
  27. data/lib/array_sort/array_methods.rb +67 -0
  28. data/lib/array_sort/core.rb +124 -0
  29. data/lib/array_sort/functions.rb +23 -0
  30. data/lib/array_sort/refinements.rb +16 -0
  31. data/lib/array_sort/registry.rb +68 -0
  32. data/lib/array_sort/trace.rb +111 -0
  33. data/lib/{array/sort → array_sort}/version.rb +1 -1
  34. data/lib/array_sort.rb +43 -0
  35. data/sig/array_sort.rbs +368 -0
  36. metadata +47 -71
  37. data/.gitignore +0 -9
  38. data/.rubocop.yml +0 -11
  39. data/.travis.yml +0 -6
  40. data/Gemfile +0 -6
  41. data/Gemfile.lock +0 -22
  42. data/Rakefile +0 -10
  43. data/array-sort.gemspec +0 -37
  44. data/bin/console +0 -14
  45. data/bin/setup +0 -8
  46. data/lib/array/sort/bubble_sort.rb +0 -91
  47. data/lib/array/sort/heap_sort.rb +0 -111
  48. data/lib/array/sort/helper.rb +0 -34
  49. data/lib/array/sort/insertion_sort.rb +0 -78
  50. data/lib/array/sort/merge_sort.rb +0 -94
  51. data/lib/array/sort/quick_sort.rb +0 -73
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ArraySort
4
+ # Adds the {ArrayMethods} to Array only in files that opt in, instead of everywhere.
5
+ #
6
+ # @example
7
+ # require 'array_sort'
8
+ # using ArraySort::Refinements
9
+ #
10
+ # [3, 1, 2].merge_sort # => [1, 2, 3]
11
+ module Refinements
12
+ refine Array do
13
+ import_methods ArraySort::ArrayMethods
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ArraySort
4
+ # Describes one sorting algorithm: what it is called, whether it is stable, and its complexity.
5
+ #
6
+ # Complexities are written without the O(...), e.g. +"n log n"+. In the distribution sorts, +k+ is the range of the
7
+ # keys (largest minus smallest) and +w+ is the number of bytes in the largest key.
8
+ #
9
+ # @!attribute [r] name
10
+ # @return [Symbol] the method prefix, e.g. +:merge+ for +merge_sort+
11
+ # @!attribute [r] title
12
+ # @return [String] the human-readable name, e.g. +"Merge sort"+
13
+ # @!attribute [r] kind
14
+ # @return [Symbol] +:comparison+ for sorts that compare elements (and accept a comparison block), or
15
+ # +:distribution+ for sorts that place elements by numeric key (Integer, or any real number for bucket sort)
16
+ # @!attribute [r] best
17
+ # @return [String] best-case time complexity
18
+ # @!attribute [r] average
19
+ # @return [String] average-case time complexity
20
+ # @!attribute [r] worst
21
+ # @return [String] worst-case time complexity
22
+ # @!attribute [r] space
23
+ # @return [String] extra space used, beyond the copy made by the non-bang methods
24
+ Algorithm = Data.define(:name, :title, :implementation, :stable, :kind, :best, :average, :worst, :space) do
25
+ # @return [Boolean] whether elements that compare equal keep their original relative order
26
+ def stable? = stable
27
+
28
+ # @return [Boolean] whether the algorithm sorts by comparing elements
29
+ def comparison? = kind == :comparison
30
+
31
+ # @return [Boolean] whether the algorithm sorts by distributing numeric keys, without comparing elements
32
+ def distribution? = kind == :distribution
33
+ end
34
+
35
+ @algorithms = {}
36
+
37
+ class << self
38
+ # Returns the names of every available algorithm, in alphabetical order. Each name +x+ provides +x_sort+,
39
+ # +x_sort!+, +x_sort_by+ and +x_sort_by!+.
40
+ #
41
+ # @example
42
+ # ArraySort.algorithms # => [:binary_insertion, :bubble, :bucket, ...]
43
+ # @return [Array<Symbol>]
44
+ def algorithms
45
+ @algorithms.keys.sort
46
+ end
47
+
48
+ # Returns the description of an algorithm.
49
+ #
50
+ # @example
51
+ # ArraySort.algorithm(:merge).stable? # => true
52
+ # @param name [Symbol, String]
53
+ # @return [Algorithm]
54
+ # @raise [ArgumentError] if there is no algorithm with that name
55
+ def algorithm(name)
56
+ @algorithms.fetch(name.to_sym) { raise ArgumentError, "unknown sorting algorithm: #{name.inspect}" }
57
+ end
58
+
59
+ private
60
+
61
+ # Called by each algorithm file to add itself.
62
+ def register(name, implementation, title:, stable:, best:, average:, worst:, space:, kind: :comparison)
63
+ raise "algorithm #{name.inspect} is already registered" if @algorithms.key?(name)
64
+
65
+ @algorithms[name] = Algorithm.new(name:, title:, implementation:, stable:, kind:, best:, average:, worst:, space:)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ArraySort
4
+ # A record of everything a sorting algorithm did: every comparison it made and every write to the array, in order.
5
+ # Build one with {ArraySort.trace}.
6
+ #
7
+ # Replaying the writes onto a copy of {#input} reproduces {#result} step by step, which makes traces handy for
8
+ # visualizing or teaching how the algorithms differ.
9
+ class Trace
10
+ # One comparison between two elements. +result+ is -1, 0 or 1.
11
+ Comparison = Data.define(:left, :right, :result)
12
+
13
+ # One assignment +array[index] = value+. A swap shows up as two writes.
14
+ Write = Data.define(:index, :value)
15
+
16
+ # @return [Algorithm] the algorithm that ran
17
+ attr_reader :algorithm
18
+ # @return [Array] a copy of the array before sorting
19
+ attr_reader :input
20
+ # @return [Array] the sorted array
21
+ attr_reader :result
22
+ # @return [Array<Comparison, Write>] everything the algorithm did, in order
23
+ attr_reader :events
24
+
25
+ # @api private
26
+ def initialize(algorithm, input, result, events)
27
+ @algorithm = algorithm
28
+ @input = input
29
+ @result = result
30
+ @events = events
31
+ end
32
+
33
+ # @return [Integer] how many comparisons were made
34
+ def comparisons
35
+ events.count { |event| event.is_a?(Comparison) }
36
+ end
37
+
38
+ # @return [Integer] how many elements were written
39
+ def writes
40
+ events.count { |event| event.is_a?(Write) }
41
+ end
42
+
43
+ # The array handed to the algorithm while tracing. It reports every element assignment.
44
+ #
45
+ # @api private
46
+ class Buffer < Array
47
+ def initialize(array, on_write)
48
+ super(array, &nil)
49
+ @on_write = on_write
50
+ end
51
+
52
+ # Only single-element assignment is supported; algorithms must not use the range or length forms.
53
+ def []=(index, value)
54
+ @on_write.call(index, value)
55
+ super
56
+ end
57
+ end
58
+ private_constant :Buffer
59
+
60
+ # @api private
61
+ def self.run(name, array, &on_event)
62
+ algorithm = ArraySort.algorithm(name)
63
+ input = Array.new(array).freeze
64
+ events = []
65
+ record = lambda do |event|
66
+ events << event
67
+ on_event&.call(event)
68
+ end
69
+
70
+ buffer = Buffer.new(input, ->(index, value) { record.call(Write.new(index:, value:)) })
71
+ algorithm.implementation.call(buffer, algorithm.comparison? ? recording_comparator(record) : lambda { |element|
72
+ element
73
+ })
74
+ new(algorithm, input, Array.new(buffer), events.freeze)
75
+ end
76
+
77
+ # Compares with <=> like an untraced sort, and records each comparison.
78
+ def self.recording_comparator(record)
79
+ compare = Core.comparator(nil)
80
+ lambda do |a, b|
81
+ compare.call(a, b).tap { |result| record.call(Comparison.new(left: a, right: b, result: result <=> 0)) }
82
+ end
83
+ end
84
+ private_class_method :recording_comparator
85
+ end
86
+
87
+ class << self
88
+ # Sorts a copy of +array+ with the named algorithm, recording each comparison and write.
89
+ #
90
+ # Elements are compared with +<=>+ (distribution sorts never compare; they need Integer elements, or real numbers
91
+ # for bucket sort).
92
+ #
93
+ # @example
94
+ # trace = ArraySort.trace(:insertion, [3, 1, 2])
95
+ # trace.result # => [1, 2, 3]
96
+ # trace.comparisons # => 3
97
+ # trace.events.first
98
+ # # => #<data ArraySort::Trace::Comparison left=3, right=1, result=1>
99
+ #
100
+ # @example Streaming events as they happen
101
+ # ArraySort.trace(:heap, [3, 1, 2]) { |event| puts event.inspect }
102
+ #
103
+ # @param name [Symbol, String] one of {ArraySort.algorithms}
104
+ # @param array [Array] the array to sort; it is not modified
105
+ # @yieldparam event [Trace::Comparison, Trace::Write] each event, as it happens
106
+ # @return [Trace]
107
+ def trace(name, array, &)
108
+ Trace.run(name, array, &)
109
+ end
110
+ end
111
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArraySort
4
- VERSION = '0.1.1'
4
+ VERSION = '1.0.0'
5
5
  end
data/lib/array_sort.rb ADDED
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Popular sorting algorithms for Ruby arrays.
4
+ #
5
+ # Requiring +array_sort+ loads everything without changing Array. From there, sort with the module functions
6
+ # (+ArraySort.merge_sort(array)+), or opt in per file with +using ArraySort::Refinements+. Requiring +array/sort+
7
+ # instead also adds the sort methods to every Array.
8
+ module ArraySort
9
+ end
10
+
11
+ require_relative 'array_sort/version'
12
+ require_relative 'array_sort/registry'
13
+ require_relative 'array_sort/core'
14
+
15
+ # Algorithms some others build on come first.
16
+ require_relative 'array_sort/algorithms/bubble_sort'
17
+ require_relative 'array_sort/algorithms/heap_sort'
18
+ require_relative 'array_sort/algorithms/insertion_sort'
19
+ require_relative 'array_sort/algorithms/quick_sort'
20
+
21
+ require_relative 'array_sort/algorithms/binary_insertion_sort'
22
+ require_relative 'array_sort/algorithms/bucket_sort'
23
+ require_relative 'array_sort/algorithms/cocktail_shaker_sort'
24
+ require_relative 'array_sort/algorithms/comb_sort'
25
+ require_relative 'array_sort/algorithms/counting_sort'
26
+ require_relative 'array_sort/algorithms/cycle_sort'
27
+ require_relative 'array_sort/algorithms/gnome_sort'
28
+ require_relative 'array_sort/algorithms/intro_sort'
29
+ require_relative 'array_sort/algorithms/merge_sort'
30
+ require_relative 'array_sort/algorithms/odd_even_sort'
31
+ require_relative 'array_sort/algorithms/pancake_sort'
32
+ require_relative 'array_sort/algorithms/radix_sort'
33
+ require_relative 'array_sort/algorithms/selection_sort'
34
+ require_relative 'array_sort/algorithms/shell_sort'
35
+ require_relative 'array_sort/algorithms/smooth_sort'
36
+ require_relative 'array_sort/algorithms/tim_sort'
37
+ require_relative 'array_sort/algorithms/tournament_sort'
38
+ require_relative 'array_sort/algorithms/tree_sort'
39
+
40
+ require_relative 'array_sort/array_methods'
41
+ require_relative 'array_sort/functions'
42
+ require_relative 'array_sort/refinements'
43
+ require_relative 'array_sort/trace'
@@ -0,0 +1,368 @@
1
+ # Generated by script/generate_sig.rb from the algorithm registry; run `bundle exec rake sig` to update.
2
+
3
+ module ArraySort
4
+ VERSION: String
5
+
6
+ type real = Integer | Float | Rational
7
+
8
+ def self.algorithms: () -> Array[Symbol]
9
+ def self.algorithm: (Symbol | String name) -> Algorithm
10
+ def self.trace: (Symbol | String name, Array[untyped] array) ?{ (Trace::event event) -> void } -> Trace
11
+
12
+ def self.binary_insertion_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
13
+ def self.binary_insertion_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
14
+ def self.binary_insertion_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
15
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
16
+ def self.binary_insertion_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
17
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
18
+
19
+ def self.bubble_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
20
+ def self.bubble_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
21
+ def self.bubble_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
22
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
23
+ def self.bubble_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
24
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
25
+
26
+ def self.bucket_sort: [T] (Array[real] array) -> Array[real]
27
+ def self.bucket_sort!: [T] (Array[real] array) -> Array[real]
28
+ def self.bucket_sort_by: [T] (Array[T] array) { (T) -> real } -> Array[T]
29
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
30
+ def self.bucket_sort_by!: [T] (Array[T] array) { (T) -> real } -> Array[T]
31
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
32
+
33
+ def self.cocktail_shaker_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
34
+ def self.cocktail_shaker_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
35
+ def self.cocktail_shaker_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
36
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
37
+ def self.cocktail_shaker_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
38
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
39
+
40
+ def self.comb_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
41
+ def self.comb_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
42
+ def self.comb_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
43
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
44
+ def self.comb_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
45
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
46
+
47
+ def self.counting_sort: [T] (Array[Integer] array) -> Array[Integer]
48
+ def self.counting_sort!: [T] (Array[Integer] array) -> Array[Integer]
49
+ def self.counting_sort_by: [T] (Array[T] array) { (T) -> Integer } -> Array[T]
50
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
51
+ def self.counting_sort_by!: [T] (Array[T] array) { (T) -> Integer } -> Array[T]
52
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
53
+
54
+ def self.cycle_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
55
+ def self.cycle_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
56
+ def self.cycle_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
57
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
58
+ def self.cycle_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
59
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
60
+
61
+ def self.gnome_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
62
+ def self.gnome_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
63
+ def self.gnome_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
64
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
65
+ def self.gnome_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
66
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
67
+
68
+ def self.heap_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
69
+ def self.heap_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
70
+ def self.heap_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
71
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
72
+ def self.heap_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
73
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
74
+
75
+ def self.insertion_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
76
+ def self.insertion_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
77
+ def self.insertion_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
78
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
79
+ def self.insertion_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
80
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
81
+
82
+ def self.intro_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
83
+ def self.intro_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
84
+ def self.intro_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
85
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
86
+ def self.intro_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
87
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
88
+
89
+ def self.merge_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
90
+ def self.merge_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
91
+ def self.merge_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
92
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
93
+ def self.merge_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
94
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
95
+
96
+ def self.odd_even_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
97
+ def self.odd_even_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
98
+ def self.odd_even_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
99
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
100
+ def self.odd_even_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
101
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
102
+
103
+ def self.pancake_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
104
+ def self.pancake_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
105
+ def self.pancake_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
106
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
107
+ def self.pancake_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
108
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
109
+
110
+ def self.quick_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
111
+ def self.quick_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
112
+ def self.quick_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
113
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
114
+ def self.quick_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
115
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
116
+
117
+ def self.radix_sort: [T] (Array[Integer] array) -> Array[Integer]
118
+ def self.radix_sort!: [T] (Array[Integer] array) -> Array[Integer]
119
+ def self.radix_sort_by: [T] (Array[T] array) { (T) -> Integer } -> Array[T]
120
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
121
+ def self.radix_sort_by!: [T] (Array[T] array) { (T) -> Integer } -> Array[T]
122
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
123
+
124
+ def self.selection_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
125
+ def self.selection_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
126
+ def self.selection_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
127
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
128
+ def self.selection_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
129
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
130
+
131
+ def self.shell_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
132
+ def self.shell_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
133
+ def self.shell_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
134
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
135
+ def self.shell_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
136
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
137
+
138
+ def self.smooth_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
139
+ def self.smooth_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
140
+ def self.smooth_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
141
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
142
+ def self.smooth_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
143
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
144
+
145
+ def self.tim_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
146
+ def self.tim_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
147
+ def self.tim_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
148
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
149
+ def self.tim_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
150
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
151
+
152
+ def self.tournament_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
153
+ def self.tournament_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
154
+ def self.tournament_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
155
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
156
+ def self.tournament_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
157
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
158
+
159
+ def self.tree_sort: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
160
+ def self.tree_sort!: [T] (Array[T] array) ?{ (T a, T b) -> Numeric? } -> Array[T]
161
+ def self.tree_sort_by: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
162
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
163
+ def self.tree_sort_by!: [T] (Array[T] array) { (T) -> untyped } -> Array[T]
164
+ | [T] (Array[T] array) -> Enumerator[T, Array[T]]
165
+
166
+ class Algorithm < Data
167
+ attr_reader name: Symbol
168
+ attr_reader title: String
169
+ attr_reader implementation: untyped
170
+ attr_reader stable: bool
171
+ attr_reader kind: :comparison | :distribution
172
+ attr_reader best: String
173
+ attr_reader average: String
174
+ attr_reader worst: String
175
+ attr_reader space: String
176
+ def stable?: () -> bool
177
+ def comparison?: () -> bool
178
+ def distribution?: () -> bool
179
+ end
180
+
181
+ class Trace
182
+ type event = Comparison | Write
183
+
184
+ class Comparison < Data
185
+ attr_reader left: untyped
186
+ attr_reader right: untyped
187
+ attr_reader result: Integer
188
+ end
189
+
190
+ class Write < Data
191
+ attr_reader index: Integer
192
+ attr_reader value: untyped
193
+ end
194
+
195
+ attr_reader algorithm: Algorithm
196
+ attr_reader input: Array[untyped]
197
+ attr_reader result: Array[untyped]
198
+ attr_reader events: Array[event]
199
+ def comparisons: () -> Integer
200
+ def writes: () -> Integer
201
+ end
202
+
203
+ module ArrayMethods[Elem]
204
+ def swap: (Integer index1, Integer index2) -> self
205
+
206
+ def binary_insertion_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
207
+ def binary_insertion_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
208
+ def binary_insertion_sort_by: () { (Elem) -> untyped } -> Array[Elem]
209
+ | () -> Enumerator[Elem, Array[Elem]]
210
+ def binary_insertion_sort_by!: () { (Elem) -> untyped } -> self
211
+ | () -> Enumerator[Elem, self]
212
+
213
+ def bubble_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
214
+ def bubble_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
215
+ def bubble_sort_by: () { (Elem) -> untyped } -> Array[Elem]
216
+ | () -> Enumerator[Elem, Array[Elem]]
217
+ def bubble_sort_by!: () { (Elem) -> untyped } -> self
218
+ | () -> Enumerator[Elem, self]
219
+
220
+ def bucket_sort: () -> Array[Elem]
221
+ def bucket_sort!: () -> self
222
+ def bucket_sort_by: () { (Elem) -> real } -> Array[Elem]
223
+ | () -> Enumerator[Elem, Array[Elem]]
224
+ def bucket_sort_by!: () { (Elem) -> real } -> self
225
+ | () -> Enumerator[Elem, self]
226
+
227
+ def cocktail_shaker_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
228
+ def cocktail_shaker_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
229
+ def cocktail_shaker_sort_by: () { (Elem) -> untyped } -> Array[Elem]
230
+ | () -> Enumerator[Elem, Array[Elem]]
231
+ def cocktail_shaker_sort_by!: () { (Elem) -> untyped } -> self
232
+ | () -> Enumerator[Elem, self]
233
+
234
+ def comb_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
235
+ def comb_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
236
+ def comb_sort_by: () { (Elem) -> untyped } -> Array[Elem]
237
+ | () -> Enumerator[Elem, Array[Elem]]
238
+ def comb_sort_by!: () { (Elem) -> untyped } -> self
239
+ | () -> Enumerator[Elem, self]
240
+
241
+ def counting_sort: () -> Array[Elem]
242
+ def counting_sort!: () -> self
243
+ def counting_sort_by: () { (Elem) -> Integer } -> Array[Elem]
244
+ | () -> Enumerator[Elem, Array[Elem]]
245
+ def counting_sort_by!: () { (Elem) -> Integer } -> self
246
+ | () -> Enumerator[Elem, self]
247
+
248
+ def cycle_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
249
+ def cycle_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
250
+ def cycle_sort_by: () { (Elem) -> untyped } -> Array[Elem]
251
+ | () -> Enumerator[Elem, Array[Elem]]
252
+ def cycle_sort_by!: () { (Elem) -> untyped } -> self
253
+ | () -> Enumerator[Elem, self]
254
+
255
+ def gnome_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
256
+ def gnome_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
257
+ def gnome_sort_by: () { (Elem) -> untyped } -> Array[Elem]
258
+ | () -> Enumerator[Elem, Array[Elem]]
259
+ def gnome_sort_by!: () { (Elem) -> untyped } -> self
260
+ | () -> Enumerator[Elem, self]
261
+
262
+ def heap_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
263
+ def heap_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
264
+ def heap_sort_by: () { (Elem) -> untyped } -> Array[Elem]
265
+ | () -> Enumerator[Elem, Array[Elem]]
266
+ def heap_sort_by!: () { (Elem) -> untyped } -> self
267
+ | () -> Enumerator[Elem, self]
268
+
269
+ def insertion_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
270
+ def insertion_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
271
+ def insertion_sort_by: () { (Elem) -> untyped } -> Array[Elem]
272
+ | () -> Enumerator[Elem, Array[Elem]]
273
+ def insertion_sort_by!: () { (Elem) -> untyped } -> self
274
+ | () -> Enumerator[Elem, self]
275
+
276
+ def intro_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
277
+ def intro_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
278
+ def intro_sort_by: () { (Elem) -> untyped } -> Array[Elem]
279
+ | () -> Enumerator[Elem, Array[Elem]]
280
+ def intro_sort_by!: () { (Elem) -> untyped } -> self
281
+ | () -> Enumerator[Elem, self]
282
+
283
+ def merge_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
284
+ def merge_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
285
+ def merge_sort_by: () { (Elem) -> untyped } -> Array[Elem]
286
+ | () -> Enumerator[Elem, Array[Elem]]
287
+ def merge_sort_by!: () { (Elem) -> untyped } -> self
288
+ | () -> Enumerator[Elem, self]
289
+
290
+ def odd_even_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
291
+ def odd_even_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
292
+ def odd_even_sort_by: () { (Elem) -> untyped } -> Array[Elem]
293
+ | () -> Enumerator[Elem, Array[Elem]]
294
+ def odd_even_sort_by!: () { (Elem) -> untyped } -> self
295
+ | () -> Enumerator[Elem, self]
296
+
297
+ def pancake_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
298
+ def pancake_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
299
+ def pancake_sort_by: () { (Elem) -> untyped } -> Array[Elem]
300
+ | () -> Enumerator[Elem, Array[Elem]]
301
+ def pancake_sort_by!: () { (Elem) -> untyped } -> self
302
+ | () -> Enumerator[Elem, self]
303
+
304
+ def quick_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
305
+ def quick_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
306
+ def quick_sort_by: () { (Elem) -> untyped } -> Array[Elem]
307
+ | () -> Enumerator[Elem, Array[Elem]]
308
+ def quick_sort_by!: () { (Elem) -> untyped } -> self
309
+ | () -> Enumerator[Elem, self]
310
+
311
+ def radix_sort: () -> Array[Elem]
312
+ def radix_sort!: () -> self
313
+ def radix_sort_by: () { (Elem) -> Integer } -> Array[Elem]
314
+ | () -> Enumerator[Elem, Array[Elem]]
315
+ def radix_sort_by!: () { (Elem) -> Integer } -> self
316
+ | () -> Enumerator[Elem, self]
317
+
318
+ def selection_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
319
+ def selection_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
320
+ def selection_sort_by: () { (Elem) -> untyped } -> Array[Elem]
321
+ | () -> Enumerator[Elem, Array[Elem]]
322
+ def selection_sort_by!: () { (Elem) -> untyped } -> self
323
+ | () -> Enumerator[Elem, self]
324
+
325
+ def shell_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
326
+ def shell_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
327
+ def shell_sort_by: () { (Elem) -> untyped } -> Array[Elem]
328
+ | () -> Enumerator[Elem, Array[Elem]]
329
+ def shell_sort_by!: () { (Elem) -> untyped } -> self
330
+ | () -> Enumerator[Elem, self]
331
+
332
+ def smooth_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
333
+ def smooth_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
334
+ def smooth_sort_by: () { (Elem) -> untyped } -> Array[Elem]
335
+ | () -> Enumerator[Elem, Array[Elem]]
336
+ def smooth_sort_by!: () { (Elem) -> untyped } -> self
337
+ | () -> Enumerator[Elem, self]
338
+
339
+ def tim_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
340
+ def tim_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
341
+ def tim_sort_by: () { (Elem) -> untyped } -> Array[Elem]
342
+ | () -> Enumerator[Elem, Array[Elem]]
343
+ def tim_sort_by!: () { (Elem) -> untyped } -> self
344
+ | () -> Enumerator[Elem, self]
345
+
346
+ def tournament_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
347
+ def tournament_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
348
+ def tournament_sort_by: () { (Elem) -> untyped } -> Array[Elem]
349
+ | () -> Enumerator[Elem, Array[Elem]]
350
+ def tournament_sort_by!: () { (Elem) -> untyped } -> self
351
+ | () -> Enumerator[Elem, self]
352
+
353
+ def tree_sort: () ?{ (Elem a, Elem b) -> Numeric? } -> Array[Elem]
354
+ def tree_sort!: () ?{ (Elem a, Elem b) -> Numeric? } -> self
355
+ def tree_sort_by: () { (Elem) -> untyped } -> Array[Elem]
356
+ | () -> Enumerator[Elem, Array[Elem]]
357
+ def tree_sort_by!: () { (Elem) -> untyped } -> self
358
+ | () -> Enumerator[Elem, self]
359
+
360
+ end
361
+
362
+ module Refinements
363
+ end
364
+ end
365
+
366
+ class Array[unchecked out Elem]
367
+ include ArraySort::ArrayMethods[Elem]
368
+ end