I pretty much exclusively use Kotlin for competitive programming, mostly because it's the language I'm currently most comfortable with. Here are some scattered notes and tidbits about my experience which I think might be useful to others; if you have any tips/suggestions, feel free to let me know.
Primer
- Kotlin has an official primer for competitive programming. However, the IO code suggested there is only so-so; it's definitely better than
Scanner
, but you definitely can save a lot of runtime in heavy input problems by using the classic Java combination ofBufferedReader
+StringTokenizer
Useful features
A lot less boilerplate than Java. Members are
public
by default. Type inference means a lot less "Pokémon speak". Variables and functions can be declared straight in the top-level of the file. (basically the equivalent ofstatic
functions). Fields have implicit getters and setters that can easily be overridden when necessary.PHP-like string templates, e.g.
"$id $cost"
Extension functions – syntactic sugar for static functions; gives more natural "afterthought" syntax, as well as allowing direct access to public members of the receiver
data class
es – basically custom tuples. Allows convenient destructuring declarations too.Has access to the data structures in the Java standard library (
TreeMap
,HashMap
,PriorityQueue
etc.), and also can useBigInteger
andBigDecimal
if neededFunctional idioms for collection manipulation –
map
,fold
,filter
, etc.Sequences – lazy sequence generators, potentially infinite, has standard collection manipulation functions too. Using the
sequence { ... }
block function allows building a sequence using a scopedyield(value)
function, reminiscent of Pythoninline class
es – allows the creation of a new type that wraps over a base type, but that is represented by an underlying type at runtime. Especially useful for "modulo $$$10^9 + 7$$$" problems, as I keep code for aModInt
class that overloads the arithmetic operators appropriately, but is represented as a plainint
in JVM runtime. Keep in mind that they are experimental as of Kotlin 1.3, but that's fine for CP in my opinionunsigned integer types in the standard library that use the
inline class
feature. Not used very often, but handy if neededinline fun
ctions – tells the compiler to inline the function to call sites. Useful for higher-order functions (JVM won't need to create a new object for the lambda) as well as small functions that are called very often; basically, anything you might use a macro for in C++, you probably want to use aninline fun
orinline val
fortailrec fun
– tail recursion optimizationrun
block function – great way to write code that needs to shortcut (e.g.return@run "NO"
) without having to write a new function and pass every relevant argumentfunctions in functions – functions can be defined within e.g. the
main
function, so again, no having to pass lots of arguments or global variables. Keep in mind that these are represented as objects during runtime. It's too bad they can't beinline
as of yet
Potential pitfalls
Generic wrappers for JVM primitive types can cause TLE for some problems. Use primitive arrays (
IntArray
etc.) whenever possible to avoid this, but see next pointInherits the hack-prone quicksort from Java for primitive arrays. Easiest solution is to use generic arrays or lists instead, but due to the performance benefit of primitive arrays, I've took the trouble to write code that shuffles them randomly before sorting.
For Kotlin versions < 1.3.30, there is a bug that will throw an exception when using
.asJavaRandom()
on instances ofkotlin.random.Random
, including Kotlin's default instance. Either use Java's own Random class, or steal this wrapper:
class JavaRandom(val kt: Random) : java.util.Random(0) {
override fun next(bits: Int): Int = kt.nextBits(bits)
override fun setSeed(seed: Long) {}
}