more solutions in crystal
parent
9426f02642
commit
eb21d847e1
|
@ -1,23 +1,59 @@
|
||||||
# miscellaneous stuff
|
# miscellaneous stuff
|
||||||
|
|
||||||
module Euler
|
require "big"
|
||||||
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|
|
module Euler
|
||||||
if sieve[i]
|
alias NumType = Int32 | Int64 | UInt32 | UInt64 | BigInt
|
||||||
(i * i).step(to: n, by: i) do |j|
|
|
||||||
sieve[j] = false
|
def self.trial_division(n : NumType)
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
result = sieve.map_with_index { |b, i| b ? i : nil }.compact
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.palindrome?(x)
|
def self.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,27 +1,3 @@
|
||||||
alias NumType = Int32 | Int64 | UInt32 | UInt64
|
require "./euler"
|
||||||
|
|
||||||
def trial_division(n : NumType)
|
puts Euler.trial_division(600851475143).max
|
||||||
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
|
|
||||||
|
|
|
@ -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