restructuring solutions for spec usage
							parent
							
								
									eb21d847e1
								
							
						
					
					
						commit
						251fb30d67
					
				
							
								
								
									
										102
									
								
								crystal/euler.cr
								
								
								
								
							
							
						
						
									
										102
									
								
								crystal/euler.cr
								
								
								
								
							|  | @ -3,57 +3,79 @@ | |||
| require "big" | ||||
| 
 | ||||
| module Euler | ||||
|   alias NumType = Int32 | Int64 | UInt32 | UInt64 | BigInt | ||||
|   extend self | ||||
| 
 | ||||
|   def self.trial_division(n : NumType) | ||||
|     factors = [] of NumType | ||||
|     check = ->(p: NumType) { | ||||
|       q, r = n.divmod(p) | ||||
|       while r.zero? | ||||
|         factors << p | ||||
|         n = q | ||||
|   alias NumType = Int32 | Int64 | UInt32 | UInt64 | ||||
| 
 | ||||
|   macro trial_division_method(given_type) | ||||
|     def trial_division(n : {{given_type}}) | ||||
|       factors = [] of {{given_type}} | ||||
|       check = ->(p: {{given_type}}) { | ||||
|         q, r = n.divmod(p) | ||||
|       end | ||||
|     } | ||||
|         while r.zero? | ||||
|           factors << p | ||||
|           n = q | ||||
|           q, r = n.divmod(p) | ||||
|         end | ||||
|       } | ||||
| 
 | ||||
|     check.call(2) | ||||
|     check.call(3) | ||||
|     p = 5 | ||||
|     while p * p <= n | ||||
|       check.call(p) | ||||
|       p += 2 | ||||
|       check.call(p) | ||||
|       p += 4 | ||||
|       check.call(2) | ||||
|       check.call(3) | ||||
|       p = 5 | ||||
|       while p * p <= n | ||||
|         check.call(p) | ||||
|         p += 2 | ||||
|         check.call(p) | ||||
|         p += 4 | ||||
|       end | ||||
|       factors << n if n > 1 | ||||
|       factors | ||||
|     end | ||||
|     factors << n if n > 1 | ||||
|     factors | ||||
|   end | ||||
| 
 | ||||
|   def self.prime_factorization(n : NumType) | ||||
|     result = {} of NumType => NumType | ||||
|     factors = self.trial_division(n) | ||||
|   macro prime_factorization_method(given_type) | ||||
|     def prime_factorization(n : {{given_type}}) | ||||
|       result = {} of {{given_type}} => Int32 | ||||
|       factors = self.trial_division(n) | ||||
| 
 | ||||
|     factors.each do |f| | ||||
|       result[f] = 0 | ||||
|       num = n | ||||
|       while num % f == 0 | ||||
|         result[f] += 1 | ||||
|         num /= f | ||||
|       factors.each do |f| | ||||
|         result[f] = 0 | ||||
|         num = n | ||||
|         while num % f == 0 | ||||
|           result[f] += 1 | ||||
|           num /= f | ||||
|         end | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     result | ||||
|       result | ||||
|     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 | ||||
|   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 | ||||
|  |  | |||
|  | @ -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) | ||||
|   result = [1] of Int32 | ||||
| module Euler | ||||
|   module Problem002 | ||||
|     extend self | ||||
| 
 | ||||
|   a = 1 | ||||
|   b = 2 | ||||
|   accum = 0 | ||||
|     def fibonacci_nums_up_to(n) | ||||
|       result = [1] of Int32 | ||||
| 
 | ||||
|   while accum < n | ||||
|     accum = a + b | ||||
|     result << b | ||||
|     a = b | ||||
|     b = accum | ||||
|       a = 1 | ||||
|       b = 2 | ||||
|       accum = 0 | ||||
| 
 | ||||
|       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 | ||||
| 
 | ||||
|   result | ||||
| end | ||||
| 
 | ||||
| puts fibonacci_nums_up_to(4000000).select{ |n| n.even? }.sum | ||||
|  |  | |||
|  | @ -1,3 +1,11 @@ | |||
| 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" | ||||
| 
 | ||||
| def products_of_three_digit_nums | ||||
|   (100..999).to_a.combinations(2).map { |p| p.product } | ||||
| end | ||||
| module Euler | ||||
|   module Problem004 | ||||
|     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" | ||||
| 
 | ||||
| def integer_factorization_divisible_by_all_up_to(n) | ||||
|   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 | ||||
| module Euler | ||||
|   module Problem005 | ||||
|     extend self | ||||
| 
 | ||||
|     def integer_factorization_divisible_by_all_up_to(n) | ||||
|       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 | ||||
|       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 | ||||
|   result | ||||
| 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" | ||||
| 
 | ||||
| def largest_consecutive_product(n, adjacent) | ||||
|   Euler.to_big_ints(Euler.to_digit_list(n)).each_cons(adjacent).map { |x| x.product }.max | ||||
| end | ||||
| module Euler | ||||
|   module Problem008 | ||||
|     extend self | ||||
| 
 | ||||
| puts largest_consecutive_product( | ||||
| BigInt.new("73167176531330624919225119674426574742355349194934 | ||||
| 96983520312774506326239578318016984801869478851843 | ||||
| 85861560789112949495459501737958331952853208805511 | ||||
| 12540698747158523863050715693290963295227443043557 | ||||
| 66896648950445244523161731856403098711121722383113 | ||||
| 62229893423380308135336276614282806444486645238749 | ||||
| 30358907296290491560440772390713810515859307960866 | ||||
| 70172427121883998797908792274921901699720888093776 | ||||
| 65727333001053367881220235421809751254540594752243 | ||||
| 52584907711670556013604839586446706324415722155397 | ||||
| 53697817977846174064955149290862569321978468622482 | ||||
| 83972241375657056057490261407972968652414535100474 | ||||
| 82166370484403199890008895243450658541227588666881 | ||||
| 16427171479924442928230863465674813919123162824586 | ||||
| 17866458359124566529476545682848912883142607690042 | ||||
| 24219022671055626321111109370544217506941658960408 | ||||
| 07198403850962455444362981230987879927244284909188 | ||||
| 84580156166097919133875499200524063689912560717606 | ||||
| 05886116467109405077541002256983155200055935729725 | ||||
| 71636269561882670428252483600823257530420752963450"), 13) | ||||
|     def largest_consecutive_product(n, adjacent) | ||||
|       Euler.to_big_ints(Euler.to_digit_list(n)).each_cons(adjacent).map { |x| x.product }.max | ||||
|     end | ||||
| 
 | ||||
|     def solution | ||||
|       largest_consecutive_product( | ||||
|       BigInt.new("73167176531330624919225119674426574742355349194934 | ||||
|       96983520312774506326239578318016984801869478851843 | ||||
|       85861560789112949495459501737958331952853208805511 | ||||
|       12540698747158523863050715693290963295227443043557 | ||||
|       66896648950445244523161731856403098711121722383113 | ||||
|       62229893423380308135336276614282806444486645238749 | ||||
|       30358907296290491560440772390713810515859307960866 | ||||
|       70172427121883998797908792274921901699720888093776 | ||||
|       65727333001053367881220235421809751254540594752243 | ||||
|       52584907711670556013604839586446706324415722155397 | ||||
|       53697817977846174064955149290862569321978468622482 | ||||
|       83972241375657056057490261407972968652414535100474 | ||||
|       82166370484403199890008895243450658541227588666881 | ||||
|       16427171479924442928230863465674813919123162824586 | ||||
|       17866458359124566529476545682848912883142607690042 | ||||
|       24219022671055626321111109370544217506941658960408 | ||||
|       07198403850962455444362981230987879927244284909188 | ||||
|       84580156166097919133875499200524063689912560717606 | ||||
|       05886116467109405077541002256983155200055935729725 | ||||
|       71636269561882670428252483600823257530420752963450"), 13) | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,14 +1,22 @@ | |||
| require "./euler" | ||||
| 
 | ||||
| def generate_pythagorean_triples(upper_bound) | ||||
|   ([] 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 | ||||
| module Euler | ||||
|   module Problem009 | ||||
|     extend self | ||||
| 
 | ||||
|     def generate_pythagorean_triples(upper_bound) | ||||
|       ([] 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 | ||||
| 
 | ||||
|     def solution | ||||
|       generate_pythagorean_triples(500).find([-1]) { |x| x.sum == 1000 }.product | ||||
|     end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| puts generate_pythagorean_triples(500).find([-1]) { |x| x.sum == 1000 }.product | ||||
|  |  | |||
|  | @ -1,4 +1,12 @@ | |||
| require "./prime" | ||||
| 
 | ||||
| prime = Euler::Prime.new | ||||
| puts prime.take_while { |x| x < 2000000 }.sum | ||||
| module Euler | ||||
|   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 | ||||
|   class Prime | ||||
|     include Iterator(NumType) | ||||
|     # needs to include BigInt ... | ||||
|     include Iterator(NumType | BigInt) | ||||
| 
 | ||||
|     def initialize() | ||||
|       @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