August 27, 2024

P86 - Node degree and graph coloration.

a) Write a method Node.degree that determines the degree of a given node in an undirected graph.

> "[a-b, b-c, a-c, a-d]".toGraph().nodes["a"].degree()
3

b) Use Welsh-Powell's algorithm to paint the nodes of an undirected graph in such a way that adjacent nodes have different colors. Write a method colorNodes that returns a list of tuples, each of which contains a node and an integer representing its color.

> "[a-b, b-c, a-c, a-d]".toGraph().colorNodes()
[(a,1), (b,2), (c,3), (d,2)]

kotlin

package org.kotlin99.graphs

import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import org.junit.Test
import org.kotlin99.common.containsAll
import java.util.*

fun <V> Graph.Node<V, *>.degree(): Int = this.edges.size

fun <V> Graph<V, *>.colorNodes(): List<Pair<V, Int>> {
    val colorByNode = LinkedHashMap<V, Int>()
    val nodeList = nodes.values.sortedBy { -it.degree() }.toMutableList()
    var color = 1

    while (nodeList.isNotEmpty()) {
        nodeList.forEach { node ->
            val hasSameColorNeighbour = node.neighbors().any { colorByNode[it.value] == color }
            if (!hasSameColorNeighbour) {
                colorByNode[node.value] = color
            }
        }
        nodeList.removeAll { colorByNode.containsKey(it.value) }
        color += 1
    }

    return colorByNode.entries.map { Pair(it.key, it.value) }
}


class P86Test {
    @Test fun `node degree in undirected graph`() {
        assertThat("[a]".toGraph().nodes["a"]!!.degree(), equalTo(0))

        "[a-b]".toGraph().let {
            assertThat(it.nodes["a"]!!.degree(), equalTo(1))
            assertThat(it.nodes["b"]!!.degree(), equalTo(1))
        }

        "[a-b, a-c]".toGraph().let {
            assertThat(it.nodes["a"]!!.degree(), equalTo(2))
            assertThat(it.nodes["b"]!!.degree(), equalTo(1))
            assertThat(it.nodes["c"]!!.degree(), equalTo(1))
        }

        "[a-b, b-c, a-c, a-d]".toGraph().let {
            assertThat(it.nodes["a"]!!.degree(), equalTo(3))
            assertThat(it.nodes["b"]!!.degree(), equalTo(2))
            assertThat(it.nodes["c"]!!.degree(), equalTo(2))
            assertThat(it.nodes["d"]!!.degree(), equalTo(1))
        }
    }

    @Test fun `color nodes of undirected graph (so that adjacent nodes have different color)`() {
        assertThat("[a]".toGraph().colorNodes(), containsAll(listOf(Pair("a", 1))))
        assertThat("[a-b]".toGraph().colorNodes(), containsAll(listOf(Pair("a", 1), Pair("b", 2))))
        assertThat("[a-b, a-c]".toGraph().colorNodes(), containsAll(listOf(Pair("a", 1), Pair("b", 2), Pair("c", 2))))
        assertThat("[a-b, b-c, c-d]".toGraph().colorNodes(), containsAll(listOf(Pair("a", 2), Pair("b", 1), Pair("c", 2), Pair("d", 1))))

        assertThat("[a-b, a-c, b-c]".toGraph().colorNodes(), containsAll(listOf(
            Pair("a", 1),
            Pair("b", 2),
            Pair("c", 3)
        )))

        assertThat("[a-b, b-c, a-c, a-d]".toGraph().colorNodes(), containsAll(listOf(
            Pair("a", 1),
            Pair("b", 2),
            Pair("c", 3),
            Pair("d", 2)
        )))
    }
}
Be first to comment
Leave a reply