Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 328 lines (288 sloc) 7.504 kB
74a3a62 @tardate added MyMath.rb
authored
1 class Integer
2
3 # @see project euler #15,20,34
4 def factorial
5 (2..self).inject(1) { |prod, n| prod * n }
6 end
7
8 # sum of digits in the number, expressed as a decimal
9 # @see project euler #16, 20
10 def sum_digits
11 self.to_s.split('').inject(0) { |memo, c| memo + c.to_i }
12 end
13
14 # num of digits in the number, expressed as a decimal
15 # @see project euler #25
16 def num_digits
17 self.to_s.length
18 end
19
20 # returns an array of all the base10 digit rotations of the number
21 # @see project euler #35
22 def rotations
23 self.to_s.rotations.collect { |s| s.to_i }
24 end
25
26 # tests if all the base10 digits in the number are odd
27 # @see project euler #35
28 def all_digits_odd?
29 self.to_s.split('').inject(0) { |memo, s| memo + ( s.to_i%2==0 ? 1 : 0 ) } == 0
30 end
31
32 # @see project euler #4, 36, 91
33 def palindrome?(base = 10)
34 case base
35 when 2
36 sprintf("%0b",self).palindrome?
37 else
38 self.to_s.palindrome?
39 end
40 end
41
42 # http://en.wikipedia.org/wiki/Prime_factor
43 # @see project euler #12
44 def prime_factors
45 primes = Array.new
46 d = 2
47 n = self
48 while n > 1
49 if n%d==0
50 primes << d
51 n/=d
52 else
53 d+=1
54 end
55 end
56 primes
57 end
58
59 # http://en.wikipedia.org/wiki/Divisor_function
60 # @see project euler #12
61 def divisor_count
62 primes = self.prime_factors
63 primes.uniq.inject(1) { |memo, p| memo * ( ( primes.find_all {|i| i == p} ).length + 1) }
64 end
65
66 #
67 # @see project euler #12, 21, 23
68 def divisors
69 d = Array.new
70 (1..self-1).each { |n| d << n if self % n == 0 }
71 d
72 end
73
74 # @see project euler #
75 def prime?
76 divisors.length == 1 # this is a brute force check
77 end
78
79 # prime series up to this limit, using Sieve of Eratosthenes method
80 # http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
81 # @see project euler #7, 10, 35
82 def prime_series
83 t = self
84 limit = Math.sqrt(t)
85 @a = (2..t).to_a
86 n = 2
87 while (n < limit) do
88 x = n*2
89 begin
90 @a[x-2]=2
91 x+=n
92 end until (x > t )
93 begin
94 n+=1
95 end until ( @a[n-2] != 2 )
96 end
97 @a.uniq!
98 end
99
100 # @see project euler #23
101 def perfect?
102 self == divisors.sum
103 end
104
105 # @see project euler #23
106 def deficient?
107 self > divisors.sum
108 end
109
110 # @see project euler #23
111 def abundant?
112 self < divisors.sum
113 end
114
115 # http://en.wikipedia.org/wiki/Collatz_conjecture
116 # @see project euler #14
117 def collatz_series
118 @a = Array.new
119 @a << n = self
120 while n > 1
121 if n % 2 == 0
122 n /= 2
123 else
124 n = 3*n + 1
125 end
126 @a << n
127 end
128 @a
129 end
130
131 # express integer as an english phrase
132 # @see project euler #17
133 def speak
134 case
135 when self <20
136 ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
137 "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" ][self]
138 when self > 19 && self < 100
139 a = ["twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"][self / 10 - 2]
140 r = self % 10
141 if r == 0
142 a
143 else
144 a + "-" + r.speak
145 end
146 when self > 99 && self < 1000
147 a = (self / 100).speak + " hundred"
148 r = self % 100
149 if r == 0
150 a
151 else
152 a + " and " + r.speak
153 end
154 when self > 999 && self < 10000
155 a = (self / 1000).speak + " thousand"
156 r = self % 1000
157 if r == 0
158 a
159 else
160 a + ( r <100 ? " and " : " " ) + r.speak
161 end
162 else
163 self
164 end
165 end
166
167 # generates triangle number for this integer
168 # @see project euler #42
169 def triangle
170 self * ( self + 1 ) / 2
171 end
172
173 # calculates integer partitions for given number using array of elements
174 # http://en.wikipedia.org/wiki/Integer_partition
175 # @see project euler #31
176 def integer_partitions(pArray, p=0)
177 if p==pArray.length-1
178 1
179 else
180 self >= 0 ? (self - pArray[p]).integer_partitions(pArray ,p) + self.integer_partitions(pArray,p+1) : 0
181 end
182 end
183
184 end
185
186 class Array
187
188 # sum elements in the array
189 def sum
190 self.inject(0) { |sum, n| sum + n }
191 end
192
193 # sum of squares for elements in the array
194 # @see project euler #6
195 def sum_of_squares
196 self.inject(0) { |sos, n| sos + n**2 }
197 end
198
199 # @see project euler #17
200 def square_of_sum
201 ( self.inject(0) { |sum, n| sum + n } ) ** 2
202 end
203
204 # index of the smallest item in the array
205 def index_of_smallest
206 value, index = self.first, 0
207 self.each_with_index {| obj, i | value, index = obj, i if obj<value }
208 index
209 end
210
211 # removes numbers from the array that are factors of other elements in the array
212 # @see project euler #5
213 def remove_factors
214 @a=Array.new
215 self.each do | x |
216 @a << x if 0 == ( self.inject(0) { | memo, y | memo + (x!=y && y%x==0 ? 1 : 0) } )
217 end
218 @a
219 end
220
221 # http://utilitymill.com/edit/GCF_and_LCM_Calculator
222 # @see project euler #5
223 def GCF
224 t_val = self[0]
225 for cnt in 0...self.length-1
226 num1 = t_val
227 num2 = self[cnt+1]
228 num1,num2=num2,num1 if num1 < num2
229 while num1 - num2 > 0
230 num3 = num1 - num2
231 num1 = [num2,num3].max
232 num2 = [num2,num3].min
233 end
234 t_val = num1
235 end
236 t_val
237 end
238
239 # http://utilitymill.com/edit/GCF_and_LCM_Calculator
240 # @see project euler #5
241 def LCM
242 a=self.remove_factors
243 t_val = a[0]
244 for cnt in 0...a.length-1
245 num1 = t_val
246 num2 = a[cnt+1]
247 tmp = [num1,num2].GCF
248 t_val = tmp * num1/tmp * num2/tmp
249 end
250 t_val
251 end
252
253 # brute force method:
254 # http://www.cut-the-knot.org/Curriculum/Arithmetic/LCM.shtml
255 # @see project euler #5
256 def lcm2
257 a=self.remove_factors
258 c=a.dup
259 while c.uniq.length>1
260 index = c.index_of_smallest
261 c[index]+=a[index]
262 end
263 c.first
264 end
265
266 # returns the kth Lexicographical permutation of the elements in the array
267 # http://en.wikipedia.org/wiki/Permutation#Lexicographical_order_generation
268 # @see project euler #24
269 def lexicographic_permutation(k)
270 k -= 1
271 @s = self.dup
272 n = @s.length
273 n_less_1_factorial = (n - 1).factorial # compute (n - 1)!
274
275 (1..n-1).each do |j|
276 tempj = (k / n_less_1_factorial) % (n + 1 - j)
277
278 @s[j-1..j+tempj-1]=@s[j+tempj-1,1]+@s[j-1..j+tempj-2] unless tempj==0
279 n_less_1_factorial = n_less_1_factorial / (n- j)
280 end
281 @s
282 end
283
284 # returns ordered array of all the lexicographic permutations of the elements in the array
285 # http://en.wikipedia.org/wiki/Permutation#Lexicographical_order_generation
286 # @see project euler #24
287 def lexicographic_permutations
288 @a=Array.new
289 (1..self.length.factorial).each { |i| @a << self.lexicographic_permutation(i) }
290 @a
291 end
292
293 end
294
295 class String
296
297 # sum of digits in the number
298 # @see project euler #16, 20
299 def sum_digits
300 self.split('').inject(0) { |memo, c| memo + c.to_i }
301 end
302
303 # product of digits in the number
304 # @see project euler #8
305 def product_digits
306 self.split('').inject(1) { |memo, c| memo * c.to_i }
307 end
308
309 #
310 # @see project euler #4, 36, 91
311 def palindrome?
312 self==self.reverse
313 end
314
315 # returns an array of all the character rotations of the string
316 # @see project euler #35
317 def rotations
318 s = self
319 @rotations = Array[s]
320 (1..s.length-1).each do |i|
321 s=s[1..s.length-1]+s[0,1]
322 @rotations << s
323 end
324 @rotations
325 end
326
327 end
Something went wrong with that request. Please try again.