ruby-nuggets 0.6.9 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.rspec +1 -0
  2. data/README +1 -1
  3. data/Rakefile +4 -4
  4. data/lib/nuggets/array/correlation.rb +5 -0
  5. data/lib/nuggets/array/correlation_mixin.rb +62 -0
  6. data/lib/nuggets/array/histogram.rb +5 -0
  7. data/lib/nuggets/array/histogram_mixin.rb +155 -0
  8. data/lib/nuggets/array/mean.rb +5 -0
  9. data/lib/nuggets/array/mean_mixin.rb +139 -0
  10. data/lib/nuggets/array/median.rb +5 -0
  11. data/lib/nuggets/array/median_mixin.rb +74 -0
  12. data/lib/nuggets/array/mode.rb +5 -0
  13. data/lib/nuggets/array/mode_mixin.rb +70 -0
  14. data/lib/nuggets/array/monotone.rb +5 -5
  15. data/lib/nuggets/array/only.rb +3 -2
  16. data/lib/nuggets/array/regression.rb +5 -0
  17. data/lib/nuggets/array/regression_mixin.rb +63 -0
  18. data/lib/nuggets/array/runiq_mixin.rb +1 -1
  19. data/lib/nuggets/array/standard_deviation_mixin.rb +5 -8
  20. data/lib/nuggets/array/variance_mixin.rb +30 -11
  21. data/lib/nuggets/enumerable/all_any_extended.rb +6 -6
  22. data/lib/nuggets/enumerable/minmax.rb +2 -2
  23. data/lib/nuggets/env/set_mixin.rb +4 -4
  24. data/lib/nuggets/env/user_home_mixin.rb +1 -1
  25. data/lib/nuggets/file/replace_mixin.rb +3 -3
  26. data/lib/nuggets/file/sub_mixin.rb +2 -2
  27. data/lib/nuggets/file/which_mixin.rb +15 -14
  28. data/lib/nuggets/hash/nest_mixin.rb +3 -3
  29. data/lib/nuggets/hash/only.rb +6 -4
  30. data/lib/nuggets/hash/unroll_mixin.rb +1 -1
  31. data/lib/nuggets/io/modes.rb +12 -12
  32. data/lib/nuggets/numeric/duration.rb +3 -3
  33. data/lib/nuggets/object/blank_mixin.rb +6 -6
  34. data/lib/nuggets/object/boolean_mixin.rb +3 -3
  35. data/lib/nuggets/object/singleton_class_mixin.rb +3 -3
  36. data/lib/nuggets/range/quantile_mixin.rb +1 -1
  37. data/lib/nuggets/statistics.rb +11 -0
  38. data/lib/nuggets/statistics_mixins.rb +11 -0
  39. data/lib/nuggets/string/case.rb +4 -4
  40. data/lib/nuggets/string/msub.rb +1 -1
  41. data/lib/nuggets/string/nsub.rb +2 -2
  42. data/lib/nuggets/string/sub_with_md.rb +2 -2
  43. data/lib/nuggets/tempfile/open.rb +1 -1
  44. data/lib/nuggets/uri/content_type_mixin.rb +1 -1
  45. data/lib/nuggets/uri/exist_mixin.rb +2 -2
  46. data/lib/nuggets/util/content_type.rb +1 -1
  47. data/lib/nuggets/util/i18n.rb +63 -63
  48. data/lib/nuggets/util/ruby.rb +7 -7
  49. data/lib/nuggets/version.rb +2 -2
  50. data/spec/nuggets/array/mean_spec.rb +127 -0
  51. data/spec/nuggets/array/median_spec.rb +79 -0
  52. data/spec/nuggets/array/mode_spec.rb +59 -0
  53. data/spec/nuggets/string/evaluate_spec.rb +2 -2
  54. metadata +29 -15
@@ -0,0 +1,5 @@
1
+ require 'nuggets/array/mode_mixin'
2
+
3
+ class Array
4
+ include Nuggets::Array::ModeMixin
5
+ end
@@ -0,0 +1,70 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # A component of ruby-nuggets, some extensions to the Ruby programming #
5
+ # language. #
6
+ # #
7
+ # Copyright (C) 2007-2011 Jens Wille #
8
+ # #
9
+ # Authors: #
10
+ # Jens Wille <jens.wille@uni-koeln.de> #
11
+ # #
12
+ # ruby-nuggets is free software; you can redistribute it and/or modify it #
13
+ # under the terms of the GNU General Public License as published by the Free #
14
+ # Software Foundation; either version 3 of the License, or (at your option) #
15
+ # any later version. #
16
+ # #
17
+ # ruby-nuggets is distributed in the hope that it will be useful, but WITHOUT #
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
20
+ # more details. #
21
+ # #
22
+ # You should have received a copy of the GNU General Public License along #
23
+ # with ruby-nuggets. If not, see <http://www.gnu.org/licenses/>. #
24
+ # #
25
+ ###############################################################################
26
+ #++
27
+
28
+ require 'nuggets/array/histogram_mixin'
29
+
30
+ module Nuggets
31
+ class Array
32
+ module ModeMixin
33
+
34
+ def self.included(base)
35
+ base.send :include, Nuggets::Array::HistogramMixin
36
+ end
37
+
38
+ # call-seq:
39
+ # array.mode => anObject
40
+ # array.mode(+true+) => anArray
41
+ #
42
+ # Returns the mode[http://en.wikipedia.org/wiki/Mode_%28statistics%29] of
43
+ # the values in _array_ (via #histogram).
44
+ #
45
+ # If parameter +true+ is passed, an Array of all modes is returned.
46
+ def mode(all = false, &block)
47
+ hist, modes = histogram(&block), []
48
+ freq = hist.values.max
49
+
50
+ hist.each { |key, value|
51
+ if value == freq
52
+ modes << key
53
+ break unless all
54
+ end
55
+ }
56
+
57
+ all ? modes : modes.first
58
+ end
59
+
60
+ # call-seq:
61
+ # array.modes => anArray
62
+ #
63
+ # Returns an Array of all modes of the values in _array_ (see #mode).
64
+ def modes(&block)
65
+ mode(true, &block)
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -28,7 +28,7 @@
28
28
  class Array
29
29
 
30
30
  # call-seq:
31
- # array.monotone?(operator) => true or false
31
+ # array.monotone?(operator) => +true+ or +false+
32
32
  #
33
33
  # Check whether _array_ is monotone according to +operator+.
34
34
  def monotone?(operator)
@@ -42,7 +42,7 @@ class Array
42
42
  alias_method :monotonic?, :monotone?
43
43
 
44
44
  # call-seq:
45
- # array.ascending? => true or false
45
+ # array.ascending? => +true+ or +false+
46
46
  #
47
47
  # Check whether _array_ is (strictly) ascending.
48
48
  def ascending?(strict = false)
@@ -51,7 +51,7 @@ class Array
51
51
  alias_method :increasing?, :ascending?
52
52
 
53
53
  # call-seq:
54
- # array.strictly_ascending? => true or false
54
+ # array.strictly_ascending? => +true+ or +false+
55
55
  #
56
56
  # Check whether _array_ is strictly ascending.
57
57
  def strictly_ascending?
@@ -60,7 +60,7 @@ class Array
60
60
  alias_method :strictly_increasing?, :strictly_ascending?
61
61
 
62
62
  # call-seq:
63
- # array.descending? => true or false
63
+ # array.descending? => +true+ or +false+
64
64
  #
65
65
  # Check whether _array_ is (strictly) descending.
66
66
  def descending?(strict = false)
@@ -69,7 +69,7 @@ class Array
69
69
  alias_method :decreasing?, :descending?
70
70
 
71
71
  # call-seq:
72
- # array.strictly_descending? => true or false
72
+ # array.strictly_descending? => +true+ or +false+
73
73
  #
74
74
  # Check whether _array_ is strictly descending.
75
75
  def strictly_descending?
@@ -28,10 +28,11 @@
28
28
  class Array
29
29
 
30
30
  # call-seq:
31
- # array.only(relax = true or false) => anObject
31
+ # array.only => anObject
32
+ # array.only(+true+) => anObject
32
33
  #
33
34
  # Returns the only element of _array_. Raises an IndexError if _array_'s
34
- # size is not 1, unless +relax+ is true.
35
+ # size is not 1, unless parameter +true+ is passed.
35
36
  #
36
37
  # Idea stolen from Gavin Sinclair's Ruby Extensions Project.
37
38
  def only(relax = size == 1)
@@ -0,0 +1,5 @@
1
+ require 'nuggets/array/regression_mixin'
2
+
3
+ class Array
4
+ include Nuggets::Array::RegressionMixin
5
+ end
@@ -0,0 +1,63 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # A component of ruby-nuggets, some extensions to the Ruby programming #
5
+ # language. #
6
+ # #
7
+ # Copyright (C) 2007-2011 Jens Wille #
8
+ # #
9
+ # Authors: #
10
+ # Jens Wille <jens.wille@uni-koeln.de> #
11
+ # #
12
+ # ruby-nuggets is free software; you can redistribute it and/or modify it #
13
+ # under the terms of the GNU General Public License as published by the Free #
14
+ # Software Foundation; either version 3 of the License, or (at your option) #
15
+ # any later version. #
16
+ # #
17
+ # ruby-nuggets is distributed in the hope that it will be useful, but WITHOUT #
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
20
+ # more details. #
21
+ # #
22
+ # You should have received a copy of the GNU General Public License along #
23
+ # with ruby-nuggets. If not, see <http://www.gnu.org/licenses/>. #
24
+ # #
25
+ ###############################################################################
26
+ #++
27
+
28
+ require 'nuggets/array/correlation_mixin'
29
+
30
+ module Nuggets
31
+ class Array
32
+ module RegressionMixin
33
+
34
+ def self.included(base)
35
+ base.send :include, Nuggets::Array::CorrelationMixin
36
+ end
37
+
38
+ # call-seq:
39
+ # array.linear_least_squares => anArray
40
+ #
41
+ # Calculates the {linear least squares regression}[http://en.wikipedia.org/wiki/Ordinary_least_squares]
42
+ # for the <tt>{x,y}</tt> pairs in _array_.
43
+ def linear_least_squares
44
+ sx, sy = 0.0, 0.0
45
+
46
+ return [] if empty?
47
+
48
+ each { |x, y|
49
+ sx += x
50
+ sy += y
51
+ }
52
+
53
+ b = corr * sy / sx
54
+ a = (sy - b * sx) / size.to_f
55
+
56
+ map { |x, _| [x, a + b * x] }
57
+ end
58
+
59
+ alias_method :llsq, :linear_least_squares
60
+
61
+ end
62
+ end
63
+ end
@@ -38,7 +38,7 @@ module Nuggets
38
38
  end
39
39
 
40
40
  # call-seq:
41
- # array.runiq! => an_array or nil
41
+ # array.runiq! => an_array or +nil+
42
42
  #
43
43
  # Reverse #uniq!.
44
44
  def runiq!
@@ -4,7 +4,7 @@
4
4
  # A component of ruby-nuggets, some extensions to the Ruby programming #
5
5
  # language. #
6
6
  # #
7
- # Copyright (C) 2007-2009 Jens Wille #
7
+ # Copyright (C) 2007-2011 Jens Wille #
8
8
  # #
9
9
  # Authors: #
10
10
  # Jens Wille <jens.wille@uni-koeln.de> #
@@ -38,13 +38,10 @@ module Nuggets
38
38
  # call-seq:
39
39
  # array.standard_deviation => aFloat
40
40
  #
41
- # Calculates the standard deviation of the items contained in _array_.
42
- def standard_deviation
43
- begin
44
- Math.sqrt(block_given? ? variance { |*a| yield(*a) } : variance)
45
- rescue Errno::EDOM
46
- 0.0
47
- end
41
+ # Calculates the {standard deviation}[http://en.wikipedia.org/wiki/Standard_deviation]
42
+ # of the values in _array_.
43
+ def standard_deviation(&block)
44
+ Math.sqrt(variance(&block))
48
45
  end
49
46
 
50
47
  alias_method :std, :standard_deviation
@@ -4,7 +4,7 @@
4
4
  # A component of ruby-nuggets, some extensions to the Ruby programming #
5
5
  # language. #
6
6
  # #
7
- # Copyright (C) 2007-2009 Jens Wille #
7
+ # Copyright (C) 2007-2011 Jens Wille #
8
8
  # #
9
9
  # Authors: #
10
10
  # Jens Wille <jens.wille@uni-koeln.de> #
@@ -32,27 +32,46 @@ module Nuggets
32
32
  # call-seq:
33
33
  # array.variance => aFloat
34
34
  #
35
- # Calculates the variance of the items in _array_.
36
- #
37
- # Based on <http://warrenseen.com/blog/2006/03/13/how-to-calculate-standard-deviation/>.
35
+ # Calculates the variance[http://en.wikipedia.org/wiki/Variance] of the
36
+ # values in _array_.
38
37
  def variance
39
- s, mean = 0.0, 0.0
38
+ sx, sq = 0.0, 0.0
40
39
 
41
- return s if empty?
40
+ return sx if empty?
42
41
 
43
- each_with_index { |x, n|
42
+ each { |x|
44
43
  x = yield x if block_given?
45
44
 
46
- delta = x - mean
47
- mean += delta / (n + 1)
48
- s += delta * (x - mean)
45
+ sx += x
46
+ sq += x ** 2
49
47
  }
50
48
 
51
- s / size
49
+ (sq - sx ** 2 / size) / size
52
50
  end
53
51
 
54
52
  alias_method :var, :variance
55
53
 
54
+ # call-seq:
55
+ # array.covariance => aFloat
56
+ #
57
+ # Calculates the covariance[http://en.wikipedia.org/wiki/Covariance] of the
58
+ # <tt>{x,y}</tt> pairs in _array_.
59
+ def covariance
60
+ sx, sy, sp = 0.0, 0.0, 0.0
61
+
62
+ return sx if empty?
63
+
64
+ each { |x, y|
65
+ sx += x
66
+ sy += y
67
+ sp += x * y
68
+ }
69
+
70
+ (sp - sx * sy / size) / size
71
+ end
72
+
73
+ alias_method :cov, :covariance
74
+
56
75
  end
57
76
  end
58
77
  end
@@ -31,23 +31,23 @@ module Enumerable
31
31
  alias_method :_nuggets_original_any?, :any?
32
32
 
33
33
  # call-seq:
34
- # enum.all?(obj[, operator]) => true or false
35
- # enum.all? { ... } => true or false
34
+ # enum.all?(obj[, operator]) => +true+ or +false+
35
+ # enum.all? { ... } => +true+ or +false+
36
36
  #
37
37
  # Adds the ability to pass an +object+ instead of a block, which will then
38
38
  # be tested against each item in _enum_ according to +operator+, defaulting
39
- # to :===.
39
+ # to <tt>:===</tt>.
40
40
  def all?(object = default = Object.new, operator = :===, &block)
41
41
  _nuggets_original_all?(&_block_for_all_any_extended(object, default, operator, &block))
42
42
  end
43
43
 
44
44
  # call-seq:
45
- # enum.any?(obj[, operator]) => true or false
46
- # enum.any? { ... } => true or false
45
+ # enum.any?(obj[, operator]) => +true+ or +false+
46
+ # enum.any? { ... } => +true+ or +false+
47
47
  #
48
48
  # Adds the ability to pass an +object+ instead of a block, which will then
49
49
  # be tested against each item in _enum_ according to +operator+, defaulting
50
- # to :===.
50
+ # to <tt>:===</tt>.
51
51
  def any?(object = default = Object.new, operator = :===, &block)
52
52
  _nuggets_original_any?(&_block_for_all_any_extended(object, default, operator, &block))
53
53
  end
@@ -85,7 +85,7 @@ module Enumerable
85
85
  # call-seq:
86
86
  # enum.max(what) => aValue
87
87
  #
88
- # Maximum #minmax. If +what+ is omitted, or nil, the original Enumerable#max
88
+ # Maximum #minmax. If +what+ is omitted, or +nil+, the original Enumerable#max
89
89
  # is called.
90
90
  def max(what = nil)
91
91
  what ? minmax(:max, what) : block_given? ?
@@ -95,7 +95,7 @@ module Enumerable
95
95
  # call-seq:
96
96
  # enum.min(what) => aValue
97
97
  #
98
- # Minimum #minmax. If +what+ is omitted, or nil, the original Enumerable#min
98
+ # Minimum #minmax. If +what+ is omitted, or +nil+, the original Enumerable#min
99
99
  # is called.
100
100
  def min(what = nil)
101
101
  what ? minmax(:min, what) : block_given? ?
@@ -30,10 +30,10 @@ module Nuggets
30
30
  module SetMixin
31
31
 
32
32
  # call-seq:
33
- # ENV.set(env = {}, clear = true) => aHash
34
- # ENV.set(env = {}, clear = true) { ... } => anObject
33
+ # ENV.set([env[, clear]]) => aHash
34
+ # ENV.set([env[, clear]]) { ... } => anObject
35
35
  #
36
- # Overrides ENV with +env+, clearing it beforehand if +clear+ is true. If a
36
+ # Overrides ENV with +env+, clearing it beforehand if +clear+ is +true+. If a
37
37
  # block is given, restores ENV to its original state afterwards and returns
38
38
  # the result of the block; otherwise returns the original ENV as a hash.
39
39
  def set(env = {}, clear = true)
@@ -56,7 +56,7 @@ module Nuggets
56
56
  alias_method :without, :set
57
57
 
58
58
  # call-seq:
59
- # ENV.with(env = {}, clear = false) { ... } => anObject
59
+ # ENV.with([env[, clear]]) { ... } => anObject
60
60
  #
61
61
  # Temporarily overrides ENV with +env+ for the block execution. See #set.
62
62
  def with(env = {}, clear = false)
@@ -30,7 +30,7 @@ module Nuggets
30
30
  module UserHomeMixin
31
31
 
32
32
  # call-seq:
33
- # ENV.user_home(default = '/') => aString
33
+ # ENV.user_home([default]) => aString
34
34
  #
35
35
  # Returns the user's home directory, or +default+ if it could not be found.
36
36
  def user_home(default = ::File::ALT_SEPARATOR ? 'C:/' : '/')
@@ -30,13 +30,13 @@ module Nuggets
30
30
  module ReplaceMixin
31
31
 
32
32
  # call-seq:
33
- # File.replace(name, create_if_missing = false) { ... } => aString
34
- # File.replace(name, create_if_missing = false) { |content| ... } => aString
33
+ # File.replace(name[, create_if_missing]) { ... } => aString
34
+ # File.replace(name[, create_if_missing]) { |content| ... } => aString
35
35
  #
36
36
  # Replaces the contents of file +name+ with the result of the block. Yields
37
37
  # the file's contents to the block if requested. Returns the new content.
38
38
  #
39
- # If +create_if_missing+ is true and the file does not exist, it will be
39
+ # If +create_if_missing+ is +true+ and the file does not exist, it will be
40
40
  # created.
41
41
  def replace(name, create_if_missing = false, &block)
42
42
  open(name, create_if_missing && !exist?(name) ? 'w+' : 'r+') { |f|
@@ -47,7 +47,7 @@ module Nuggets
47
47
  end
48
48
 
49
49
  # call-seq:
50
- # File.sub!(name, *args, &block) => aString or nil
50
+ # File.sub!(name, *args, &block) => aString or +nil+
51
51
  #
52
52
  # Calls String#sub! on file +name+'s contents with +args+ and (optional)
53
53
  # +block+ and replaces the file with the new content. Returns the result
@@ -75,7 +75,7 @@ module Nuggets
75
75
  end
76
76
 
77
77
  # call-seq:
78
- # File.gsub!(name, *args, &block) => aString or nil
78
+ # File.gsub!(name, *args, &block) => aString or +nil+
79
79
  #
80
80
  # Calls String#gsub! on file +name+'s contents with +args+ and (optional)
81
81
  # +block+ and replaces the file with the new content. Returns the result
@@ -34,7 +34,7 @@ module Nuggets
34
34
  DEFAULT_EXTENSIONS = [RbConfig::CONFIG['EXEEXT']]
35
35
 
36
36
  # call-seq:
37
- # File.which(executable, extensions = DEFAULT_EXTENSIONS) => aString or nil
37
+ # File.which(executable[, extensions]) => aString or +nil+
38
38
  #
39
39
  # Returns +executable+ if it's executable, or the full path to +executable+
40
40
  # found in PATH, or +nil+ otherwise. Checks +executable+ with each extension
@@ -44,27 +44,28 @@ module Nuggets
44
44
  def which(executable, extensions = DEFAULT_EXTENSIONS)
45
45
  extensions |= ['']
46
46
 
47
- extensions.each { |extension|
48
- executable += extension
49
- return executable if executable?(executable)
47
+ if env = ENV['PATH']
48
+ dirs = env.split(self::PATH_SEPARATOR)
49
+ dirs.map! { |dir| expand_path(dir) }
50
+ end
50
51
 
51
- if path = ENV['PATH']
52
- path.split(::File::PATH_SEPARATOR).each { |dir|
53
- candidate = join(expand_path(dir), executable)
54
- return candidate if executable?(candidate)
55
- }
56
- end
57
- }
52
+ extensions.find { |extension|
53
+ file = "#{executable}#{extension}"
54
+ return file if file?(file) && executable?(file)
58
55
 
59
- nil
56
+ dirs.find { |dir|
57
+ path = join(dir, file)
58
+ return path if file?(path) && executable?(path)
59
+ } if dirs
60
+ }
60
61
  end
61
62
 
62
63
  # call-seq:
63
- # File.which_command(commands) => aString or nil
64
+ # File.which_command(commands) => aString or +nil+
64
65
  #
65
66
  # Returns the first of +commands+ that is executable (according to #which).
66
67
  def which_command(commands, extensions = DEFAULT_EXTENSIONS)
67
- commands.find { |command| which(command[/\S+/], extensions) }
68
+ commands.find { |command| which(command.to_s[/\S+/], extensions) }
68
69
  end
69
70
 
70
71
  end