Anagram finder in Kotlin

This is the Kotlin implementation of the anagram program. The problem and the solution is described in the main anagram article. Do read that article first.

Kotlin execution-speed is slightly better than that of Java. But it has the worst memory performance of all languages so far, using 396 MB. Almost four times as much memory as Java (100 MB). This may partly be because there is no way of triggering a garbage collection. In Java there is, and without explicit garbage collection the Java program has roughly the same meory usage as the Kotlin program.

Note the implementation of printf() at the beginning of the code.

The source code

val MINIMUM           = 3
var comparisons : Int = 0

fun printf(fmt : String, vararg args: Any?) {
    print(fmt.format(*args))
}

class Word : Comparable<Word> {
    var offset  : Int
    var value   : String
    var unified : String

    constructor (offset : Int, value : String, unified : String) {
        this.offset  = offset
        this.value   = value
        this.unified = unified
    }

    override operator fun compareTo(other : Word) : Int {
        comparisons++
        var rval : Int = this.unified.compareTo(other.unified)
        return if (0 != rval) rval else (this.offset - other.offset)
    }
}

class AnagramFinder {
    private var len        : Int
    private var words      = mutableListOf<Word>()
    private var accepted   = mutableListOf<Word>()
    private var low_offset : Int = 0

    constructor(text : String, len : Int) {
        this.len = len
        for (i in (0..(text.length-len))) {
            var value   : String = text.substring(i..i+len-1)
            words.add(Word(i, value, this.get_unified(value)))
        }
    }

    fun get_unified(value : String) : String {
        var tmp : CharArray = CharArray(len)
        value.toCharArray(tmp)
        tmp.sort()
        return String(tmp)
    }

    fun print_one_result() {
        printf("%3d:", accepted.count())
        accepted.forEach { printf(" %4d:%s", it.offset, it.value) }
        printf("\n")
    }

    fun add_candidate(cand : Int) {
        var c = words[cand]
        if (c.offset < low_offset)
            return
        accepted.forEach {
            if (it.value == c.value)
                return
        }
        accepted.add(c)
        low_offset = c.offset + len
    }

    fun add_range(first : Int, last : Int) {
        if (last-first+1 >= MINIMUM) {
            accepted.clear()
            low_offset = 0
            for (n in first..last)
                add_candidate(n)
            if (accepted.count() >= MINIMUM)
                print_one_result()
        }
    }

    fun find_all() {
        words.sort()
        var first : Int = 0
        for (i in (1..(words.count()-1))) {
            if (words[first].unified != words[i].unified) {
                add_range(first, i-1)
                first = i
            }
        }
        add_range(first, words.count()-1)
    }
}

fun read_text() : String {
    var sb             = StringBuilder(500 * 512)
    var line : String? = readLine()
    while (null != line) {
        for (ch : Char in line)
            if (ch.isLetter())
                sb.append(ch.toUpperCase())
        line = readLine()
    }
    return String(sb)
}

fun main(args: Array<String>) {
    var from : Int = if (args.size > 0) args[0].toInt() else 6
    var to   : Int = if (args.size > 1) args[1].toInt() else from
    var text = read_text()

    for (len in from..to) {
        printf("%slen = %d\n", (if (len > from) "\n" else ""), len)
        var af = AnagramFinder(text, len)
        af.find_all()
    }
    printf("string length = %5d, comparisons = %d\n", text.length, comparisons)
}

You can reach me by email at “lars dash 7 dot sdu dot se” or by telephone +46 705 189090

View source for the content of this page.