magician 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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