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.
- data/.travis.yml +6 -8
- data/CHANGELOG.md +33 -5
- data/Gemfile +7 -7
- data/LICENSE.txt +1 -1
- data/README.md +15 -9
- data/VERSION +1 -1
- data/lib/magician/array.rb +133 -92
- data/lib/magician/integer.rb +44 -50
- data/lib/magician/math.rb +167 -116
- data/lib/magician/numeric.rb +38 -26
- data/lib/magician/random.rb +31 -0
- data/lib/magician/shortcuts.rb +5 -2
- data/lib/magician/string.rb +7 -7
- data/magician.gemspec +20 -18
- data/spec/array_spec.rb +87 -70
- data/spec/integer_spec.rb +44 -30
- data/spec/math_spec.rb +90 -72
- data/spec/numeric_spec.rb +36 -18
- data/spec/random_spec.rb +21 -0
- data/spec/shortcuts_spec.rb +7 -5
- data/spec/spec_helper.rb +2 -0
- data/spec/string_spec.rb +10 -9
- metadata +20 -18
data/.travis.yml
CHANGED
@@ -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
|
-
|
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
|
data/CHANGELOG.md
CHANGED
@@ -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
|
-
|
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
|
-
|
10
|
-
|
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
|
-
|
16
|
-
|
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
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,15 @@
|
|
1
|
-
# magician [](http://travis-ci.org/thenickperson/magician) [](https://gemnasium.com/thenickperson/magician) [](http://badge.fury.io/rb/magician) [](http://travis-ci.org/thenickperson/magician) [](https://gemnasium.com/thenickperson/magician) [](https://codeclimate.com/github/thenickperson/magician)
|
2
2
|
|
3
3
|
A suite of handy methods for doing calculations in irb.
|
4
4
|
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
53
|
+
future version unintentionally.
|
48
54
|
- Please try not to mess with the Rakefile, version, or history. If you want to
|
49
|
-
|
50
|
-
|
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)
|
59
|
+
Copyright (c) 2013 Nicolas McCurdy. See LICENSE.txt for further details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/magician/array.rb
CHANGED
@@ -1,97 +1,138 @@
|
|
1
1
|
# Magician's extensions to the Array class.
|
2
2
|
class Array
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
data/lib/magician/integer.rb
CHANGED
@@ -1,55 +1,49 @@
|
|
1
1
|
# Magician's extensions to the Integer class.
|
2
2
|
class Integer
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|