more solutions in crystal
							parent
							
								
									9426f02642
								
							
						
					
					
						commit
						eb21d847e1
					
				| 
						 | 
				
			
			@ -1,23 +1,59 @@
 | 
			
		|||
# miscellaneous stuff
 | 
			
		||||
 | 
			
		||||
module Euler
 | 
			
		||||
  def self.eratosthenes_sieve(n)
 | 
			
		||||
    sieve = Array.new(n + 1, true)
 | 
			
		||||
    sieve[0] = false
 | 
			
		||||
    sieve[1] = false
 | 
			
		||||
require "big"
 | 
			
		||||
 | 
			
		||||
    2.step(to: Math.sqrt(n)) do |i|
 | 
			
		||||
      if sieve[i]
 | 
			
		||||
        (i * i).step(to: n, by: i) do |j|
 | 
			
		||||
          sieve[j] = false
 | 
			
		||||
        end
 | 
			
		||||
module Euler
 | 
			
		||||
  alias NumType = Int32 | Int64 | UInt32 | UInt64 | BigInt
 | 
			
		||||
 | 
			
		||||
  def self.trial_division(n : NumType)
 | 
			
		||||
    factors = [] of NumType
 | 
			
		||||
    check = ->(p: NumType) {
 | 
			
		||||
      q, r = n.divmod(p)
 | 
			
		||||
      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
 | 
			
		||||
    end
 | 
			
		||||
    factors << n if n > 1
 | 
			
		||||
    factors
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def self.prime_factorization(n : NumType)
 | 
			
		||||
    result = {} of NumType => NumType
 | 
			
		||||
    factors = self.trial_division(n)
 | 
			
		||||
 | 
			
		||||
    factors.each do |f|
 | 
			
		||||
      result[f] = 0
 | 
			
		||||
      num = n
 | 
			
		||||
      while num % f == 0
 | 
			
		||||
        result[f] += 1
 | 
			
		||||
        num /= f
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    result = sieve.map_with_index { |b, i| b ? i : nil }.compact
 | 
			
		||||
    result
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def self.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,27 +1,3 @@
 | 
			
		|||
alias NumType = Int32 | Int64 | UInt32 | UInt64
 | 
			
		||||
require "./euler"
 | 
			
		||||
 | 
			
		||||
def trial_division(n : NumType)
 | 
			
		||||
  factors = [] of NumType
 | 
			
		||||
  check = ->(p: NumType) {
 | 
			
		||||
    q, r = n.divmod(p)
 | 
			
		||||
    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
 | 
			
		||||
  end
 | 
			
		||||
  factors << n if n > 1
 | 
			
		||||
  factors
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
puts trial_division(600851475143).max
 | 
			
		||||
puts Euler.trial_division(600851475143).max
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
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
 | 
			
		||||
      end
 | 
			
		||||
    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))
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
puts (1..100).sum ** 2 - (1..100).map { |n| n * n }.sum
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
require "./euler"
 | 
			
		||||
 | 
			
		||||
puts Euler.eratosthenes_sieve(1000000)[10000]
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
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
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
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
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
puts generate_pythagorean_triples(500).find([-1]) { |x| x.sum == 1000 }.product
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
require "./prime"
 | 
			
		||||
 | 
			
		||||
prime = Euler::Prime.new
 | 
			
		||||
puts prime.take_while { |x| x < 2000000 }.sum
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,68 @@
 | 
			
		|||
require "./euler"
 | 
			
		||||
 | 
			
		||||
module Euler
 | 
			
		||||
  class Prime
 | 
			
		||||
    include Iterator(NumType)
 | 
			
		||||
 | 
			
		||||
    def initialize()
 | 
			
		||||
      @sieve_size = 16
 | 
			
		||||
      @sieved_up_to = 0
 | 
			
		||||
 | 
			
		||||
      @primes = Array(Bool).new(@sieve_size, true)
 | 
			
		||||
      @primes[0] = false
 | 
			
		||||
      @primes[1] = false
 | 
			
		||||
 | 
			
		||||
      @index = 0
 | 
			
		||||
      iterative_eratosthenes_sieve
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private def check_and_increase_sieve
 | 
			
		||||
      if @index > @primes.size - 1
 | 
			
		||||
        @sieve_size *= 2
 | 
			
		||||
        until @primes.size == @sieve_size
 | 
			
		||||
          @primes << true
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      iterative_eratosthenes_sieve
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private def iterative_eratosthenes_sieve
 | 
			
		||||
      2.step(to: Math.sqrt(@sieve_size)) do |i|
 | 
			
		||||
        if @primes[i]
 | 
			
		||||
          (i * i >= @sieved_up_to ? i * i : @sieved_up_to + i - (@sieved_up_to % i)).step(to: @sieve_size-1, by: i) do |j|
 | 
			
		||||
            @primes[j] = false
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      @sieved_up_to = @sieve_size-1
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def next
 | 
			
		||||
      @index += 1
 | 
			
		||||
      check_and_increase_sieve
 | 
			
		||||
 | 
			
		||||
      until @primes[@index]
 | 
			
		||||
        @index += 1
 | 
			
		||||
        check_and_increase_sieve
 | 
			
		||||
      end
 | 
			
		||||
      @index
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.eratosthenes_sieve(n)
 | 
			
		||||
      sieve = Array.new(n + 1, true)
 | 
			
		||||
      sieve[0] = false
 | 
			
		||||
      sieve[1] = false
 | 
			
		||||
 | 
			
		||||
      2.step(to: Math.sqrt(n)) do |i|
 | 
			
		||||
        if sieve[i]
 | 
			
		||||
          (i * i).step(to: n, by: i) do |j|
 | 
			
		||||
            sieve[j] = false
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      result = sieve.map_with_index { |b, i| b ? i : nil }.compact
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
		Reference in New Issue