Home > Blockchain >  I did not get the Desired Outcome for this Question in Kotlin?
I did not get the Desired Outcome for this Question in Kotlin?

Time:08-28

So I was creating an adjacency list from an Undirected Graph

 val presentedGraph = listOf(
     listOf('i', 'j'),
     listOf('k', 'i'),
     listOf('m', 'k'),
     listOf('k', 'l'),
     listOf('o', 'n')
 )

The outcome that I was looking for was this

hashMapOf(
        'i' to listOf('j', 'k'),
        'j' to listOf('i'),
        'k' to listOf('i', 'm', 'l'),
        'm' to listOf('k'),
        'l' to listOf('k'),
        'o' to listOf('n'),
        'n' to listOf('o')
    )

But got this instead

{i=[i], j=[j], k=[k], l=[l], m=[m], n=[n], o=[o]}

Here's the code for it

fun undirectedPath (edges: List<List<Char>>, root: Char, destination: Char){
    val graph = buildGraph(edges)
    println(graph)

}
fun buildGraph(edges: List<List<Char>>): HashMap<Char, List<Char>>{
    val graph = hashMapOf<Char, List<Char>>()

    for (i in edges.indices){
        for (j in edges[i].indices){
            val a = edges[i][j]
            val b = edges[i][j]
            if (!graph.containsKey(a)) { graph[a] = listOf() }
            if (!graph.containsKey(b)) { graph[b] = listOf() }
            graph[a] = listOf(b)
            graph[b] = listOf(a)
        }
    }
    return graph
}

Any help will be appreciated, Thank You.

CodePudding user response:

Several things wrong here:

  • The fact that you're setting both a and b to the same expression ought to be a clue that one of them is wrong! In fact a should be set to edges[i][0].
  • Because j runs from 0, it effectively assumes an extra edge from each node to itself. To avoid that, j should skip the first item and start from 1.
  • Each time you assign graph[a] and graph[b], you discard any previous items. That's why the result has only one target for each edge. To fix that, you need to add() the target to the existing list…
  • …which means that each target list must be a MutableList.

Those changes should be enough to get the result you want.

However, there are still several code smells present. For one thing, the input is a list of lists — but each of the inner lists has exactly two items. It would be neater to use a more precise structure, such as a Pair.

And it's always worth being aware of the standard library, which includes a wide range of manipulations and algorithms. In this case, you could replace the whole function with a one-liner:

fun buildGraph(edges: List<Pair<Char, Char>>)
    = (edges   edges.map{ it.second to it.first })
    .groupBy({ it.first }, { it.second })

As well as being a good deal shorter, that also makes it a good deal clearer what it's doing: combining the list of edges with the reverse list, and returning a map from each node to the list of nodes it connects to/from.

CodePudding user response:

You can try this.

  val hashMap = HashMap<Char, ArrayList<Char>>()
    presentedGraph.forEach { list ->
        list.forEach { char ->
            if (!hashMap.containsKey(char)) {
                hashMap[char] = arrayListOf()
            }
            hashMap[char]?.addAll(list.filter { char != it }.toList().distinct())
        }
    }
    println(hashMap)

Output:

{i=[j, k], j=[i], k=[i, m, l], l=[k], m=[k], n=[o], o=[n]}
  • Related