ruby-nuggets 0.6.9 → 0.7.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.
- data/.rspec +1 -0
- data/README +1 -1
- data/Rakefile +4 -4
- data/lib/nuggets/array/correlation.rb +5 -0
- data/lib/nuggets/array/correlation_mixin.rb +62 -0
- data/lib/nuggets/array/histogram.rb +5 -0
- data/lib/nuggets/array/histogram_mixin.rb +155 -0
- data/lib/nuggets/array/mean.rb +5 -0
- data/lib/nuggets/array/mean_mixin.rb +139 -0
- data/lib/nuggets/array/median.rb +5 -0
- data/lib/nuggets/array/median_mixin.rb +74 -0
- data/lib/nuggets/array/mode.rb +5 -0
- data/lib/nuggets/array/mode_mixin.rb +70 -0
- data/lib/nuggets/array/monotone.rb +5 -5
- data/lib/nuggets/array/only.rb +3 -2
- data/lib/nuggets/array/regression.rb +5 -0
- data/lib/nuggets/array/regression_mixin.rb +63 -0
- data/lib/nuggets/array/runiq_mixin.rb +1 -1
- data/lib/nuggets/array/standard_deviation_mixin.rb +5 -8
- data/lib/nuggets/array/variance_mixin.rb +30 -11
- data/lib/nuggets/enumerable/all_any_extended.rb +6 -6
- data/lib/nuggets/enumerable/minmax.rb +2 -2
- data/lib/nuggets/env/set_mixin.rb +4 -4
- data/lib/nuggets/env/user_home_mixin.rb +1 -1
- data/lib/nuggets/file/replace_mixin.rb +3 -3
- data/lib/nuggets/file/sub_mixin.rb +2 -2
- data/lib/nuggets/file/which_mixin.rb +15 -14
- data/lib/nuggets/hash/nest_mixin.rb +3 -3
- data/lib/nuggets/hash/only.rb +6 -4
- data/lib/nuggets/hash/unroll_mixin.rb +1 -1
- data/lib/nuggets/io/modes.rb +12 -12
- data/lib/nuggets/numeric/duration.rb +3 -3
- data/lib/nuggets/object/blank_mixin.rb +6 -6
- data/lib/nuggets/object/boolean_mixin.rb +3 -3
- data/lib/nuggets/object/singleton_class_mixin.rb +3 -3
- data/lib/nuggets/range/quantile_mixin.rb +1 -1
- data/lib/nuggets/statistics.rb +11 -0
- data/lib/nuggets/statistics_mixins.rb +11 -0
- data/lib/nuggets/string/case.rb +4 -4
- data/lib/nuggets/string/msub.rb +1 -1
- data/lib/nuggets/string/nsub.rb +2 -2
- data/lib/nuggets/string/sub_with_md.rb +2 -2
- data/lib/nuggets/tempfile/open.rb +1 -1
- data/lib/nuggets/uri/content_type_mixin.rb +1 -1
- data/lib/nuggets/uri/exist_mixin.rb +2 -2
- data/lib/nuggets/util/content_type.rb +1 -1
- data/lib/nuggets/util/i18n.rb +63 -63
- data/lib/nuggets/util/ruby.rb +7 -7
- data/lib/nuggets/version.rb +2 -2
- data/spec/nuggets/array/mean_spec.rb +127 -0
- data/spec/nuggets/array/median_spec.rb +79 -0
- data/spec/nuggets/array/mode_spec.rb +59 -0
- data/spec/nuggets/string/evaluate_spec.rb +2 -2
- metadata +29 -15
data/.rspec
CHANGED
data/README
CHANGED
data/Rakefile
CHANGED
@@ -10,10 +10,10 @@ begin
|
|
10
10
|
},
|
11
11
|
|
12
12
|
:gem => {
|
13
|
-
:version
|
14
|
-
:summary
|
15
|
-
:
|
16
|
-
:
|
13
|
+
:version => Nuggets::VERSION,
|
14
|
+
:summary => %q{Some extensions to the Ruby programming language.},
|
15
|
+
:author => %q{Jens Wille},
|
16
|
+
:email => %q{jens.wille@uni-koeln.de}
|
17
17
|
}
|
18
18
|
}}
|
19
19
|
rescue LoadError => err
|
@@ -0,0 +1,62 @@
|
|
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/variance_mixin'
|
29
|
+
|
30
|
+
module Nuggets
|
31
|
+
class Array
|
32
|
+
module CorrelationMixin
|
33
|
+
|
34
|
+
def self.included(base)
|
35
|
+
base.send :include, Nuggets::Array::VarianceMixin
|
36
|
+
end
|
37
|
+
|
38
|
+
# call-seq:
|
39
|
+
# array.correlation_coefficient => anArray
|
40
|
+
#
|
41
|
+
# Calculates the {Pearson product-moment correlation
|
42
|
+
# coefficient}[http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient]
|
43
|
+
# for the <tt>{x,y}</tt> pairs in _array_.
|
44
|
+
def correlation_coefficient
|
45
|
+
sx, sy = 0.0, 0.0
|
46
|
+
|
47
|
+
return sx if empty?
|
48
|
+
|
49
|
+
each { |x, y|
|
50
|
+
sx += x
|
51
|
+
sy += y
|
52
|
+
}
|
53
|
+
|
54
|
+
(sx * cov) / (sy * var { |x, _| x })
|
55
|
+
end
|
56
|
+
|
57
|
+
alias_method :corr, :correlation_coefficient
|
58
|
+
alias_method :pmcc, :correlation_coefficient
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,155 @@
|
|
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
|
+
module Nuggets
|
29
|
+
class Array
|
30
|
+
module HistogramMixin
|
31
|
+
|
32
|
+
# Provides some default formats for #formatted_histogram.
|
33
|
+
#
|
34
|
+
# Example:
|
35
|
+
#
|
36
|
+
# (default) ab [==] 2
|
37
|
+
# (percent) xyz [===] 3 (37.50%)
|
38
|
+
# (numeric) 42 [==] 2
|
39
|
+
# (numeric_percent) 123 [=] 1 (12.50%)
|
40
|
+
#
|
41
|
+
# The "numeric" variants format the item as a (decimal) number.
|
42
|
+
FORMATS = {
|
43
|
+
:default => '%-*s [%s]%*s %*d',
|
44
|
+
:percent => '%-*s [%s]%*s %*d (%.2f%%)',
|
45
|
+
:numeric => '%*d [%s]%*s %*d',
|
46
|
+
:numeric_percent => '%*d [%s]%*s %*d (%.2f%%)'
|
47
|
+
}
|
48
|
+
|
49
|
+
# Encapsulates a #histogram item and provides the following attributes (see
|
50
|
+
# also #annotated_histogram):
|
51
|
+
#
|
52
|
+
# item:: The original item
|
53
|
+
# freq:: The item's frequency in the collection
|
54
|
+
# percentage:: The percentage of the item's frequency in the collection
|
55
|
+
# max_freq:: The maximum frequency in the collection
|
56
|
+
# max_freq_length:: The maximum frequency's "width"
|
57
|
+
# max_item_length:: The maximum item length in the collection
|
58
|
+
HistogramItem = ::Struct.new(
|
59
|
+
:item, :freq, :max_freq, :max_freq_length, :max_item_length, :percentage
|
60
|
+
)
|
61
|
+
|
62
|
+
# call-seq:
|
63
|
+
# array.histogram => aHash
|
64
|
+
# array.histogram { |x| ... } => aHash
|
65
|
+
#
|
66
|
+
# Calculates the {frequency histogram}[http://en.wikipedia.org/wiki/Histogram]
|
67
|
+
# of the values in _array_. Returns a Hash that maps any value, or the result
|
68
|
+
# of the value yielded to the block, to its frequency.
|
69
|
+
def histogram
|
70
|
+
hist = ::Hash.new(0)
|
71
|
+
each { |x| hist[block_given? ? yield(x) : x] += 1 }
|
72
|
+
hist
|
73
|
+
end
|
74
|
+
|
75
|
+
# call-seq:
|
76
|
+
# array.annotated_histogram => anArray
|
77
|
+
# array.annotated_histogram { |hist_item| ... } => aHash
|
78
|
+
#
|
79
|
+
# Calculates the #histogram for _array_ and yields each histogram item
|
80
|
+
# (see HistogramItem) to the block or returns an Array of the histogram
|
81
|
+
# items.
|
82
|
+
def annotated_histogram
|
83
|
+
hist, items = histogram, []
|
84
|
+
|
85
|
+
percentage = size / 100.0
|
86
|
+
|
87
|
+
max_freq = hist.values.max
|
88
|
+
max_freq_length = max_freq.to_s.length
|
89
|
+
|
90
|
+
max_item_length = hist.keys.map { |item| item.to_s.length }.max
|
91
|
+
|
92
|
+
# try to sort the histogram hash
|
93
|
+
begin
|
94
|
+
hist = hist.sort
|
95
|
+
rescue ::ArgumentError
|
96
|
+
end
|
97
|
+
|
98
|
+
hist.each { |item, freq|
|
99
|
+
hist_item = HistogramItem.new(
|
100
|
+
item, freq, max_freq, max_freq_length, max_item_length, freq / percentage
|
101
|
+
)
|
102
|
+
|
103
|
+
block_given? ? yield(hist_item) : items << hist_item
|
104
|
+
}
|
105
|
+
|
106
|
+
block_given? ? hist : items
|
107
|
+
end
|
108
|
+
|
109
|
+
# call-seq:
|
110
|
+
# array.formatted_histogram([format[, indicator]]) => aString
|
111
|
+
#
|
112
|
+
# Returns the #histogram of _array_ as a formatted String according to
|
113
|
+
# +format+, using +indicator+ to draw the frequency bar.
|
114
|
+
#
|
115
|
+
# +format+ may be a Symbol indicating one of the provided default formats
|
116
|
+
# (see FORMATS) or a format String (see Kernel#sprintf) that will receive
|
117
|
+
# the following arguments (in order):
|
118
|
+
#
|
119
|
+
# 1. +max_item_length+ (Integer)
|
120
|
+
# 1. +item+ (String)
|
121
|
+
# 1. "frequency_bar" (String)
|
122
|
+
# 1. "padding" (String)
|
123
|
+
# 1. +max_freq_length+ (Integer)
|
124
|
+
# 1. +freq+ (Integer)
|
125
|
+
# 1. +percentage+ (Float, optional)
|
126
|
+
#
|
127
|
+
# See HistogramItem for further details on the individual arguments.
|
128
|
+
def formatted_histogram(format = :default, indicator = '=')
|
129
|
+
format = FORMATS[format] if FORMATS.has_key?(format)
|
130
|
+
raise ::TypeError, "String expected, got #{format.class}" unless format.is_a?(::String)
|
131
|
+
|
132
|
+
include_percentage = format.include?('%%')
|
133
|
+
indicator_length = indicator.length
|
134
|
+
|
135
|
+
lines = []
|
136
|
+
|
137
|
+
annotated_histogram { |hist|
|
138
|
+
arguments = [
|
139
|
+
hist.max_item_length, hist.item, # item (padded)
|
140
|
+
indicator * hist.freq, # indicator bar
|
141
|
+
(hist.max_freq - hist.freq) * indicator_length, '', # indicator padding
|
142
|
+
hist.max_freq_length, hist.freq # frequency (padded)
|
143
|
+
]
|
144
|
+
|
145
|
+
arguments << hist.percentage if include_percentage # percentage (optional)
|
146
|
+
|
147
|
+
lines << format % arguments
|
148
|
+
}
|
149
|
+
|
150
|
+
lines.join("\n")
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,139 @@
|
|
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
|
+
module Nuggets
|
29
|
+
class Array
|
30
|
+
module MeanMixin
|
31
|
+
|
32
|
+
# call-seq:
|
33
|
+
# array.generalized_mean(exponent) => aFloat
|
34
|
+
# array.generalized_mean(exponent) { |x| ... } => aFloat
|
35
|
+
#
|
36
|
+
# Calculates the {generalized mean}[http://en.wikipedia.org/wiki/Generalized_mean]
|
37
|
+
# of the values in _array_ for +exponent+. Returns the #geometric_mean if
|
38
|
+
# +exponent+ is zero.
|
39
|
+
#
|
40
|
+
# An optional block may be passed to provide a weight for each value.
|
41
|
+
# Defaults to 1. Returns +nil+ if the sum of all weights is zero (this
|
42
|
+
# includes _array_ being empty).
|
43
|
+
def generalized_mean(exponent, &block)
|
44
|
+
return geometric_mean(&block) if exponent.zero?
|
45
|
+
|
46
|
+
total, weights = 0, 0
|
47
|
+
|
48
|
+
each { |x|
|
49
|
+
weight = block ? block[x] : 1
|
50
|
+
|
51
|
+
total += weight * x ** exponent
|
52
|
+
weights += weight
|
53
|
+
}
|
54
|
+
|
55
|
+
(total / weights.to_f) ** (1 / exponent) unless weights.zero?
|
56
|
+
end
|
57
|
+
|
58
|
+
alias_method :power_mean, :generalized_mean
|
59
|
+
alias_method :minkowski_mean, :generalized_mean
|
60
|
+
|
61
|
+
# call-seq:
|
62
|
+
# array.arithmetic_mean => aFloat
|
63
|
+
# array.arithmetic_mean { |x| ... } => aFloat
|
64
|
+
#
|
65
|
+
# Calculates the {arithmetic mean}[http://en.wikipedia.org/wiki/Arithmetic_mean]
|
66
|
+
# of the values in _array_.
|
67
|
+
#
|
68
|
+
# An optional block may be passed to provide a weight for each value.
|
69
|
+
# Defaults to 1. Returns +nil+ if the sum of all weights is zero (this
|
70
|
+
# includes _array_ being empty).
|
71
|
+
def arithmetic_mean(&block)
|
72
|
+
generalized_mean(1, &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
alias_method :mean, :arithmetic_mean
|
76
|
+
alias_method :average, :arithmetic_mean
|
77
|
+
alias_method :avg, :arithmetic_mean
|
78
|
+
|
79
|
+
# call-seq:
|
80
|
+
# array.root_mean_square => aFloat
|
81
|
+
# array.root_mean_square { |x| ... } => aFloat
|
82
|
+
#
|
83
|
+
# Calculates the {root mean square}[http://en.wikipedia.org/wiki/Root_mean_square]
|
84
|
+
# (quadratic mean) of the values in _array_.
|
85
|
+
#
|
86
|
+
# An optional block may be passed to provide a weight for each value.
|
87
|
+
# Defaults to 1. Returns +nil+ if the sum of all weights is zero (this
|
88
|
+
# includes _array_ being empty).
|
89
|
+
def root_mean_square(&block)
|
90
|
+
generalized_mean(2, &block)
|
91
|
+
end
|
92
|
+
|
93
|
+
alias_method :rms, :root_mean_square
|
94
|
+
alias_method :quadratic_mean, :root_mean_square
|
95
|
+
|
96
|
+
# call-seq:
|
97
|
+
# array.harmonic_mean => aFloat
|
98
|
+
# array.harmonic_mean { |x| ... } => aFloat
|
99
|
+
#
|
100
|
+
# Calculates the {harmonic mean}[http://en.wikipedia.org/wiki/Harmonic_mean]
|
101
|
+
# of the values in _array_.
|
102
|
+
#
|
103
|
+
# An optional block may be passed to provide a weight for each value.
|
104
|
+
# Defaults to 1. Returns +nil+ if the sum of all weights is zero (this
|
105
|
+
# includes _array_ being empty).
|
106
|
+
def harmonic_mean(&block)
|
107
|
+
generalized_mean(-1, &block)
|
108
|
+
end
|
109
|
+
|
110
|
+
alias_method :harmean, :harmonic_mean
|
111
|
+
|
112
|
+
# call-seq:
|
113
|
+
# array.geometric_mean => aFloat
|
114
|
+
# array.geometric_mean { |x| ... } => aFloat
|
115
|
+
#
|
116
|
+
# Calculates the {geometric mean}[http://en.wikipedia.org/wiki/Geometric_median]
|
117
|
+
# of the values in _array_.
|
118
|
+
#
|
119
|
+
# An optional block may be passed to provide a weight for each value.
|
120
|
+
# Defaults to 1. Returns +nil+ if the sum of all weights is zero (this
|
121
|
+
# includes _array_ being empty).
|
122
|
+
def geometric_mean
|
123
|
+
total, weights = 1, 0
|
124
|
+
|
125
|
+
each { |x|
|
126
|
+
weight = block_given? ? yield(x) : 1
|
127
|
+
|
128
|
+
total *= x ** weight
|
129
|
+
weights += weight
|
130
|
+
}
|
131
|
+
|
132
|
+
total ** (1 / weights.to_f) unless weights.zero?
|
133
|
+
end
|
134
|
+
|
135
|
+
alias_method :geomean, :geometric_mean
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,74 @@
|
|
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
|
+
module Nuggets
|
29
|
+
class Array
|
30
|
+
module MedianMixin
|
31
|
+
|
32
|
+
# call-seq:
|
33
|
+
# array.median([prefer]) => anObject
|
34
|
+
# array.median { |left, right| ... } => anObject
|
35
|
+
#
|
36
|
+
# Determines the median[http://en.wikipedia.org/wiki/Median] of the values
|
37
|
+
# in _array_. _array_ must be sortable.
|
38
|
+
#
|
39
|
+
# If _array_ contains an even number of values, a block may be passed to
|
40
|
+
# decide what the "middle" (average) should be. For Numeric values, the
|
41
|
+
# block is optional and the arithmetic mean will be used when no block
|
42
|
+
# is passed; for other values, the block is mandatory.
|
43
|
+
#
|
44
|
+
# Alternatively, +prefer+ may either be set to +true+, 1, or <tt>:left</tt>
|
45
|
+
# to use the left "middle", or to +false+, 2, or <tt>:right</tt> to use the
|
46
|
+
# right "middle". The block will then be ignored.
|
47
|
+
def median(prefer = nil)
|
48
|
+
return if empty?
|
49
|
+
|
50
|
+
sorted, index = sort, (size / 2.0).ceil - 1
|
51
|
+
|
52
|
+
case prefer
|
53
|
+
when true, 1, :left then prefer_left = true
|
54
|
+
when false, 2, :right then prefer_right = true
|
55
|
+
end
|
56
|
+
|
57
|
+
middle1 = sorted[index]
|
58
|
+
return middle1 if prefer_left || size.odd?
|
59
|
+
|
60
|
+
middle2 = sorted[index + 1]
|
61
|
+
return middle2 if prefer_right
|
62
|
+
|
63
|
+
unless block_given?
|
64
|
+
# simple arithmetic mean
|
65
|
+
(middle1 + middle2) / 2.0
|
66
|
+
else
|
67
|
+
# make your own average
|
68
|
+
yield middle1, middle2
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|