nuggets 0.9.9 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (222) hide show
  1. checksums.yaml +4 -4
  2. data/COPYING +663 -0
  3. data/ChangeLog +7 -0
  4. data/README +74 -0
  5. data/Rakefile +50 -0
  6. data/lib/nuggets.rb +73 -0
  7. data/lib/nuggets/all.rb +35 -0
  8. data/lib/nuggets/all_mixins.rb +33 -0
  9. data/lib/nuggets/ansicolor2css.rb +124 -0
  10. data/lib/nuggets/argv/option.rb +3 -0
  11. data/lib/nuggets/argv/option_mixin.rb +84 -0
  12. data/lib/nuggets/array/boost.rb +5 -0
  13. data/lib/nuggets/array/boost_mixin.rb +77 -0
  14. data/lib/nuggets/array/combination.rb +62 -0
  15. data/lib/nuggets/array/correlation.rb +5 -0
  16. data/lib/nuggets/array/correlation_mixin.rb +63 -0
  17. data/lib/nuggets/array/flatten_once.rb +56 -0
  18. data/lib/nuggets/array/flush.rb +5 -0
  19. data/lib/nuggets/array/flush_mixin.rb +46 -0
  20. data/lib/nuggets/array/format.rb +65 -0
  21. data/lib/nuggets/array/hashify.rb +5 -0
  22. data/lib/nuggets/array/hashify_mixin.rb +47 -0
  23. data/lib/nuggets/array/histogram.rb +5 -0
  24. data/lib/nuggets/array/histogram_mixin.rb +169 -0
  25. data/lib/nuggets/array/in_order.rb +50 -0
  26. data/lib/nuggets/array/limit.rb +5 -0
  27. data/lib/nuggets/array/limit_mixin.rb +56 -0
  28. data/lib/nuggets/array/mean.rb +5 -0
  29. data/lib/nuggets/array/mean_mixin.rb +202 -0
  30. data/lib/nuggets/array/median.rb +5 -0
  31. data/lib/nuggets/array/median_mixin.rb +73 -0
  32. data/lib/nuggets/array/mode.rb +5 -0
  33. data/lib/nuggets/array/mode_mixin.rb +69 -0
  34. data/lib/nuggets/array/monotone.rb +83 -0
  35. data/lib/nuggets/array/only.rb +41 -0
  36. data/lib/nuggets/array/rand.rb +44 -0
  37. data/lib/nuggets/array/regression.rb +5 -0
  38. data/lib/nuggets/array/regression_mixin.rb +149 -0
  39. data/lib/nuggets/array/runiq.rb +5 -0
  40. data/lib/nuggets/array/runiq_mixin.rb +52 -0
  41. data/lib/nuggets/array/shuffle.rb +132 -0
  42. data/lib/nuggets/array/standard_deviation.rb +5 -0
  43. data/lib/nuggets/array/standard_deviation_mixin.rb +50 -0
  44. data/lib/nuggets/array/to_hash.rb +64 -0
  45. data/lib/nuggets/array/variance.rb +5 -0
  46. data/lib/nuggets/array/variance_mixin.rb +81 -0
  47. data/lib/nuggets/content_type.rb +97 -0
  48. data/lib/nuggets/dotted_decimal.rb +59 -0
  49. data/lib/nuggets/enumerable/agrep.rb +79 -0
  50. data/lib/nuggets/enumerable/all_any_extended.rb +66 -0
  51. data/lib/nuggets/enumerable/minmax.rb +102 -0
  52. data/lib/nuggets/env/set.rb +3 -0
  53. data/lib/nuggets/env/set_mixin.rb +67 -0
  54. data/lib/nuggets/env/user_encoding.rb +3 -0
  55. data/lib/nuggets/env/user_encoding_mixin.rb +54 -0
  56. data/lib/nuggets/env/user_home.rb +3 -0
  57. data/lib/nuggets/env/user_home_mixin.rb +56 -0
  58. data/lib/nuggets/file/ext.rb +5 -0
  59. data/lib/nuggets/file/ext_mixin.rb +87 -0
  60. data/lib/nuggets/file/replace.rb +5 -0
  61. data/lib/nuggets/file/replace_mixin.rb +55 -0
  62. data/lib/nuggets/file/sub.rb +5 -0
  63. data/lib/nuggets/file/sub_mixin.rb +95 -0
  64. data/lib/nuggets/file/which.rb +5 -0
  65. data/lib/nuggets/file/which_mixin.rb +72 -0
  66. data/lib/nuggets/hash/at.rb +68 -0
  67. data/lib/nuggets/hash/deep_fetch.rb +5 -0
  68. data/lib/nuggets/hash/deep_fetch_mixin.rb +74 -0
  69. data/lib/nuggets/hash/deep_merge.rb +5 -0
  70. data/lib/nuggets/hash/deep_merge_mixin.rb +53 -0
  71. data/lib/nuggets/hash/idmap.rb +5 -0
  72. data/lib/nuggets/hash/idmap_mixin.rb +41 -0
  73. data/lib/nuggets/hash/in_order.rb +43 -0
  74. data/lib/nuggets/hash/insert.rb +53 -0
  75. data/lib/nuggets/hash/nest.rb +5 -0
  76. data/lib/nuggets/hash/nest_mixin.rb +78 -0
  77. data/lib/nuggets/hash/only.rb +52 -0
  78. data/lib/nuggets/hash/seen.rb +5 -0
  79. data/lib/nuggets/hash/seen_mixin.rb +58 -0
  80. data/lib/nuggets/hash/unroll.rb +5 -0
  81. data/lib/nuggets/hash/unroll_mixin.rb +88 -0
  82. data/lib/nuggets/hash/zip.rb +5 -0
  83. data/lib/nuggets/hash/zip_mixin.rb +159 -0
  84. data/lib/nuggets/i18n.rb +155 -0
  85. data/lib/nuggets/integer/factorial.rb +56 -0
  86. data/lib/nuggets/integer/length.rb +5 -0
  87. data/lib/nuggets/integer/length_mixin.rb +49 -0
  88. data/lib/nuggets/integer/map.rb +5 -0
  89. data/lib/nuggets/integer/map_mixin.rb +42 -0
  90. data/lib/nuggets/integer/to_binary_s.rb +38 -0
  91. data/lib/nuggets/io/agrep.rb +43 -0
  92. data/lib/nuggets/io/interact.rb +5 -0
  93. data/lib/nuggets/io/interact_mixin.rb +159 -0
  94. data/lib/nuggets/io/modes.rb +121 -0
  95. data/lib/nuggets/io/null.rb +5 -0
  96. data/lib/nuggets/io/null_mixin.rb +40 -0
  97. data/lib/nuggets/io/redirect.rb +5 -0
  98. data/lib/nuggets/io/redirect_mixin.rb +50 -0
  99. data/lib/nuggets/lazy_attr.rb +44 -0
  100. data/lib/nuggets/log_parser.rb +70 -0
  101. data/lib/nuggets/log_parser/apache.rb +101 -0
  102. data/lib/nuggets/log_parser/rails.rb +219 -0
  103. data/lib/nuggets/net/success.rb +59 -0
  104. data/lib/nuggets/numeric/between.rb +2 -0
  105. data/lib/nuggets/numeric/duration.rb +100 -0
  106. data/lib/nuggets/numeric/limit.rb +62 -0
  107. data/lib/nuggets/numeric/signum.rb +52 -0
  108. data/lib/nuggets/numeric/to_multiple.rb +61 -0
  109. data/lib/nuggets/object/blank.rb +20 -0
  110. data/lib/nuggets/object/blank_mixin.rb +99 -0
  111. data/lib/nuggets/object/boolean.rb +5 -0
  112. data/lib/nuggets/object/boolean_mixin.rb +61 -0
  113. data/lib/nuggets/object/eigenclass.rb +2 -0
  114. data/lib/nuggets/object/ghost_class.rb +2 -0
  115. data/lib/nuggets/object/metaclass.rb +2 -0
  116. data/lib/nuggets/object/msend.rb +5 -0
  117. data/lib/nuggets/object/msend_mixin.rb +43 -0
  118. data/lib/nuggets/object/silence.rb +5 -0
  119. data/lib/nuggets/object/silence_mixin.rb +44 -0
  120. data/lib/nuggets/object/singleton_class.rb +5 -0
  121. data/lib/nuggets/object/singleton_class_mixin.rb +95 -0
  122. data/lib/nuggets/object/uniclass.rb +2 -0
  123. data/lib/nuggets/object/virtual_class.rb +2 -0
  124. data/lib/nuggets/pluggable.rb +91 -0
  125. data/lib/nuggets/proc/bind.rb +5 -0
  126. data/lib/nuggets/proc/bind_mixin.rb +51 -0
  127. data/lib/nuggets/range/quantile.rb +5 -0
  128. data/lib/nuggets/range/quantile_mixin.rb +42 -0
  129. data/lib/nuggets/ruby.rb +235 -0
  130. data/lib/nuggets/statistics.rb +12 -0
  131. data/lib/nuggets/statistics_mixins.rb +12 -0
  132. data/lib/nuggets/string/camelscore.rb +5 -0
  133. data/lib/nuggets/string/camelscore_mixin.rb +116 -0
  134. data/lib/nuggets/string/capitalize_first.rb +46 -0
  135. data/lib/nuggets/string/case.rb +81 -0
  136. data/lib/nuggets/string/evaluate.rb +5 -0
  137. data/lib/nuggets/string/evaluate_mixin.rb +47 -0
  138. data/lib/nuggets/string/msub.rb +84 -0
  139. data/lib/nuggets/string/nsub.rb +65 -0
  140. data/lib/nuggets/string/sub_with_md.rb +111 -0
  141. data/lib/nuggets/string/wc.rb +5 -0
  142. data/lib/nuggets/string/wc_mixin.rb +95 -0
  143. data/lib/nuggets/string/word_wrap.rb +76 -0
  144. data/lib/nuggets/string/xor.rb +5 -0
  145. data/lib/nuggets/string/xor_mixin.rb +59 -0
  146. data/lib/nuggets/tempfile/open.rb +57 -0
  147. data/lib/nuggets/uri/content_type.rb +5 -0
  148. data/lib/nuggets/uri/content_type_mixin.rb +47 -0
  149. data/lib/nuggets/uri/exist.rb +5 -0
  150. data/lib/nuggets/uri/exist_mixin.rb +56 -0
  151. data/lib/nuggets/uri/redirect.rb +5 -0
  152. data/lib/nuggets/uri/redirect_mixin.rb +101 -0
  153. data/lib/nuggets/version.rb +27 -0
  154. data/spec/nuggets/array/boost_spec.rb +50 -0
  155. data/spec/nuggets/array/combination_spec.rb +25 -0
  156. data/spec/nuggets/array/correlation_spec.rb +81 -0
  157. data/spec/nuggets/array/flatten_once_spec.rb +16 -0
  158. data/spec/nuggets/array/flush_spec.rb +43 -0
  159. data/spec/nuggets/array/format_spec.rb +52 -0
  160. data/spec/nuggets/array/hashify_spec.rb +41 -0
  161. data/spec/nuggets/array/histogram_spec.rb +87 -0
  162. data/spec/nuggets/array/in_order_spec.rb +13 -0
  163. data/spec/nuggets/array/limit_spec.rb +62 -0
  164. data/spec/nuggets/array/mean_spec.rb +203 -0
  165. data/spec/nuggets/array/median_spec.rb +77 -0
  166. data/spec/nuggets/array/mode_spec.rb +57 -0
  167. data/spec/nuggets/array/monotone_spec.rb +30 -0
  168. data/spec/nuggets/array/only_spec.rb +26 -0
  169. data/spec/nuggets/array/regression_spec.rb +54 -0
  170. data/spec/nuggets/array/runiq_spec.rb +25 -0
  171. data/spec/nuggets/array/standard_deviation_spec.rb +33 -0
  172. data/spec/nuggets/array/to_hash_spec.rb +28 -0
  173. data/spec/nuggets/array/variance_spec.rb +106 -0
  174. data/spec/nuggets/dotted_decimal_spec.rb +27 -0
  175. data/spec/nuggets/enumerable/all_any_extended_spec.rb +31 -0
  176. data/spec/nuggets/enumerable/minmax_spec.rb +21 -0
  177. data/spec/nuggets/env/set_spec.rb +29 -0
  178. data/spec/nuggets/env/user_encoding_spec.rb +38 -0
  179. data/spec/nuggets/env/user_home_spec.rb +42 -0
  180. data/spec/nuggets/file/ext_spec.rb +38 -0
  181. data/spec/nuggets/file/replace_spec.rb +95 -0
  182. data/spec/nuggets/file/sub_spec.rb +149 -0
  183. data/spec/nuggets/file/which_spec.rb +22 -0
  184. data/spec/nuggets/hash/at_spec.rb +19 -0
  185. data/spec/nuggets/hash/deep_fetch_spec.rb +159 -0
  186. data/spec/nuggets/hash/deep_merge_spec.rb +78 -0
  187. data/spec/nuggets/hash/in_order_spec.rb +12 -0
  188. data/spec/nuggets/hash/insert_spec.rb +13 -0
  189. data/spec/nuggets/hash/nest_spec.rb +102 -0
  190. data/spec/nuggets/hash/only_spec.rb +29 -0
  191. data/spec/nuggets/hash/seen_spec.rb +36 -0
  192. data/spec/nuggets/hash/unroll_spec.rb +68 -0
  193. data/spec/nuggets/i18n_spec.rb +13 -0
  194. data/spec/nuggets/integer/factorial_spec.rb +10 -0
  195. data/spec/nuggets/integer/length_spec.rb +18 -0
  196. data/spec/nuggets/integer/map_spec.rb +19 -0
  197. data/spec/nuggets/integer/to_binary_s_spec.rb +19 -0
  198. data/spec/nuggets/numeric/duration_spec.rb +25 -0
  199. data/spec/nuggets/numeric/limit_spec.rb +16 -0
  200. data/spec/nuggets/numeric/signum_spec.rb +16 -0
  201. data/spec/nuggets/numeric/to_multiple_spec.rb +16 -0
  202. data/spec/nuggets/object/blank_spec.rb +34 -0
  203. data/spec/nuggets/object/boolean_spec.rb +23 -0
  204. data/spec/nuggets/object/msend_spec.rb +25 -0
  205. data/spec/nuggets/object/silence_spec.rb +36 -0
  206. data/spec/nuggets/object/singleton_class_spec.rb +51 -0
  207. data/spec/nuggets/proc/bind_spec.rb +28 -0
  208. data/spec/nuggets/range/quantile_spec.rb +33 -0
  209. data/spec/nuggets/string/camelscore_spec.rb +114 -0
  210. data/spec/nuggets/string/capitalize_first_spec.rb +13 -0
  211. data/spec/nuggets/string/case_spec.rb +31 -0
  212. data/spec/nuggets/string/evaluate_spec.rb +24 -0
  213. data/spec/nuggets/string/msub_spec.rb +20 -0
  214. data/spec/nuggets/string/nsub_spec.rb +13 -0
  215. data/spec/nuggets/string/sub_with_md_spec.rb +25 -0
  216. data/spec/nuggets/string/wc_spec.rb +73 -0
  217. data/spec/nuggets/string/word_wrap_spec.rb +81 -0
  218. data/spec/nuggets/string/xor_spec.rb +57 -0
  219. data/spec/nuggets/uri/content_type_spec.rb +42 -0
  220. data/spec/nuggets/uri/exist_spec.rb +49 -0
  221. data/spec/spec_helper.rb +36 -0
  222. metadata +309 -17
@@ -0,0 +1,5 @@
1
+ require 'nuggets/array/median_mixin'
2
+
3
+ class Array
4
+ include Nuggets::Array::MedianMixin
5
+ end
@@ -0,0 +1,73 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2011 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ module Nuggets
28
+ class Array
29
+ module MedianMixin
30
+
31
+ # call-seq:
32
+ # array.median([prefer]) => anObject
33
+ # array.median { |left, right| ... } => anObject
34
+ #
35
+ # Determines the median[http://en.wikipedia.org/wiki/Median] of the values
36
+ # in _array_. _array_ must be sortable.
37
+ #
38
+ # If _array_ contains an even number of values, a block may be passed to
39
+ # decide what the "middle" (average) should be. For Numeric values, the
40
+ # block is optional and the arithmetic mean will be used when no block
41
+ # is passed; for other values, the block is mandatory.
42
+ #
43
+ # Alternatively, +prefer+ may either be set to +true+, 1, or <tt>:left</tt>
44
+ # to use the left "middle", or to +false+, 2, or <tt>:right</tt> to use the
45
+ # right "middle". The block will then be ignored.
46
+ def median(prefer = nil)
47
+ return if empty?
48
+
49
+ sorted, index = sort, (size / 2.0).ceil - 1
50
+
51
+ case prefer
52
+ when true, 1, :left then prefer_left = true
53
+ when false, 2, :right then prefer_right = true
54
+ end
55
+
56
+ middle1 = sorted[index]
57
+ return middle1 if prefer_left || size.odd?
58
+
59
+ middle2 = sorted[index + 1]
60
+ return middle2 if prefer_right
61
+
62
+ unless block_given?
63
+ # simple arithmetic mean
64
+ (middle1 + middle2) / 2.0
65
+ else
66
+ # make your own average
67
+ yield middle1, middle2
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,5 @@
1
+ require 'nuggets/array/mode_mixin'
2
+
3
+ class Array
4
+ include Nuggets::Array::ModeMixin
5
+ end
@@ -0,0 +1,69 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2011 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ require 'nuggets/array/histogram_mixin'
28
+
29
+ module Nuggets
30
+ class Array
31
+ module ModeMixin
32
+
33
+ def self.included(base)
34
+ base.send :include, Nuggets::Array::HistogramMixin
35
+ end
36
+
37
+ # call-seq:
38
+ # array.mode => anObject
39
+ # array.mode(+true+) => anArray
40
+ #
41
+ # Returns the mode[http://en.wikipedia.org/wiki/Mode_%28statistics%29] of
42
+ # the values in _array_ (via #histogram).
43
+ #
44
+ # If parameter +true+ is passed, an Array of all modes is returned.
45
+ def mode(all = false, &block)
46
+ hist, modes = histogram(&block), []
47
+ freq = hist.values.max
48
+
49
+ hist.each { |key, value|
50
+ if value == freq
51
+ modes << key
52
+ break unless all
53
+ end
54
+ }
55
+
56
+ all ? modes : modes.first
57
+ end
58
+
59
+ # call-seq:
60
+ # array.modes => anArray
61
+ #
62
+ # Returns an Array of all modes of the values in _array_ (see #mode).
63
+ def modes(&block)
64
+ mode(true, &block)
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,83 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2011 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ class Array
28
+
29
+ # call-seq:
30
+ # array.monotone?(operator) => +true+ or +false+
31
+ #
32
+ # Check whether _array_ is monotone according to +operator+.
33
+ def monotone?(operator = nil)
34
+ if [nil, true, false].include?(operator)
35
+ ascending?(operator) || descending?(operator)
36
+ else
37
+ inject { |a, b|
38
+ return false unless a.send(operator, b)
39
+ b
40
+ }
41
+
42
+ true
43
+ end
44
+ end
45
+ alias_method :monotonic?, :monotone?
46
+
47
+ # call-seq:
48
+ # array.ascending? => +true+ or +false+
49
+ #
50
+ # Check whether _array_ is (strictly) ascending.
51
+ def ascending?(strict = false)
52
+ monotone?(strict ? :< : :<=)
53
+ end
54
+ alias_method :increasing?, :ascending?
55
+
56
+ # call-seq:
57
+ # array.strictly_ascending? => +true+ or +false+
58
+ #
59
+ # Check whether _array_ is strictly ascending.
60
+ def strictly_ascending?
61
+ ascending?(true)
62
+ end
63
+ alias_method :strictly_increasing?, :strictly_ascending?
64
+
65
+ # call-seq:
66
+ # array.descending? => +true+ or +false+
67
+ #
68
+ # Check whether _array_ is (strictly) descending.
69
+ def descending?(strict = false)
70
+ monotone?(strict ? :> : :>=)
71
+ end
72
+ alias_method :decreasing?, :descending?
73
+
74
+ # call-seq:
75
+ # array.strictly_descending? => +true+ or +false+
76
+ #
77
+ # Check whether _array_ is strictly descending.
78
+ def strictly_descending?
79
+ descending?(true)
80
+ end
81
+ alias_method :strictly_decreasing?, :strictly_descending?
82
+
83
+ end
@@ -0,0 +1,41 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2011 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ class Array
28
+
29
+ # call-seq:
30
+ # array.only => anObject
31
+ # array.only(+true+) => anObject
32
+ #
33
+ # Returns the only element of _array_. Raises an IndexError if _array_'s
34
+ # size is not 1, unless parameter +true+ is passed.
35
+ #
36
+ # Idea stolen from Gavin Sinclair's Ruby Extensions Project.
37
+ def only(relax = size == 1)
38
+ relax ? first : raise(::IndexError, 'not a single-element array')
39
+ end
40
+
41
+ end
@@ -0,0 +1,44 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2011 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ class Array
28
+
29
+ # call-seq:
30
+ # array.rand => anItem
31
+ #
32
+ # Randomly pick an item from _array_.
33
+ def rand
34
+ at(::Kernel.rand(size))
35
+ end
36
+
37
+ end
38
+
39
+ if $0 == __FILE__
40
+ a = %w[a b c d]
41
+ p a
42
+ p a.rand
43
+ p a.rand
44
+ end
@@ -0,0 +1,5 @@
1
+ require 'nuggets/array/regression_mixin'
2
+
3
+ class Array
4
+ include Nuggets::Array::RegressionMixin
5
+ end
@@ -0,0 +1,149 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # nuggets -- Extending Ruby #
5
+ # #
6
+ # Copyright (C) 2007-2012 Jens Wille #
7
+ # #
8
+ # Authors: #
9
+ # Jens Wille <jens.wille@gmail.com> #
10
+ # #
11
+ # nuggets is free software; you can redistribute it and/or modify it under #
12
+ # the terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # nuggets is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with nuggets. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
25
+ #++
26
+
27
+ module Nuggets
28
+ class Array
29
+ module RegressionMixin
30
+
31
+ # call-seq:
32
+ # array.linear_least_squares => anArray
33
+ #
34
+ # Calculates the {linear least squares regression}[http://en.wikipedia.org/wiki/Simple_linear_regression]
35
+ # for the <tt>{x,y}</tt> pairs in _array_. If _array_ only contains
36
+ # values instead of pairs, +y+ will be the value and +x+ will be each
37
+ # value's position (rank) in _array_.
38
+ def linear_least_squares
39
+ return [] if empty?
40
+
41
+ sx, sy, sq, sp, xys = 0.0, 0.0, 0.0, 0.0, first.respond_to?(:to_ary) ?
42
+ self : self.class.new(size) { |i| [i + 1, at(i)] }
43
+
44
+ xys.each { |x, y| sx += x; sy += y; sq += x ** 2; sp += x * y }
45
+
46
+ b = (v = sq * size - sx ** 2) == 0 ? 0 : (sp * size - sx * sy) / v
47
+ a = (sy - b * sx) / size
48
+
49
+ xys.map { |x, _| [x, a + b * x] }
50
+ end
51
+
52
+ alias_method :llsq, :linear_least_squares
53
+
54
+ # call-seq:
55
+ # array.linear_least_squares_incremental => anIncrementalLinearRegression
56
+ #
57
+ # Returns an instance of IncrementalLinearRegression for _array_; _array_
58
+ # being a list of values (in contrast to #linear_least_squares, which also
59
+ # accepts <tt>{x,y}</tt> pairs). Use IncrementalLinearRegression directly,
60
+ # or apply this method to an empty _array_, for more control over its input
61
+ # data.
62
+ def linear_least_squares_incremental
63
+ IncrementalLinearRegression.new(*self)
64
+ end
65
+
66
+ alias_method :llsqi, :linear_least_squares_incremental
67
+
68
+ # Inspired by {Incremental Simple Linear Regression in Ruby}[http://blog.codewren.ch/post/31378435699].
69
+ #
70
+ # Use #push to add a single <tt>{x,y}</tt> pair, #add to add a list of +y+
71
+ # values, and #<< to add a single +y+ value. Whenever a single +y+ value is
72
+ # added, it's associated with an +x+ value of its position (rank) in the
73
+ # data series.
74
+ #
75
+ # Call #to_a (or any Enumerable method) to work with the regression points.
76
+ class IncrementalLinearRegression
77
+
78
+ include ::Enumerable
79
+
80
+ def initialize(*ys)
81
+ clear
82
+ add(*ys)
83
+ end
84
+
85
+ def clear
86
+ @x = @y = @xx = @xy = 0.0
87
+ @cnt, @slope = 0, nil
88
+ self
89
+ end
90
+
91
+ def push(x, y)
92
+ cnt, @slope = @cnt += 1, nil
93
+
94
+ @x += (x - @x) / cnt
95
+ @y += (y - @y) / cnt
96
+ @xx += (x * x - @xx) / cnt
97
+ @xy += (x * y - @xy) / cnt
98
+
99
+ self
100
+ end
101
+
102
+ def add(*ys)
103
+ ys.each { |y| self << y }
104
+ self
105
+ end
106
+
107
+ def <<(y)
108
+ push(@cnt + 1, y)
109
+ end
110
+
111
+ def slope
112
+ @slope ||= @cnt < 2 ? 0 : (@xy - @x * @y) / (@xx - @x * @x)
113
+ end
114
+
115
+ def intercept
116
+ at(0)
117
+ end
118
+
119
+ def at(x)
120
+ @y + slope * (x - @x)
121
+ end
122
+
123
+ alias_method :[], :at
124
+
125
+ def each
126
+ @cnt.times { |i| yield [x = i + 1, at(x)] }
127
+ self
128
+ end
129
+
130
+ def to_a(range = nil)
131
+ range ? range.map { |x| [x, at(x)] } : super()
132
+ end
133
+
134
+ def to_s
135
+ s, i = slope, intercept
136
+
137
+ y = s == 0 ? i : begin
138
+ x = s.abs == 1 ? "#{'-' if s < 0}x" : "#{s} * x"
139
+ i == 0 ? x : "#{x} #{i < 0 ? '-' : '+'} #{i.abs}"
140
+ end
141
+
142
+ "y := #{y}".gsub(/\.0\b/, '')
143
+ end
144
+
145
+ end
146
+
147
+ end
148
+ end
149
+ end