magician 0.2.1 → 0.3.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.
@@ -1,8 +1,6 @@
1
- language: ruby
2
- rvm:
3
- - 1.9.3
4
- - jruby-19mode # JRuby in 1.9 mode
5
- - rbx-19mode # Rubinius in 1.9 mode
6
- branches:
7
- only:
8
- - master
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-19mode # JRuby in 1.9 mode
5
+ - rbx-19mode # Rubinius in 1.9 mode
6
+ - 2.0
@@ -1,19 +1,47 @@
1
+ ## 0.3.0
2
+ - Features
3
+ - Add Math.primes, which implements a fast prime sieve
4
+ - Add Array#numerics, which finds all Numerics in an Array
5
+ - Add Array#middle, an unsorted version of Array#median
6
+ - Add Numeric#to_radians and Numeric#to_degrees for conversion
7
+ - Add #boolean, #coin, and #die class/instance methods to the Random class
8
+ - Add an alias for Complex::I
9
+ - Changes
10
+ - If an Array method that uses Numerics is called on an Array with non-Numeric
11
+ objects, magician will raise a RuntimeError instead of filtering out
12
+ non-Numeric objects without warning
13
+ - Methods will now tend to prefer raising descriptive errors over returning
14
+ nil without warning
15
+ - Support making Math.fibs start with any set of two or more terms
16
+ - Simplify and clean up some of the source code
17
+ - Fixes
18
+ - Fix several issues with Integer#pandigital?
19
+ - Update the changelog to include changes in previous version 0.2.1
20
+
21
+ ## 0.2.1
22
+ - Fix an issue with Array#median giving inaccurate results (it wasn't sorting
23
+ the list)
24
+ - Performance improvements
25
+ - Add Integer#pandigital?
26
+ - Deprecate Numeric#digits
27
+ - Add a shortcut for the golden ratio
28
+
1
29
  ## 0.2.0
2
30
  - Create this changelog
3
31
  - Add examples to the readme, along with a link to magician's docs
4
32
  - Minor code style improvements
5
33
  - Move the divisible? instance method from Integer to Numeric so it can be used
6
- on more types of numbers
34
+ on more types of numbers
7
35
  - New Array#numerics instance method
8
36
  - Several of Array's instance methods will now intelligently filter out
9
- non-numbers so that these methods can be used with arrays that don't just
10
- contain Numeric objects
37
+ non-numbers so that these methods can be used with arrays that don't just
38
+ contain Numeric objects
11
39
 
12
40
  ## 0.1.1
13
41
  - Minor code style improvements
14
42
  - Improved documentation
15
- - Fix spelling errors
16
- - Document all nil returns
43
+ - Fix spelling errors
44
+ - Document all nil returns
17
45
 
18
46
  ## 0.1.0
19
47
  - Initial release
data/Gemfile CHANGED
@@ -1,14 +1,14 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Add dependencies required to use your gem here.
4
4
 
5
5
  # Add dependencies to develop your gem here.
6
6
  # Include everything needed to run rake, tests, features, etc.
7
7
  group :development do
8
- gem 'rspec', '~> 2.12.0'
9
- gem 'yard', '~> 0.7'
10
- gem 'rdoc', '~> 3.12'
11
- gem 'bundler'
12
- gem 'jeweler', '~> 1.8.4'
13
- gem 'simplecov'
8
+ gem 'rspec', '~> 2.13'
9
+ gem 'yard', '~> 0.7'
10
+ gem 'rdoc', '~> 4.0'
11
+ gem 'bundler', '~> 1.2'
12
+ gem 'jeweler', '~> 1.8'
13
+ gem 'simplecov', '~> 0.7'
14
14
  end
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 Nicolas McCurdy
1
+ Copyright (c) 2013 Nicolas McCurdy
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,9 +1,15 @@
1
- # magician [![Build Status](https://secure.travis-ci.org/thenickperson/magician.png?branch=master)](http://travis-ci.org/thenickperson/magician) [![Dependency Status](https://gemnasium.com/thenickperson/magician.png)](https://gemnasium.com/thenickperson/magician) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/thenickperson/magician)
1
+ # magician [![Gem Version](https://badge.fury.io/rb/magician.png)](http://badge.fury.io/rb/magician) [![Build Status](https://secure.travis-ci.org/thenickperson/magician.png?branch=master)](http://travis-ci.org/thenickperson/magician) [![Dependency Status](https://gemnasium.com/thenickperson/magician.png)](https://gemnasium.com/thenickperson/magician) [![Code Climate](https://codeclimate.com/github/thenickperson/magician.png)](https://codeclimate.com/github/thenickperson/magician)
2
2
 
3
3
  A suite of handy methods for doing calculations in irb.
4
4
 
5
- For detailed documentation, see
6
- [magician on RubyDoc.info](http://rubydoc.info/github/thenickperson/magician/frames).
5
+ ## [Documentation](http://rubydoc.info/github/thenickperson/magician/frames)
6
+
7
+ ## A note on Ruby 2.0 support
8
+ With the latest release of magician, all tests pass on Ruby 1.9 and 2.0.
9
+ However, magician depends on jeweler to work, which unfortunately does not seem
10
+ to be compatible with Ruby 2.0 yet. As a result, magician will most likely not
11
+ work on Ruby 2.0 at this point. If you come up with any fixes for this, please
12
+ feel free to send me a pull request.
7
13
 
8
14
  ## Examples
9
15
  ```ruby
@@ -37,17 +43,17 @@ For detailed documentation, see
37
43
 
38
44
  ## Contributing to magician
39
45
  - Check out the latest master to make sure the feature hasn't been implemented
40
- or the bug hasn't been fixed yet.
46
+ or the bug hasn't been fixed yet.
41
47
  - Check out the issue tracker to make sure someone already hasn't requested it
42
- and/or contributed it.
48
+ and/or contributed it.
43
49
  - Fork the project.
44
50
  - Start a feature/bugfix branch.
45
51
  - Commit and push until you are happy with your contribution.
46
52
  - Make sure to add tests for it. This is important so I don't break it in a
47
- future version unintentionally.
53
+ future version unintentionally.
48
54
  - Please try not to mess with the Rakefile, version, or history. If you want to
49
- have your own version, or is otherwise necessary, that is fine, but please
50
- isolate to its own commit so I can cherry-pick around it.
55
+ have your own version, or is otherwise necessary, that is fine, but please
56
+ isolate to its own commit so I can cherry-pick around it.
51
57
 
52
58
  ## Copyright
53
- Copyright (c) 2012 Nicolas McCurdy. See LICENSE.txt for further details.
59
+ Copyright (c) 2013 Nicolas McCurdy. See LICENSE.txt for further details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
@@ -1,97 +1,138 @@
1
1
  # Magician's extensions to the Array class.
2
2
  class Array
3
3
 
4
- # Returns all numbers from the array, in order. This is done by choosing all
5
- # objects from the array that are instances of Numeric or one of its
6
- # subclasses.
7
- #
8
- # @return [Array] a new array containing only Numerics
9
- def numerics
10
- select { |item| item.class <= Numeric }
11
- end
12
-
13
- # Gets the sum of the numbers in the array. The sum of an array with no
14
- # numbers is 0.
15
- #
16
- # @return [Numeric] the sum of the numbers in the array
17
- def sum
18
- nums = numerics
19
- return 0 if nums.empty?
20
- nums.inject(:+)
21
- end
22
-
23
- # Gets the product of the numbers in the array. The product of an array with
24
- # no numbers is 1.
25
- #
26
- # @return [Numeric] the product of the numbers in the array
27
- def product
28
- nums = numerics
29
- return 1 if nums.empty?
30
- nums.inject(:*)
31
- end
32
-
33
- # Gets the range of the numbers in the array (maximum - minimum). The range of
34
- # an array with no numbers is nil.
35
- #
36
- # @return [Numeric] the range of the numbers in the array
37
- def range
38
- nums = numerics
39
- return nil if nums.empty?
40
- nums.max - nums.min
41
- end
42
-
43
- # Gets the mean (average) of the numbers in the array. The mean of an array
44
- # with no numbers is nil.
45
- #
46
- # @return [Float] the mean (average) of the numbers in the array
47
- def mean
48
- nums = numerics
49
- return nil if nums.empty?
50
- nums.sum.to_f / nums.size
51
- end
52
-
53
- # Gets the median of the numbers in the array (the value in the middle of a
54
- # sorted version of the array, numbers only). If the array has an even number
55
- # of numbers, the middle two numbers will be averaged. The median of an array
56
- # with no numbers is nil.
57
- #
58
- # @return [Numeric] the median of the numbers in the array
59
- def median
60
- sorted = numerics.sort
61
- return nil if sorted.empty?
62
- if sorted.length.odd?
63
- sorted[sorted.length/2]
64
- else
65
- (sorted[sorted.length/2-1] + sorted[sorted.length/2]) / 2.0
66
- end
67
- end
68
-
69
- # Gets the mode(s) of the items in the array (the item(s) that occur(s) most
70
- # frequently). The mode of an empty array is nil.
71
- #
72
- # @return [Array] an array of all of the items in the array that occur the
73
- # most frequently (they must all have the same number of occurrences)
74
- def mode
75
- return nil if empty?
76
- occ = occurences
77
- max_occ = occ.values.max
78
- occ.select { |key, value| value == max_occ }.keys
79
- end
80
-
81
- # Gets a hash table with the number of occurrences of each item from the
82
- # original array. The keys are the items from the original array, and the
83
- # values are integers counting the number of occurrences of the associated key
84
- # values.
85
- #
86
- # @return [Hash] a hash table of the occurrences of each item from the original
87
- # array
88
- def occurences
89
- occurences = Hash.new(0)
90
- each { |item| occurences[item] += 1 }
91
- occurences
92
- end
93
-
94
- # Alias average to mean.
95
- alias :average :mean
4
+ # Returns all numbers from the array, in order. This is done by choosing all
5
+ # objects from the array that are instances of Numeric or one of its
6
+ # subclasses.
7
+ #
8
+ # @return [Array] a new array containing only Numerics
9
+ def numerics
10
+ select { |item| item.class <= Numeric }
11
+ end
12
+
13
+ # Gets the sum of the array elements. The sum of an empty array is 0. The
14
+ # array must only contain Numerics or a RuntimeError will be raised.
15
+ #
16
+ # @return [Numeric] the sum of the elements of the array
17
+ #
18
+ # @raise [RuntimeError] if the Array contains non-Numeric objects
19
+ def sum
20
+ require_numerics
21
+
22
+ empty? ? 0 : reduce(:+)
23
+ end
24
+
25
+ # Gets the product of the array elements. The product of an empty array is 1.
26
+ # The array must only contain Numerics or a RuntimeError will be raised.
27
+ #
28
+ # @return [Numeric] the product of the elements of the array
29
+ #
30
+ # @raise [RuntimeError] if the Array contains non-Numeric objects
31
+ def product
32
+ require_numerics
33
+
34
+ empty? ? 1 : reduce(:*)
35
+ end
36
+
37
+ # Finds the middle element of the array. If the array has an even number of
38
+ # elements, the middle two elements will be averaged. The middle of an empty
39
+ # array is nil. The array must only contain Numerics or a RuntimeError will be
40
+ # raised.
41
+ #
42
+ # @return [Numeric, nil] the middle of the elements of the array
43
+ #
44
+ # @raise [RuntimeError] if the Array contains non-Numeric objects
45
+ def middle
46
+ require_numerics
47
+ return nil if empty?
48
+
49
+ middle_index = length / 2
50
+ length.odd? ? slice(middle_index) : [slice(middle_index-1), slice(middle_index)].mean
51
+ end
52
+
53
+ # Gets the range of the elements of the array (maximum - minimum). The range
54
+ # of an empty array is nil. The array must only contain Numerics or a
55
+ # RuntimeError will be raised.
56
+ #
57
+ # @return [Numeric, nil] the range of the elements of the array
58
+ #
59
+ # @raise [RuntimeError] if the Array contains non-Numeric objects
60
+ def range
61
+ require_numerics
62
+
63
+ empty? ? nil : max - min
64
+ end
65
+
66
+ # Gets the mean (average) of the elements of the array. The mean of an empty
67
+ # array is nil. The array must only contain Numerics or a RuntimeError will be
68
+ # raised.
69
+ #
70
+ # @return [Float, nil] the mean (average) of the elements of the array
71
+ #
72
+ # @raise [RuntimeError] if the Array contains non-Numeric objects
73
+ def mean
74
+ require_numerics
75
+
76
+ empty? ? nil : sum.to_f / length
77
+ end
78
+
79
+ # Sorts the array and finds the element in the middle. The exact same
80
+ # functionality can be achieved by sorting the array and then running the
81
+ # middle method on it. The array must only contain Numerics or a RuntimeError
82
+ # will be raised.
83
+ #
84
+ # @see middle
85
+ #
86
+ # @return [Numeric, nil] the median of the elements of the array
87
+ #
88
+ # @raise [RuntimeError] if the Array contains non-Numeric objects
89
+ def median
90
+ require_numerics
91
+
92
+ sort.middle
93
+ end
94
+
95
+ # Gets the mode(s) of the items in the array (the item(s) that occur(s) most
96
+ # frequently). The mode of an empty array is nil.
97
+ #
98
+ # @return [Array, nil] an array of all of the items in the array that occur
99
+ # the most frequently (they must all have the same number of occurrences)
100
+ def mode
101
+ return nil if empty?
102
+
103
+ occ = occurences
104
+ max_occ = occ.values.max
105
+
106
+ occ.select { |key, value| value == max_occ }.keys
107
+ end
108
+
109
+ # Gets a hash table with the number of occurrences of each item from the
110
+ # original array. The keys are the items from the original array, and the
111
+ # values are integers counting the number of occurrences of the associated key
112
+ # values.
113
+ #
114
+ # @return [Hash] a hash table of the occurrences of each item from the original
115
+ # array
116
+ def occurences
117
+ occurences = Hash.new 0
118
+ each { |item| occurences[item] += 1 }
119
+ occurences
120
+ end
121
+
122
+ # Alias average to mean.
123
+ alias :average :mean
124
+
125
+ private
126
+
127
+ # Requires that all objects in the Array are instances of Numeric (or one of
128
+ # its subclasses), and raises an error if they are not.
129
+ #
130
+ # @raise [RuntimeError] if the Array contains non-Numeric objects
131
+ def require_numerics
132
+ unless all? { |item| item.class <= Numeric }
133
+ calling_method = caller[0][/`.*'/][1..-2]
134
+ raise RuntimeError, "Array##{calling_method} requires that the Array only contains Numeric objects."
135
+ end
136
+ end
96
137
 
97
138
  end
@@ -1,55 +1,49 @@
1
1
  # Magician's extensions to the Integer class.
2
2
  class Integer
3
3
 
4
- # Gets all of the factors of the current integer. If the current integer is
5
- # negative, it will be treated as if it were positive (so the results will
6
- # never contain negative integers). Returns nil if the integer is 0.
7
- #
8
- # @return [Array] an array of all of the factors of the current integer (in
9
- # order, including 1 and the integer itself)
10
- def factors
11
- return nil if self == 0
12
- return [1] if abs == 1
13
- #first half
14
- factors = [1]
15
- 2.upto((abs/2).to_i) do |i|
16
- if abs%i == 0
17
- factors << i
18
- end
19
- end
20
- factors << abs
21
- end
22
-
23
- # Gets the factorial of the integer, which is equivalent to the product of all
24
- # integers from 1 to the integer (inclusive). When the integer is 0, it is
25
- # equivalent to 1.
26
- #
27
- # @return [Integer] factorial of the integer
28
- def factorial
29
- return 1 if self == 0
30
- (1..self).inject(:*)
31
- end
32
-
33
- # Returns true if the integer is prime (that is, if it is not divisible by any
34
- # integer between 1 and the integer itself, exclusive). 0 and 1 are not prime
35
- # numbers, though 2 is prime. Negative numbers are never considered prime in
36
- # this implementation.
37
- #
38
- # @return [Boolean] true if the integer is prime
39
- def prime?
40
- return false if self <= 1
41
- (2..Math.sqrt(self)).each do |i|
42
- return false if self % i == 0
43
- end
44
- true
45
- end
46
-
47
- # Returns true if the number is pandigital. That is the number contains the
48
- # each of the digits 1 through 9 exactly once.
49
- #
50
- # @return [Boolean] true if pandigital
51
- def pandigital?
52
- to_s.split(//).sort!.join.to_i == 123456789
53
- end
4
+ # Gets all of the factors of the current integer. If the current integer is
5
+ # negative, it will be treated as if it were positive (so the results will
6
+ # never contain negative integers).
7
+ #
8
+ # @return [Array] an array of all of the factors of the current integer (in
9
+ # order, including 1 and the integer itself)
10
+ #
11
+ # @raise [ArgumentError] if the integer is 0, since 0 has infinite factors
12
+ def factors
13
+ raise ArgumentError, '0 has infinite factors, so the Array of its factors cannot be computed in finite time' if zero?
14
+
15
+ 1.upto(abs/2).select { |i| abs % i == 0 } << abs
16
+ end
17
+
18
+ # Gets the factorial of the integer, which is equivalent to the product of all
19
+ # integers from 1 to the integer (inclusive). When the integer is 0, it is
20
+ # equivalent to 1.
21
+ #
22
+ # @return [Integer] factorial of the integer
23
+ def factorial
24
+ return 1 if zero?
25
+
26
+ downto(1).reduce :*
27
+ end
28
+
29
+ # Returns true if the integer is prime (that is, if it is not divisible by any
30
+ # integer between 1 and the integer itself, exclusive). 0 and 1 are not prime
31
+ # numbers, though 2 is prime. Negative numbers are never considered prime in
32
+ # this implementation.
33
+ #
34
+ # @return [Boolean] true if the integer is prime
35
+ def prime?
36
+ return false if self <= 1
37
+
38
+ not 2.upto(Math.sqrt self).any? { |i| modulo(i) == 0 }
39
+ end
40
+
41
+ # Returns true if the integer is pandigital. That is, the integer contains
42
+ # each of the digits from 1 to 9 exactly once.
43
+ #
44
+ # @return [Boolean] true if the integer is pandigital
45
+ def pandigital?
46
+ to_s.split(//).sort.join == '123456789'
47
+ end
54
48
 
55
49
  end