Commit 13559f9
Changed files (1)
spec
euler
spec/euler/problem_12_spec.rb
@@ -0,0 +1,108 @@
+require 'spec_helper'
+require 'prime'
+=begin
+The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:
+
+1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
+
+Let us list the factors of the first seven triangle numbers:
+
+ 1: 1
+ 3: 1,3
+ 6: 1,2,3,6
+10: 1,2,5,10
+15: 1,3,5,15
+21: 1,3,7,21
+28: 1,2,4,7,14,28
+We can see that 28 is the first triangle number to have over five divisors.
+
+What is the value of the first triangle number to have over five hundred divisors?
+
+help:
+* http://www.wikihow.com/Determine-the-Number-of-Divisors-of-an-Integer
+* https://www.khanacademy.org/math/pre-algebra/factors-multiples/prime_factorization/v/prime-factorization
+=end
+
+class TriangleNumbers
+ include Enumerable
+
+ def each(&block)
+ n = 1
+ loop do
+ block.call(sum_of(n))
+ n += 1
+ end
+ end
+
+ private
+
+ def sum_of(n)
+ n.downto(0).inject(0) { |total, m| total += m }
+ end
+
+end
+
+describe 'problem 12' do
+ describe TriangleNumbers do
+ it 'produces the first 7 triangle numbers' do
+ expect(subject.take(7)).to eql([1, 3, 6, 10, 15, 21, 28])
+ end
+
+ it 'produces the first 10 triangle numbers' do
+ expect(subject.take(10)).to eql([1, 3, 6, 10, 15, 21, 28, 36, 45, 55])
+ end
+ end
+
+ class Divisors
+ def divisors_for(n)
+ 1.upto(n).find_all do |x|
+ (n % x).zero?
+ end
+ end
+
+ def number_of_divisors_for(n)
+ prime_factors = n.prime_division
+ powers_plus_one = prime_factors.map do |(prime, exponent)|
+ exponent + 1
+ end
+ powers_plus_one.inject(1) { |total, power| total *= power }
+ end
+ end
+
+ describe Divisors do
+ it 'returns each factor for a number' do
+ {
+ 1 => [1],
+ 2 => [1, 2],
+ 3 => [1,3],
+ 4 => [1,2,4],
+ 5 => [1, 5],
+ 6 => [1,2,3,6],
+ 7 => [1, 7],
+ 8 => [1, 2, 4, 8],
+ 9 => [1, 3, 9],
+ 10 => [1,2,5,10],
+ 11 => [1, 11],
+ 12 => [1, 2, 3, 4, 6, 12],
+ 13 => [1, 13],
+ 14 => [1, 2, 7, 14],
+ 15 => [1,3,5,15],
+ 16 => [1, 2, 4, 8, 16],
+ 21 => [1,3,7,21],
+ 24 => [1, 2, 3, 4, 6, 8, 12, 24],
+ 28 => [1, 2, 4, 7, 14, 28],
+ }.each do |key, values|
+ expect(subject.divisors_for(key)).to eql(values)
+ end
+ end
+
+ it 'brute forces the answer' do
+ subject = TriangleNumbers.new
+ divisors = Divisors.new
+ result = subject.find do |n|
+ divisors.number_of_divisors_for(n) >= 500
+ end
+ expect(result).to eql(76576500)
+ end
+ end
+end