class Rational(n : BigInt, d: BigInt) { private def gcd(x: BigInt, y: BigInt): BigInt = { if (x == 0) y else if (x < 0) gcd(-x, y) else if (y < 0) -gcd(x, -y) else gcd(y % x, x) } private val g = gcd(n, d) val numer: BigInt = n/g val denom: BigInt = d/g def +(that: Rational) = new Rational(numer * that.denom + that.numer * denom, denom * that.denom) def -(that: Rational) = new Rational(numer * that.denom - that.numer * denom, denom * that.denom) def *(that: Rational) = new Rational(numer * that.numer, denom * that.denom) def *(that: BigInt) = new Rational(that * numer, denom); def /(that: Rational) = new Rational(numer * that.denom, denom * that.numer) def reciprocal() = new Rational(denom, numer) def ==(that: Rational) = (numer == that.numer && denom == that.denom) } object e101 { val one = BigInt(1) val u = Array(one, -one, one, -one, one, -one, one, -one, one, -one, one) def solve(matrix: Array[Array[Rational]]): Array[BigInt] = { for (i <- 0 to matrix.size - 1) { // Get leading 0s for (j <- 0 to (i - 1)) { matrix(i) = matrix(i).map(_ * matrix(i)(j).reciprocal) for (k <- j to matrix(i).size - 1) { matrix(i)(k) = matrix(i)(k) - matrix(j)(k) } } //Get the 1 in front matrix(i) = matrix(i).map(_ * matrix(i)(i).reciprocal) } // We go farther than row reduction, and get something // that looks the identity // (We assume correctly our matrix is invertible) for (i <- 1 to matrix.size - 1) { val ii = matrix.size - i for (j <- 0 to ii - 1) { val m = matrix(j)(ii) for (k <- 0 to matrix(j).size - 1) { matrix(j)(k) = matrix(j)(k) - m * matrix(ii)(k) } } } val t = matrix.transpose return t(matrix.size).map((x: Rational) => x.numer / x.denom) } //For row reduction, we need the augmented matrix with the sequence in the //right-hand column def getMatrix(seq: Array[BigInt]) : Array[Array[Rational]] = { val matrix : Array[Array[Rational]] = new Array(seq.size) for (i <- 0 to matrix.size - 1) { matrix(i) = new Array(seq.size + 1) for (j <- 0 to seq.size - 1) { matrix(i)(j) = new Rational(BigInt(i + 1) pow j, 1) } matrix(i)(seq.size) = new Rational(seq(i), 1) } return matrix } def evalPoly(p: Array[BigInt], n: Int): BigInt = { var s = BigInt(0) for (i <- 0 to p.size - 1) { s += p(i) * (BigInt(n) pow i) } return s } def FIT(p: Array[BigInt]): BigInt = { for (i <- 1 to 11) { var nextVal = evalPoly(p, i) if (nextVal != evalPoly(u, i)) { return nextVal } } return 0 } def main(args: Array[String]) = { var ans = BigInt(0) var seq: Array[BigInt] = new Array(0) for(i <- 1 to 10) { seq = seq :+ evalPoly(u, i) val p = solve(getMatrix(seq)) val fit = FIT(p) ans += fit } println(ans) } }
Tuesday, April 14, 2015
Problem 101 in Scala
I worked out a solution to problem 101 first in Python, but it was difficult to port this solution to another language: I had need of numpy to solve linear systems of equations. After spending a while not wanting to do what needed to be done, I finally sat down and wrote a (not-entirely general) system of linear equations solver in Scala. Scala was a decent language for this, due to the existence of map operations, a very necessary BigInt class, and the ability to easily define and use a Rational class. I am sure that if I were more well versed in the ways of Scala I could have made this simpler, but oh well: I have a solution to the problem, my first new solution to a problem in many months, and it runs in under a second.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment