Compute PI in Kotlin on a T-shirt

I have written code in Kotlin with the objective of computing Pi in few enough lines so that it looks good on a t-shirt.

Can be cut and paste into http://try.kotlinlang.org under "My Programs" and run from browser - I just tested it with version 1.2.41 and it's working.

import kotlin.math.*
import java.math.BigInteger

fun main(args: Array<String>) {
val r = (4*(4*arccot(5) - arccot(239))).toString()
println("314 digits of Pi ${r}.${r.substring(1).dropLast(5)}")
}

fun arccot(x:BigInteger):BigInteger {
var precision = 10.toBigInteger().pow(319) / x
var total = precision
var divisor = 1.toBigInteger()

while(precision.abs() >= divisor) {
precision = -precision / x.pow(2)
divisor += 2
total += precision / divisor
}
}

fun arccot(x:Int) = arccot(x.toBigInteger())
operator fun Int.times(x: BigInteger) = this.toBigInteger() * x
operator fun BigInteger.plus(x: Int) = this + x.toBigInteger()

Currently it's longer than I'd like. I would like to shorten without making it less understandable. My vision is to have code that is readable enough it wouldn't be out of place in a production code base.

To give an idea, here's the significantly shorter Python version (which has been printed on a t-shirt and in my opinion looks good and is short enough but also quite readable). Can be run in browser here: https://repl.it/@sek/314-Digits - (there's also a link from there to the t-shirt if you are curious how that looks - the length in question isn't only the number of lines but also the width of the longest line as that determines the font size that can be used)

def pi():
r = 4*(4*arccot(5) - arccot(239))
return str(r)+'.'+str(r)[1:-5]

def arccot(x):
total = power = 10**319 // x
divisor = 1
while abs(power) >= divisor:
power = -power // x**2
divisor += 2
total += power // divisor

print("314 digits of Pi " + pi())

I noticed that you are calculating to 314 decimal places instead of 314 digits, so drop 6 instead of 5.

• You really don't need the extra functions. You can remove

fun arccot(x:Int) = arccot(x.toBigInteger())

if you convert Int to BigInteger inside your arctan method.

• You can remove

operator fun Int.times(x: BigInteger) = this.toBigInteger() * x

if you shl(2) instead of * 4.

• You can remove

operator fun BigInteger.plus(x: Int) = this + x.toBigInteger()

if you change

divisor += 2

to

divisor += BigInteger("2")

• You can shorten

println("314 digits of Pi ${r}.${r.substring(1).dropLast(5)}")

to

println("314 digits of Pi ${r}.${r.substring(1,314)}")

• Now, you can change the imports to

import java.math.*

• You don't have to declare the type for val r.

The final code I came up with by doing that is:

import java.math.*
fun main(args: Array<String>) {
val r = (acot(5).shl(2)-acot(239)).shl(2).toString()
println("314 digits of Pi ${r}.${r.substring(1,314)}")
}
fun acot(x:Int):BigInteger {
var precision = BigInteger.TEN.pow(319)/x.toBigInteger()
var total = precision
var divisor = BigInteger.ONE;
while(precision.abs() >= divisor) {
precision = -precision/(x.toBigInteger().pow(2))
divisor += BigInteger("2")
total += precision / divisor
}
}

I also came up with shorter code, with decreased width, by calculating a different way:

import java.math.*
fun main(args:Array<String>) {
val b4 = BigDecimal(4)
val r = ((atan(5)*b4-atan(239))*b4).toString()
println("314 digits of Pi \${r.substring(0,315)}")
}
fun atan(xInv:Int):BigDecimal {
var x = BigDecimal(1).divide(BigDecimal(xInv),330,3)
var (numer, total) = arrayOf(x, x)
for (i in 3..450 step 2) {
numer = -numer * x * x
total += numer / BigDecimal(i)
}