Brand new to Kotlin, how can I find the factors of a number?
For example 24 should give 1, 2, 3, 4, 6, 8, 12, 24?
I know how to do this python with a list comprehension but not sure how to do it properly in Kotlin.
Brand new to Kotlin, how can I find the factors of a number?
For example 24 should give 1, 2, 3, 4, 6, 8, 12, 24?
I know how to do this python with a list comprehension but not sure how to do it properly in Kotlin.
Not sure how you could do a "list comprehension" in Kotlin but instead you can use a function like factorsOfNumbers
below:
fun factorsOfNumber(num: Int) : MutableList<Int> {
val factors = mutableListOf<Int>()
if (num < 1)
return factors
(1..num / 2)
.filter { num % it == 0 }
.forEach { factors.add(it) }
factors.add(num)
return factors
}
fun main(args: Array<String>) {
val number = 24
println("The factors of $number are: " + factorsOfNumber(number).joinToString())
}
Output:
The factors of 24 are: 1, 2, 3, 4, 6, 8, 12, 24
Relevant documentation to understand how it works is below:
(1..num / 2)
part)Let's see the exact equivalent between Python and Kotlin...
In Python, the code would be:
N = 24
factors = [n for n in range(1, N + 1) if N % n == 0]
print(factors)
# outputs [1, 2, 3, 4, 6, 8, 12, 24]
Which is not lazy, and materializes as a list. In Kotlin this is:
val N = 24
val factors = (1..N).filter { N % it == 0 }
println(factors)
// outputs [1, 2, 3, 4, 6, 8, 12, 24]
If you want to make this slightly more efficient:
val factors = (1..N/2).filter { N % it == 0 } + N
Now since this is not lazy, it does one copy of the factor results to add the final N
value, although that list would be a lot smaller than the original. And sometimes an eager copy of smaller data structures is faster than a lazy evaluation.
You can make this whole thing lazy lazy, and process it incrementally taking only the values you want:
val factors = (1..N).asSequence().filter { N % it == 0 }
or the variant of only processing half the values:
val factors = (1..N/2).asSequence().filter { N % it == 0 } + N
Both of these result in a sequence that can be read lazily and chained with other functions.
You can also use co-routines to write a function that lazily yields the values, and here is written as an extension function on Int
:
fun Int.factorsSequence(): Sequence<Int> {
val N = this
return buildSequence {
(1..N/2).forEach {
if (N % it == 0) yield(it)
}
yield(N)
}
}
Which can be called like:
val factors = 24.factorsSequence()
println(factors.toList()) // convert to list just for printing
Of course, any of the other implementations can be made extension functions as well.
fun Int.factorsList(): List<Int> =
(1..this/2).filter { this % it == 0 } + this
val factors = 24.factorsList()
println(factors)