110 lines
1.8 KiB
Crystal
110 lines
1.8 KiB
Crystal
struct Int
|
|
def to_frac
|
|
Frac.new self
|
|
end
|
|
|
|
def over (den)
|
|
Frac.new self, den
|
|
end
|
|
end
|
|
|
|
struct Frac
|
|
include Comparable(Number)
|
|
|
|
getter num : Int64
|
|
getter den : Int64
|
|
|
|
def initialize (num : Int, den : Int)
|
|
raise "denominator can't be 0" if den.zero?
|
|
if num.zero?
|
|
@num, @den = 0_i64, 1_i64
|
|
else
|
|
sign = num.sign * den.sign
|
|
num, den = num.to_i64.abs, den.to_i64.abs
|
|
gcd = num.gcd(den)
|
|
@num = (num // gcd) * sign
|
|
@den = (den // gcd)
|
|
end
|
|
end
|
|
|
|
def initialize (num : Int)
|
|
initialize(num, 1)
|
|
end
|
|
|
|
def to_i
|
|
@num // @den
|
|
end
|
|
|
|
def to_f
|
|
@num / @den
|
|
end
|
|
|
|
def whole?
|
|
@den == 1
|
|
end
|
|
|
|
def to_frac
|
|
self
|
|
end
|
|
|
|
def inv
|
|
self.class.new @den, @num
|
|
end
|
|
|
|
def sign
|
|
@num.sign
|
|
end
|
|
|
|
def -
|
|
self.class.new -@num, @den
|
|
end
|
|
|
|
def abs
|
|
self.class.new @num.abs, @den
|
|
end
|
|
|
|
def + (other)
|
|
other = other.to_frac
|
|
lcm = @den.lcm(other.den)
|
|
self.class.new(@num * lcm // @den + other.num * lcm // other.den, lcm)
|
|
end
|
|
|
|
def - (other)
|
|
self + -other
|
|
end
|
|
|
|
def * (other)
|
|
other = other.to_frac
|
|
self.class.new @num * other.num, @den * other.den
|
|
end
|
|
|
|
def / (other)
|
|
self * other.to_frac.inv
|
|
end
|
|
|
|
def // (other)
|
|
other = other.to_frac
|
|
self.class.new((@num * other.den) // (@den * other.num))
|
|
end
|
|
|
|
def % (other)
|
|
other = other.to_frac
|
|
self.class.new((@num * other.den) % (@den * other.num), @den * other.den)
|
|
end
|
|
|
|
def <=> (other)
|
|
self.to_f <=> other.to_f
|
|
end
|
|
end
|
|
|
|
(2_i64 .. 2_i64**19).each do |candidate|
|
|
sum = 1.over candidate
|
|
(2_i64 .. Math.isqrt(candidate)).each do |factor|
|
|
if candidate % factor == 0
|
|
sum += 1.over(factor) + 1.over(candidate // factor)
|
|
end
|
|
end
|
|
if sum.whole?
|
|
puts "Sum of recipr. factors of %6d = %s exactly%s" % { candidate, sum.num, sum == 1 ? " perfect!" : "" }
|
|
end
|
|
end
|