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&lt;String&gt;) { 
  val r = (4*(4*arccot(5) - arccot(239))).toString()
  println("314 digits of Pi ${r[0]}.${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() &gt;= divisor) {
    precision = -precision / x.pow(2)
    divisor += 2
    total += precision / divisor
  }
  return total
}

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)[0]+'.'+str(r)[1:-5]

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

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[0]}.${r.substring(1).dropLast(5)}")


to

println("314 digits of Pi ${r[0]}.${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&lt;String&gt;) {
  val r = (acot(5).shl(2)-acot(239)).shl(2).toString()
  println("314 digits of Pi ${r[0]}.${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() &gt;= divisor) {
    precision = -precision/(x.toBigInteger().pow(2))
    divisor += BigInteger("2")
    total += precision / divisor
  }
  return total
}


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

import java.math.*
fun main(args:Array&lt;String&gt;) {
  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)
  }
  return total
}