restructuring solutions for spec usage
							parent
							
								
									eb21d847e1
								
							
						
					
					
						commit
						251fb30d67
					
				
							
								
								
									
										102
									
								
								crystal/euler.cr
								
								
								
								
							
							
						
						
									
										102
									
								
								crystal/euler.cr
								
								
								
								
							|  | @ -3,57 +3,79 @@ | ||||||
| require "big" | require "big" | ||||||
| 
 | 
 | ||||||
| module Euler | module Euler | ||||||
|   alias NumType = Int32 | Int64 | UInt32 | UInt64 | BigInt |   extend self | ||||||
| 
 | 
 | ||||||
|   def self.trial_division(n : NumType) |   alias NumType = Int32 | Int64 | UInt32 | UInt64 | ||||||
|     factors = [] of NumType | 
 | ||||||
|     check = ->(p: NumType) { |   macro trial_division_method(given_type) | ||||||
|       q, r = n.divmod(p) |     def trial_division(n : {{given_type}}) | ||||||
|       while r.zero? |       factors = [] of {{given_type}} | ||||||
|         factors << p |       check = ->(p: {{given_type}}) { | ||||||
|         n = q |  | ||||||
|         q, r = n.divmod(p) |         q, r = n.divmod(p) | ||||||
|       end |         while r.zero? | ||||||
|     } |           factors << p | ||||||
|  |           n = q | ||||||
|  |           q, r = n.divmod(p) | ||||||
|  |         end | ||||||
|  |       } | ||||||
| 
 | 
 | ||||||
|     check.call(2) |       check.call(2) | ||||||
|     check.call(3) |       check.call(3) | ||||||
|     p = 5 |       p = 5 | ||||||
|     while p * p <= n |       while p * p <= n | ||||||
|       check.call(p) |         check.call(p) | ||||||
|       p += 2 |         p += 2 | ||||||
|       check.call(p) |         check.call(p) | ||||||
|       p += 4 |         p += 4 | ||||||
|  |       end | ||||||
|  |       factors << n if n > 1 | ||||||
|  |       factors | ||||||
|     end |     end | ||||||
|     factors << n if n > 1 |  | ||||||
|     factors |  | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def self.prime_factorization(n : NumType) |   macro prime_factorization_method(given_type) | ||||||
|     result = {} of NumType => NumType |     def prime_factorization(n : {{given_type}}) | ||||||
|     factors = self.trial_division(n) |       result = {} of {{given_type}} => Int32 | ||||||
|  |       factors = self.trial_division(n) | ||||||
| 
 | 
 | ||||||
|     factors.each do |f| |       factors.each do |f| | ||||||
|       result[f] = 0 |         result[f] = 0 | ||||||
|       num = n |         num = n | ||||||
|       while num % f == 0 |         while num % f == 0 | ||||||
|         result[f] += 1 |           result[f] += 1 | ||||||
|         num /= f |           num /= f | ||||||
|  |         end | ||||||
|       end |       end | ||||||
|     end |  | ||||||
| 
 | 
 | ||||||
|     result |       result | ||||||
|  |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def self.palindrome?(x) |   macro to_digit_list_method(given_type) | ||||||
|  |     def to_digit_list(n : {{given_type}}) | ||||||
|  |       n.to_s.chars.map { |d| d.to_i } | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   macro to_big_ints_method(given_type) | ||||||
|  |     def to_big_ints(num_list : Array({{given_type}})) | ||||||
|  |       num_list.map { |n| BigInt.new(n) } | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   trial_division_method(NumType) | ||||||
|  |   trial_division_method(BigInt) | ||||||
|  | 
 | ||||||
|  |   prime_factorization_method(NumType) | ||||||
|  |   prime_factorization_method(BigInt) | ||||||
|  | 
 | ||||||
|  |   to_digit_list_method(NumType) | ||||||
|  |   to_digit_list_method(BigInt) | ||||||
|  | 
 | ||||||
|  |   to_big_ints_method(NumType) | ||||||
|  |   to_big_ints_method(BigInt) | ||||||
|  | 
 | ||||||
|  |   def palindrome?(x) | ||||||
|     x.to_s.reverse == x.to_s |     x.to_s.reverse == x.to_s | ||||||
|   end |   end | ||||||
| 
 |  | ||||||
|   def self.to_digit_list(n : NumType) |  | ||||||
|     n.to_s.chars.map { |d| d.to_i } |  | ||||||
|   end |  | ||||||
| 
 |  | ||||||
|   def self.to_big_ints(num_list : Array(NumType)) |  | ||||||
|     num_list.map { |n| BigInt.new(n) } |  | ||||||
|   end |  | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1 +1,9 @@ | ||||||
| puts (1..999).select { |n| (n % 3 == 0) || (n % 5 == 0) }.sum | module Euler | ||||||
|  |   module Problem001 | ||||||
|  |     extend self | ||||||
|  | 
 | ||||||
|  |     def solution | ||||||
|  |       (1..999).select { |n| (n % 3 == 0) || (n % 5 == 0) }.sum | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | @ -1,18 +1,26 @@ | ||||||
| def fibonacci_nums_up_to(n) | module Euler | ||||||
|   result = [1] of Int32 |   module Problem002 | ||||||
|  |     extend self | ||||||
| 
 | 
 | ||||||
|   a = 1 |     def fibonacci_nums_up_to(n) | ||||||
|   b = 2 |       result = [1] of Int32 | ||||||
|   accum = 0 |  | ||||||
| 
 | 
 | ||||||
|   while accum < n |       a = 1 | ||||||
|     accum = a + b |       b = 2 | ||||||
|     result << b |       accum = 0 | ||||||
|     a = b | 
 | ||||||
|     b = accum |       while accum < n | ||||||
|  |         accum = a + b | ||||||
|  |         result << b | ||||||
|  |         a = b | ||||||
|  |         b = accum | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       result | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def solution | ||||||
|  |       fibonacci_nums_up_to(4000000).select{ |n| n.even? }.sum | ||||||
|  |     end | ||||||
|   end |   end | ||||||
| 
 |  | ||||||
|   result |  | ||||||
| end | end | ||||||
| 
 |  | ||||||
| puts fibonacci_nums_up_to(4000000).select{ |n| n.even? }.sum |  | ||||||
|  |  | ||||||
|  | @ -1,3 +1,11 @@ | ||||||
| require "./euler" | require "./euler" | ||||||
| 
 | 
 | ||||||
| puts Euler.trial_division(600851475143).max | module Euler | ||||||
|  |   module Problem003 | ||||||
|  |     extend self | ||||||
|  | 
 | ||||||
|  |     def solution | ||||||
|  |       Euler.trial_division(600851475143).max | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | @ -1,7 +1,15 @@ | ||||||
| require "./euler" | require "./euler" | ||||||
| 
 | 
 | ||||||
| def products_of_three_digit_nums | module Euler | ||||||
|   (100..999).to_a.combinations(2).map { |p| p.product } |   module Problem004 | ||||||
| end |     extend self | ||||||
| 
 | 
 | ||||||
| puts products_of_three_digit_nums.select { |x| Euler.palindrome?(x) }.max |     def products_of_three_digit_nums | ||||||
|  |       (100..999).to_a.combinations(2).map { |p| p.product } | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def solution | ||||||
|  |       products_of_three_digit_nums.select { |x| Euler.palindrome?(x) }.max | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | @ -1,19 +1,27 @@ | ||||||
| require "./euler" | require "./euler" | ||||||
| 
 | 
 | ||||||
| def integer_factorization_divisible_by_all_up_to(n) | module Euler | ||||||
|   result = {} of Euler::NumType => Euler::NumType |   module Problem005 | ||||||
|   (2..n).map do |i| |     extend self | ||||||
|     Euler.prime_factorization(i).each do |prime, exponent| | 
 | ||||||
|       if !result.has_key?(prime) || (exponent > result[prime]) |     def integer_factorization_divisible_by_all_up_to(n) | ||||||
|         result[prime] = exponent |       result = {} of Euler::NumType => Euler::NumType | ||||||
|  |       (2..n).map do |i| | ||||||
|  |         Euler.prime_factorization(i).each do |prime, exponent| | ||||||
|  |           if !result.has_key?(prime) || (exponent > result[prime]) | ||||||
|  |             result[prime] = exponent | ||||||
|  |           end | ||||||
|  |         end | ||||||
|       end |       end | ||||||
|  |       result | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def factors_to_int(factorization : Hash(Euler::NumType, Euler::NumType)) | ||||||
|  |       factorization.map { |prime, exponent| prime ** exponent }.product | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def solution | ||||||
|  |       factors_to_int(integer_factorization_divisible_by_all_up_to(20)) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   result |  | ||||||
| end | end | ||||||
| 
 |  | ||||||
| def factors_to_int(factorization : Hash(Euler::NumType, Euler::NumType)) |  | ||||||
|   factorization.map { |prime, exponent| prime ** exponent }.product |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| puts factors_to_int(integer_factorization_divisible_by_all_up_to(20)) |  | ||||||
|  |  | ||||||
|  | @ -1 +1,9 @@ | ||||||
| puts (1..100).sum ** 2 - (1..100).map { |n| n * n }.sum | module Euler | ||||||
|  |   module Problem006 | ||||||
|  |     extend self | ||||||
|  | 
 | ||||||
|  |     def solution | ||||||
|  |       (1..100).sum ** 2 - (1..100).map { |n| n * n }.sum | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | @ -1,3 +1,11 @@ | ||||||
| require "./euler" | require "./prime" | ||||||
| 
 | 
 | ||||||
| puts Euler.eratosthenes_sieve(1000000)[10000] | module Euler | ||||||
|  |   module Problem007 | ||||||
|  |     extend self | ||||||
|  | 
 | ||||||
|  |     def solution | ||||||
|  |       Euler::Prime.new.skip(10000).next | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | @ -1,27 +1,35 @@ | ||||||
| require "./euler" | require "./euler" | ||||||
| 
 | 
 | ||||||
| def largest_consecutive_product(n, adjacent) | module Euler | ||||||
|   Euler.to_big_ints(Euler.to_digit_list(n)).each_cons(adjacent).map { |x| x.product }.max |   module Problem008 | ||||||
| end |     extend self | ||||||
| 
 | 
 | ||||||
| puts largest_consecutive_product( |     def largest_consecutive_product(n, adjacent) | ||||||
| BigInt.new("73167176531330624919225119674426574742355349194934 |       Euler.to_big_ints(Euler.to_digit_list(n)).each_cons(adjacent).map { |x| x.product }.max | ||||||
| 96983520312774506326239578318016984801869478851843 |     end | ||||||
| 85861560789112949495459501737958331952853208805511 | 
 | ||||||
| 12540698747158523863050715693290963295227443043557 |     def solution | ||||||
| 66896648950445244523161731856403098711121722383113 |       largest_consecutive_product( | ||||||
| 62229893423380308135336276614282806444486645238749 |       BigInt.new("73167176531330624919225119674426574742355349194934 | ||||||
| 30358907296290491560440772390713810515859307960866 |       96983520312774506326239578318016984801869478851843 | ||||||
| 70172427121883998797908792274921901699720888093776 |       85861560789112949495459501737958331952853208805511 | ||||||
| 65727333001053367881220235421809751254540594752243 |       12540698747158523863050715693290963295227443043557 | ||||||
| 52584907711670556013604839586446706324415722155397 |       66896648950445244523161731856403098711121722383113 | ||||||
| 53697817977846174064955149290862569321978468622482 |       62229893423380308135336276614282806444486645238749 | ||||||
| 83972241375657056057490261407972968652414535100474 |       30358907296290491560440772390713810515859307960866 | ||||||
| 82166370484403199890008895243450658541227588666881 |       70172427121883998797908792274921901699720888093776 | ||||||
| 16427171479924442928230863465674813919123162824586 |       65727333001053367881220235421809751254540594752243 | ||||||
| 17866458359124566529476545682848912883142607690042 |       52584907711670556013604839586446706324415722155397 | ||||||
| 24219022671055626321111109370544217506941658960408 |       53697817977846174064955149290862569321978468622482 | ||||||
| 07198403850962455444362981230987879927244284909188 |       83972241375657056057490261407972968652414535100474 | ||||||
| 84580156166097919133875499200524063689912560717606 |       82166370484403199890008895243450658541227588666881 | ||||||
| 05886116467109405077541002256983155200055935729725 |       16427171479924442928230863465674813919123162824586 | ||||||
| 71636269561882670428252483600823257530420752963450"), 13) |       17866458359124566529476545682848912883142607690042 | ||||||
|  |       24219022671055626321111109370544217506941658960408 | ||||||
|  |       07198403850962455444362981230987879927244284909188 | ||||||
|  |       84580156166097919133875499200524063689912560717606 | ||||||
|  |       05886116467109405077541002256983155200055935729725 | ||||||
|  |       71636269561882670428252483600823257530420752963450"), 13) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | @ -1,14 +1,22 @@ | ||||||
| require "./euler" | require "./euler" | ||||||
| 
 | 
 | ||||||
| def generate_pythagorean_triples(upper_bound) | module Euler | ||||||
|   ([] of Array(Euler::NumType)).tap do |triples| |   module Problem009 | ||||||
|     (2..upper_bound).each do |a| |     extend self | ||||||
|       (a..upper_bound).each do |b| | 
 | ||||||
|         c = Math.sqrt(a**2 + b**2) |     def generate_pythagorean_triples(upper_bound) | ||||||
|         triples << [a, b, c.to_i] if c % 1 == 0 |       ([] of Array(Euler::NumType)).tap do |triples| | ||||||
|  |         (2..upper_bound).each do |a| | ||||||
|  |           (a..upper_bound).each do |b| | ||||||
|  |             c = Math.sqrt(a**2 + b**2) | ||||||
|  |             triples << [a, b, c.to_i] if c % 1 == 0 | ||||||
|  |           end | ||||||
|  |         end | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|  | 
 | ||||||
|  |     def solution | ||||||
|  |       generate_pythagorean_triples(500).find([-1]) { |x| x.sum == 1000 }.product | ||||||
|  |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
| 
 |  | ||||||
| puts generate_pythagorean_triples(500).find([-1]) { |x| x.sum == 1000 }.product |  | ||||||
|  |  | ||||||
|  | @ -1,4 +1,12 @@ | ||||||
| require "./prime" | require "./prime" | ||||||
| 
 | 
 | ||||||
| prime = Euler::Prime.new | module Euler | ||||||
| puts prime.take_while { |x| x < 2000000 }.sum |   module Problem010 | ||||||
|  |     extend self | ||||||
|  | 
 | ||||||
|  |     def solution | ||||||
|  |       prime = Euler::Prime.new | ||||||
|  |       prime.take_while { |x| x < 2000000 }.sum | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | @ -2,7 +2,8 @@ require "./euler" | ||||||
| 
 | 
 | ||||||
| module Euler | module Euler | ||||||
|   class Prime |   class Prime | ||||||
|     include Iterator(NumType) |     # needs to include BigInt ... | ||||||
|  |     include Iterator(NumType | BigInt) | ||||||
| 
 | 
 | ||||||
|     def initialize() |     def initialize() | ||||||
|       @sieve_size = 16 |       @sieve_size = 16 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler001" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem001 do | ||||||
|  |   it "should return 233168" do | ||||||
|  |     Euler::Problem001.solution.should eq 233168 | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler002" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem002 do | ||||||
|  |   it "should return 4613732" do | ||||||
|  |     Euler::Problem002.solution.should eq 4613732 | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler003" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem003 do | ||||||
|  |   it "should return 6857" do | ||||||
|  |     Euler::Problem003.solution.should eq 6857 | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler004" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem004 do | ||||||
|  |   it "should return 906609" do | ||||||
|  |     Euler::Problem004.solution.should eq 906609 | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler005" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem005 do | ||||||
|  |   it "should return 232792560" do | ||||||
|  |     Euler::Problem005.solution.should eq 232792560 | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler006" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem006 do | ||||||
|  |   it "should return 25164150" do | ||||||
|  |     Euler::Problem006.solution.should eq 25164150 | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler007" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem007 do | ||||||
|  |   it "should return 104743" do | ||||||
|  |     Euler::Problem007.solution.should eq 104743 | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler008" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem008 do | ||||||
|  |   it "should return 23514624000" do | ||||||
|  |     Euler::Problem008.solution.should eq 23514624000 | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler009" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem009 do | ||||||
|  |   it "should return 31875000" do | ||||||
|  |     Euler::Problem009.solution.should eq 31875000 | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | require "spec" | ||||||
|  | require "../euler010" | ||||||
|  | 
 | ||||||
|  | describe Euler::Problem010 do | ||||||
|  |   it "should return 142913828922" do | ||||||
|  |     Euler::Problem010.solution.should eq 142913828922 | ||||||
|  |   end | ||||||
|  | end | ||||||
		Loading…
	
		Reference in New Issue