5

I have the following Kotlin function:

fun func(n: Int): Int {

    var count = 1

    var m = n
    while(m != 1) {

        m = if(m.isOdd()) 3 * m + 1 else m / 2

        count++
    }

    return count
}

I would like to write that simple algorithm in a "functional" style, using Kotlin's operators like map(), count(), etc. The closest thing I could come up with was this:

fun func(n: Int): Int {

    return n.toList()
            .map{ if(it.isOdd()) 3*it+1 else it/2 }
            .takeWhile { it != 1 }
            .count()

}

Obviously, the above code does not work because map is executed only once, but you get the idea of what I am trying to achieve.

PS: toList() is just an extension function that converts an int to a list containing that int:

fun Int.toList() = listOf(this)
2
  • While @hotkey probably provided the right answer, I think we all should agree that your original code is actually more memory efficient and will not result in creating a sequence with potentially thousands elements just to find out how many elements were generated. Commented Aug 17, 2017 at 0:37
  • @Strelok That is a good point. What I was looking for is a solution where all variables were immutable and hotkey's answer delivers that. However, if someone knows a way to do the same thing but 'discarding elements on-the-fly' (so memory is not an issue) please let us know. Commented Aug 17, 2017 at 0:43

1 Answer 1

10

Since you do not know how many items there will be, you can construct a (possibly infinite) sequence where each item is calculated based on the previous one, then limit it with your condition it != 1 and count how many items there are:

return generateSequence(n) { if (it.isOdd()) 3 * it + 1 else it / 2 }
        .takeWhile { it != 1 }
        .count()

Here, generateSequence(n) { ... }, constructs a Sequence<Int> that has n for its first element, and each of the following elements is calculated by the code passed as a lambda (it is called on the previous element, and only when another item is queried, i.e. lazily).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.