module RubyLabs
=begin rdoc
== IterationLab
The IterationLab module has definitions of methods from Chapter 4
of Explorations in Computing.
The methods demonstrate how a simple strategy of repeatedly comparing
items in an array can be used to search the array and to sort it.
The module has two implementations of linear search (contains?
and +search+) and an implementation of insertion sort (+isort+).
Helper methods called by the searching and sorting methods are also
documented here.
=end
module IterationLab
# The RubyLabs implementation of Ruby's include? method.
# Does a linear search of array +a+ to find item +k+, returning
# +true+ or +false+ depending on whether the item was found.
#
# Example:
# >> a = TestArray.new(10)
# => [89, 41, 69, 14, 4, 7, 8, 26, 81, 12]
# >> contains?(a, 7)
# => true
# >> contains?(a, 42)
# => false
#
# :call-seq:
# contains?(a,k) => Boolean
#
#--
# :begin :contains?
def contains?(a, k)
a.each { |x| return true if x == k}
return false
end
# :end :contains?
# The RubyLabs implementation of Ruby's index method.
# Does a linear search of array +a+ to find item +k+, returning
# the index of the first occurrence of +k+ or +nil+ if +k+ is
# not found.
#
# Example:
# >> a = TestArray.new(10)
# => [89, 41, 69, 14, 4, 7, 8, 26, 81, 12]
# >> search(a, 42)
# => nil
# >> search(a, 7)
# => 5
#
# :call-seq:
# search(a,k) => Fixnum
#
#--
# :begin :search
def search(a, k)
i = 0
while i < a.length
return i if a[i] == k
i += 1
end
return nil
end
# :end :search
# Return a copy of +a+, sorted using the insertion sort algorithm.
# On each iteration remove an item from the
# array, find a location for it to the left of its original position,
# and insert it back into the array at the new location.
#
# Example:
# >> a = TestArray.new(10)
# => [97, 87, 16, 2, 81, 80, 7, 64, 5, 71]
# >> isort(a)
# => [2, 5, 7, 16, 64, 71, 80, 81, 87, 97]
#
# :call-seq:
# isort(a) => Array
#
#--
# :begin :isort :move_left :less
def isort(array)
a = array.clone # don't modify the input array....
i = 1
while i < a.length
move_left(a, i) # find a place for a[i] somewhere to the left
i += 1
end
return a
end
# :end :isort
# Helper method called by +isort+ to remove the item at locaton +i+
# and reinsert it at a location between 0 and +i+ (i.e. move the item
# to the left in the array).
#--
# :begin :move_left
def move_left(a, i)
x = a.slice!(i) # remove the item at location i
j = i-1 # start scanning from the left of i
while j >= 0 && less(x, a[j])
j = j-1 # move left
end
a.insert(j+1, x) # insert x back into a at location j
end
# :end :move_left
# +less+ is called by +isort+ to compare two items.
# It is implemented as a helper method in order to allow users to
# attach a probe to count the number of comparisons.
#--
# :begin :less
def less(x, y)
return x < y
end
# :end :less
# A helper method that can be called from a probe to display the contents
# of an array during a search or sort.
#
# A call to brackets(a,i) will return a string that includes
# all the items in +a+, with a left bracket before a[i]
# and a right bracket after the last item.
#
# See also RecursionLab#brackets.
#
# Example:
# >> a = TestArray.new(10)
# => [55, 29, 72, 33, 14, 57, 85, 42, 26, 97]
# >> puts brackets(a, 3)
# 29 55 72 [33 14 57 85 42 26 97]
# => nil
#
# :call-seq:
# brackets(a,i) => String
#
def brackets(a, i)
if i <= 0
return ("[" + a.join(" ") + "]")
elsif i >= a.length
return " " + a.join(" ") + " [ ]"
else
pre = a.slice(0..(i-1))
post = a.slice(i..-1)
return " " + pre.join(" ") + " [" + post.join(" ") + "]"
end
end
end # IterationLab
end # RubyLabs