Before I go into another possible solution I will give you some suggestions on your current code:
Use val
instead of var
whenever possible. This is possible for all variables in your code.
No need to specify <Int>
on setOf
, Kotlin can figure out the best applicable type itself.
The function twoInThree
is capable of handling any kinds of sets, not just ints. You can use a generic type parameter for this.
Change the method to fun <T> twoInThree(a: Set<T>, b: Set<T>, c: Set<T>): MutableSet<T>
And naturally also val results = mutableSetOf<T>()
Prefer to return immutable types unless you really need to do otherwise, in this case prefer to return a Set
over MutableSet
(callers don't need to care about the fact that you are using a MutableSet in your implementation)
The approach
Your approach involves checking for multiple intersections and then creating a union of all sets and removing the intersection of all sets.
The assignment is about finding elements which exists in exactly two of the three given sets a, b, c.
Your approach is fine, there's nothing wrong with it, but... Will it scale?
If you would check for elements which exists in all three of the sets, or in exactly one set, that could be done quite easily by returning different intersections and unions and so on. But what if there would be five sets?
The assignment is about exactly two of the three sets.
One, two, three.
We can use counting!
By counting the number of times each element appears, we can iterate over all sets (no matter if it's three, five, or twenty) exactly once.
By counting the number of times each element appears, we can easily change the code to return elements that occur only once, twice, or three times.
So how to do this?
My approach
Start with creating a list of all sets. listOf(a, b, c)
Then go through the list and map each set to all its elements. .flatMap { it }
which can also be written as .flatten()
Then create a grouping of the elements .groupingBy { it }
Then create a map with the counts of each element .eachCount()
listOf(a, b, c).flatten().groupingBy { it }.eachCount()
This gives you a map Map<Int, Int>
where the keys are the elements and the values are the number of times each element occurs.
Now you can filter this map and return the keys which matches your requirement .filter { it.value == 2 }.map { it.key }
Full code:
val result = listOf(a, b, c).flatten()
.groupingBy { it }
.eachCount()
.filter { it.value == 2 }
.map { it.key }