157 lines
3.6 KiB
Plaintext
157 lines
3.6 KiB
Plaintext
import ballerina/io;
|
|
|
|
function gcd(int num, int den) returns int {
|
|
int n = num; // make mutable
|
|
int d = den; // ditto
|
|
while d != 0 {
|
|
int t = d;
|
|
d = n % d;
|
|
n = t;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
class Frac {
|
|
int num;
|
|
int den;
|
|
|
|
function init(int num, int den) {
|
|
int n = num; // make mutable
|
|
int d = den; // ditto
|
|
if n == 0 {
|
|
d = 1;
|
|
} else if d < 0 {
|
|
n = -n;
|
|
d = -d;
|
|
}
|
|
int g = gcd(n, d).abs();
|
|
if g > 1 {
|
|
n /= g;
|
|
d /= g;
|
|
}
|
|
self.num = n;
|
|
self.den = d;
|
|
}
|
|
|
|
function fromInt(int i) returns Frac {
|
|
return new Frac(i, 1);
|
|
}
|
|
|
|
function neg() returns Frac {
|
|
return new Frac(-self.num, self.den);
|
|
}
|
|
|
|
function inv() returns Frac {
|
|
return new Frac(self.den, self.num);
|
|
}
|
|
|
|
function copy() returns Frac {
|
|
return new Frac(self.num, self.den);
|
|
}
|
|
|
|
function abs() returns Frac {
|
|
if self.num >= 0 { return self.copy(); }
|
|
return self.neg();
|
|
}
|
|
|
|
function add(Frac other) returns Frac {
|
|
return new Frac(self.num * other.den + self.den * other.num, self.den * other.den);
|
|
}
|
|
|
|
function sub(Frac other) returns Frac {
|
|
return self.add(other.neg());
|
|
}
|
|
|
|
function mul(Frac other) returns Frac {
|
|
return new Frac(self.num * other.num, self.den * other.den);
|
|
}
|
|
|
|
function div(Frac other) returns Frac {
|
|
return new Frac(self.num * other.den, self.den * other.num);
|
|
}
|
|
|
|
function toFloat() returns float {
|
|
return <float>self.num / <float>self.den;
|
|
}
|
|
|
|
function toInt() returns int {
|
|
float f = self.toFloat();
|
|
f = f >= 0.0 ? f.floor() : f.ceiling();
|
|
return <int>f;
|
|
}
|
|
|
|
function idiv(Frac other) returns Frac {
|
|
return new Frac(self.toInt(), 1);
|
|
}
|
|
|
|
function mod(Frac other) returns Frac {
|
|
return self.sub(self.idiv(other).mul(other));
|
|
}
|
|
|
|
function lt(Frac other) returns boolean {
|
|
return self.toFloat() < other.toFloat();
|
|
}
|
|
|
|
function le(Frac other) returns boolean {
|
|
return self.toFloat() <= other.toFloat();
|
|
}
|
|
|
|
function gt(Frac other) returns boolean {
|
|
return self.toFloat() > other.toFloat();
|
|
}
|
|
|
|
function ge(Frac other) returns boolean {
|
|
return self.toFloat() >= other.toFloat();
|
|
}
|
|
|
|
function eq(Frac other) returns boolean {
|
|
return self.toFloat() == other.toFloat();
|
|
}
|
|
|
|
function ne(Frac other) returns boolean {
|
|
return self.toFloat() != other.toFloat();
|
|
}
|
|
|
|
function toString() returns string {
|
|
return string `${self.num} / ${self.den}`;
|
|
}
|
|
}
|
|
|
|
function divisors(int n) returns int[] {
|
|
if n < 1 { return []; }
|
|
int[] divisors = [];
|
|
int[] divisors2 = [];
|
|
int i = 1;
|
|
int k = n % 2 == 0 ? 1 : 2;
|
|
while i * i <= n {
|
|
if n % i == 0 {
|
|
divisors.push(i);
|
|
int j = n / i;
|
|
if j != i { divisors2.push(j); }
|
|
}
|
|
i += k;
|
|
}
|
|
if divisors2.length() > 0 {
|
|
divisors.push(...divisors2.reverse());
|
|
}
|
|
return divisors;
|
|
}
|
|
|
|
function properDivisors(int n) returns int[] {
|
|
int[] d = divisors(n);
|
|
int c = d.length();
|
|
return c <= 1 ? [] : d.slice(0, c - 1);
|
|
}
|
|
|
|
public function main() {
|
|
final Frac one = new Frac(1, 1);
|
|
io:println("The following numbers (less than 2^19) are perfect:");
|
|
foreach int i in 2..<(<int>1<<19) {
|
|
var sum = new Frac(1, i);
|
|
foreach int j in properDivisors(i).slice(1) {
|
|
sum = sum.add(new Frac(1, j));
|
|
}
|
|
if sum.eq(one) { io:println(" ", i); }
|
|
}
|
|
}
|