# frozen_string_literal: true class Array # Returns a new array created by sorting +self+, using bubble sort algorithm. # # Comparisons for the sort will be done using the <=> operator or using an optional code block. # # The block must implement a comparison between +a+ and +b+ and return an integer less than 0 when +b+ follows +a+, # +0+ when +a+ and +b+ are equivalent, or an integer greater than 0 when +a+ follows +b+. # # The result is guaranteed to be stable. When the comparison of two elements returns +0+, the order of the elements # will be preserved. # # @return [Array] the sorted array def bubble_sort(&block) dup.bubble_sort!(&block) end # Sorts +self+ in place, using bubble sort algorithm. # # Comparisons for the sort will be done using the <=> operator or using an optional code block. # # The block must implement a comparison between +a+ and +b+ and return an integer less than 0 when +b+ follows +a+, # +0+ when +a+ and +b+ are equivalent, or an integer greater than 0 when +a+ follows +b+. # # The result is guaranteed to be stable. When the comparison of two elements returns +0+, the order of the elements # will be preserved. # # @return [Array] +self+ def bubble_sort!(&block) return self if length <= 1 n = length loop do new_n = bubble_sort_check(n, &block) n = new_n break if n.zero? end self end # Returns a new array created by sorting +self+ with bubble sort algorithm, using a set of keys generated by mapping # the values in self through the given block. # # The result is guaranteed to be stable. When the comparison of two elements returns +0+, the order of the elements # will be preserved. # # If no block is given, an Enumerator is returned instead. # # @return [Array] if a block is given, the sorted array # @return [Enumerator] if no block is given, an Enumerator def bubble_sort_by(&block) if block_given? dup.bubble_sort_by!(&block) else to_enum :bubble_sort_by end end # Sorts +self+ in place with bubble sort algorithm, using a set of keys generated by mapping the values in self # through the given block. # # The result is guaranteed to be stable. When the comparison of two elements returns +0+, the order of the elements # will be preserved. # # If no block is given, an Enumerator is returned instead. # # @return [Array] if a block is given, the sorted array # @return [Enumerator] if no block is given, an Enumerator def bubble_sort_by!(&_block) if block_given? bubble_sort! do |a, b| yield(a) <=> yield(b) end else to_enum :bubble_sort_by! end end private # @private def bubble_sort_check(length_checking, &block) new_n = 0 (1...length_checking).each do |i| next unless sort_compare(self[i - 1], self[i], &block).positive? swap i - 1, i new_n = i end new_n end end