#
# Generic helper.  Really, String.delete should handle this...
#
class String
	def del(pattern)
		sub(pattern, "")
	end
	def del!(pattern)
		sub(pattern, "")
	end
	def gdel(pattern)
		gsub(pattern, "")
	end
	def gdel!(pattern)
		gsub!(pattern, "")
	end
	#
	# Return a string containing only the unique characters from this
	# string.  Useful for displaying error messages about wrong
	# characters.
	#
	def uniqchars
		livebytes = {}
		self.each_byte { |c|
			livebytes[c] = true
		}
		newstr = ""
		livebytes.keys.sort { |a,b| a <=> b }.each { |c|
			newstr += sprintf("%c", c)
		}
		newstr
	end
end



#
# Generic helper.
#
class Array
	#
	# Like delete_if, but only removes the first entries that are matched
	# (sort of like a starting anchor in a regexp)
	#
	def delete_head
		badlines = true
		i = 0
		len = length
		while i < len
			break if (!yield(self[i]))
			i += 1
		end
		return slice!(0, i)
	end
	def delete_tail
		badlines = true
		i = length - 1
		while i >= 0
			break if (!yield(self[i]))
			i -= 1
		end
		return slice!(i, length - i)
	end
end


#
# Iterate through a series of files, line by line, providing enough
# context for sane error messages (hopefully).
#
def files_as_lines(files)
	files.each { |filename|
		lineno = 1
		open(filename, "r").each_line { |line|
			yield(line, filename, lineno)
			lineno += 1
		}
	}
end

#
# Create a singleton for each DIFFERENT instance of the class that
# instance this.
#
# The class must define 'hash' and '==' as appropriate.
#
module MultiSingleton
	@@known_components = {}
	def MultiSingleton.new(*data)
		myself = super(*data)
		@@known_components[myself] = myself unless @@known_components[myself]
		return @@known_components[myself]
	end
end

#
# Add the keyword 'maximizer' for definition of accessors.
# This will generate an accessor for the specified symbol,
# as well as a setter function '<symbol>_maximizer(value, score)'
# which will set <symbol> iff score is higher than the previous highest score.
#
#--
# FIXME Wrap an each around this when it is tested that it works.
#++
# NOTE: The code do not presently accept more than one symbol per line.
#
module Maximizer
	def maximizer(symbol)
		symbol = symbol.id2name
		module_eval <<-eom
			def #{symbol}_maximize(value, score)
				if !@#{symbol}_score || @#{symbol}_score < score
					@#{symbol} = value
					@#{symbol}_score = score
				end
			end
			def #{symbol}_score
				@#{symbol}_score
			end
			def #{symbol}
				@#{symbol}
			end
		eom
	end
end


#
# Convenience function for getting access to a private metaclass for this
# object
#
class Object
	def singleton_class
		return (class <<self; self; end)
	end
	private :singleton_class
end
class Array
=begin
--- Array.shuffle!
    re-organizes the elements in the array in random order.
    This function work the opposite of Array.sort!.

    The functionality is useful for simulations and games.

    XXX Note that this does NOT generate an even shuffle.
    If we are to generate an even shuffle, we need to make sure we generate
    all permutations with the same likelihood, which this doesn't.
=end
	def shuffle!
		len = self.length
		self.each_index { |i|
			swapwith = rand(len)
			tmp = self[i]
			self[i] = self[swapwith]
			self[swapwith] = tmp
		}
	end
=begin
--- Array.shuffle
    Return a copy of the array, with the element in random order.

    See also Array.shuffle!
=end
	def shuffle
		tmp = self.clone
		tmp.shuffle!
		return tmp
	end
=begin
--- Array.inject(start)
    Simple implementation of "inject", as used in Smalltalk.
=end
	def inject(start)
		each { |i| start = yield(start, i) }
		return start
	end
end
