```fun findCombs(res: List<String>, digis: L...
# announcements
w
Copy code
fun findCombs(res: List<String>, digis: List<Int>) : List<String> = if (digitss.isEmpty()) res 
        else for (letter in map[digis[0]]) findCombs(res + letter, digis.subList(1, digis.lastIndex))
r
What do you expect the function to return, if
digis
is not empty?
Right now, the else branch just executes a for-loop, and doesn't return anything. That's a problem, because the function is declared to always return a
List<String>
, but right now it doesn't.
w
yeah I know that but I want it to recurse in the for loop when its non empty
so whats the best way to do that?
make it optionally null?
r
Well, even a recursion has to return at some point. I don't know what you're trying to do with the function, so I can just take a guess - do you want to collect the result of each recursive call in a list and return that? Kotlin can't guess that for you, you have to tell it.
w
uhh its a problem where you find all combination using those old nokia keyboards
Copy code
fun findCombs(res: List<String>, digis: List<Int>) : List<String> {
            if (digitss.isEmpty()) return res
            for (letter in map[digis[0]]) findCombs(res + letter, digis.subList(1, digis.lastIndex))
        }
I fixed it like this
not as graceful...but il take it
now the issue is
for (letter in map[digis[0]])
is throwing an error as hashmap is nullable
for (letter in map!![digis[0]])
still throws the error though
any idea how to fix this?
a
map.getValue
r
That shouldn't work either, as soon as you fix that error the original will pop up again as you're still not returning a value
Does this work?
Copy code
fun findCombs(res: List<String>, digis: List<Int>): List<String> =
    if (digis.isEmpty()) {
        res
    } else {
        map[digis[0]]!!.flatMap { letter ->
            findCombs(res + letter, digis.subList(1, digis.lastIndex))
        }
    }
@arekolek I didn't think the logic through completely from the incomplete example, but that might very well be what's needed here. If that's the case, it can be simplified further, though:
Copy code
fun findCombs(digits: List<Int>) : List<String> =
    digits.flatMap { map.getValue(it) }
a
actually, I think he wants all the combinations, so that wouldn't be it
I understand that
map
is
val map: Map<Int, List<String>>
so it'd be more like:
Copy code
fun findCombs(digits: List<Int>): List<String> {
    return digits.fold(listOf("")) { acc, i ->
        acc.flatMap { prefix ->
            map.getValue(i).map { suffix ->
                prefix + suffix
            }
        }
    }
}
w
@arekolek I'm a little confused as to how your code above works
if
acc
is initially empty, then why will
acc.flatmap
have even one 'iteration' (i.e. there is no
prefix
present)
a
at first I put there
emptyList()
and then there were indeed zero iterations
once I put
listOf("")
that's different
there's one element in the accumulator, the empty string
w
right so, listOf("") means there is one element, sn empty string
gotcha! very clever
I'm fond of one liner solutions (or well, one expression) like this
but they're hard to come up with..
a
somehow it was easier to reason about for me than recursion 😛
😁 1
w
meanwhile, any idea why my attempt doesn't work?
Copy code
fun findCombs(res: List<String>, digis: List<Int>) : List<String> {
            if (digitss.isEmpty()) return res
            for (letter in map?.getValue(digis[0])) findCombs(res + letter, digis.subList(1, digis.lastIndex))
        }
a
like Robin said above, you never return anything if
if
is not true
w
type inference fails on
res + letter
oh that initial issue is solved...this is something to do with type parameters I think
a
map.getValue(digis[0])
should be enough
but I don't know what your
map
type is, so it's difficult to say what's wrong
w
and nice, may i don't have enough practice with flatmap etc. to come with intuitive solution with it
yes that works indeed
?.
was unnecessary
here is the map:
Copy code
val map: HashMap<Int, List<Char>> = hashMapOf(2 to listOf('a','b','c'), 3 to listOf('d','e','f'), 4 to listOf('g','h','i'), 5 to listOf('j','k','l'),
                6 to listOf('m','n','o'), 7 to listOf('p','q','r', 's'), 8 to listOf('t','u', 'v'), 9 to listOf('w','x','y','z'))
duh! wrong types one was String, other Char
damn that was stupid of me
thanks anyways!
a
probably you need
res.map { it + letter }
(
res + letter.toString()
would make the types agree, but I think that's far from working code)
w
yeah the issue was, it should be List<char> instead of List<String>
because of the map
a
as far as your code goes, I think it should be something along the lines of:
Copy code
fun findCombs(res: List<String>, digits: List<Int>) : List<String> {
    if (digits.isEmpty()) return res
    val results = mutableListOf<String>()
    for (letter in map.getValue(digits[0])) {
        results += findCombs(res.map { it + letter }, digits.drop(1))
    }
    return results
}

findCombs(listOf(""), listOf(2, 7, 3, 5))
it does basically the same thing as
fold.flatMap.map
did
w
so in the code you gave here, shouldn't
result
be set to whatever
res
contained?
to ensure all results are combined
okay i get it now