June 25, 2023

A simple Kotlin demo

I am working with Kotlin native on my Fedora linux system. I have an ascii file with over 300,000 words that I read and then work up some simple searches on. I use the functional programing tools -- filter() and count(). Here is the output:
File: dictionary.txt
349900 lines in file
202 palindromes
23406 lines begin with a
22162 lines begin with b
28110 lines begin with c
17562 lines begin with d
12347 lines begin with e
12181 lines begin with f
13011 lines begin with g
13702 lines begin with h
9929 lines begin with i
4202 lines begin with j
9927 lines begin with k
12617 lines begin with l
23314 lines begin with m
10559 lines begin with n
9645 lines begin with o
25987 lines begin with p
1439 lines begin with q
14017 lines begin with r
34071 lines begin with s
18216 lines begin with t
14522 lines begin with u
5693 lines begin with v
8103 lines begin with w
999 lines begin with x
1977 lines begin with y
2202 lines begin with z
Here are some comments on the code that follows and about Kotlin in general after my first day working with it. Having just done a bit of C# programming, what can I say about Kotlin versus C#? They are closely comparable. Both are worlds better than Java. I like it that Kotlin is optimized for terse source code. The principle of least surprise serves me very well, I can guess what I should do and usually I am correct. I'll note that although no types appear in this final source code, the compiler complained on numerous occasions when I was doing things that would cause a type clash.

This code is longer than my C# equivalent simply because I had to write my own "Reader" class. I used a one line "read the file" in C# -- and there are a variety of those available for Kotlin also (so why didn't I use one?). Being able to type prinln() rather than Console.WriteLine() is nice.

There is much much less available online about Kotlin that about C#. But there is enough.

import platform.posix.*
import kotlinx.cinterop.*

/* This file is 3206215 bytes in size,
 * and has 349900 words (and 3 comment lines)
 * It is not out of the question to store it all in a list
 */
val dict_path = "dictionary.txt"

fun main()
{
    val reader = Reader ( dict_path )
    reader.show()

    val all = reader.readAll ()
    if ( all == null )
	return

    var count = all.size
    println ( "$count lines in file" )

    // get all palindromes
    // note that Kotlin lambdas can use "it" if
    // there is a single argument

    var pals = all.filter ( { it.reversed() == it } )
    //val raw_count = pals.size
    //println ( "$raw_count palindromes" )

    pals = pals.filter ( { ! bogus ( it ) } )
    val pal_count = pals.size
    println ( "$pal_count palindromes" )

    // for ( p in pals )
    // 	println ( "$p ${p.length} ${p.toSet().size}" )

    for ( xx in 'a' .. 'z' ) {
	val num = all.count ( { it.get(0) == xx } )
	println ( "$num lines begin with $xx" )
    }
}

// this "bogus" function is true if the string is
// a repeat of a single character and has length > 1
fun bogus (x : String ): Boolean = x.length > 1 && x.toSet().size == 1

class Reader ( var path : String ) {

    // shorthand for one line function body
    fun show () = println ( "File: $path" )

    fun readAll () : ArrayList ?
    {
	val buflen = 1024
	val rv = ArrayList()

	val file = fopen ( path, "r" )
	if ( file == null ) {
	    println ("Cannot open input file: $path")
	    return null
	}

	memScoped {
	    val buffer = allocArray(buflen)
	    while ( true ) {
		var cline = fgets(buffer, buflen, file)
		if ( cline == null )
		    break

		var line = cline.toKString().trimEnd()
		if ( line.get(0) == '#' )
		    continue
		rv.add ( line )
		// println ( line.trimEnd() )
	    }
	}

	return rv
    }
}

// THE END

Have any comments? Questions? Drop me a line!

Adventures in Computing / tom@mmto.org