From 8fbcfdf09c3ebf5771070c4aef742ada6a4426a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Segovia=20C=C3=B3rdoba?= Date: Sat, 29 Jul 2023 18:01:30 +0200 Subject: [PATCH] Add `Graph.toGraphSortedByEdges: Graph` --- CHANGELOG.md | 2 ++ kotlin-stdlib/api/android/kotlin-stdlib.api | 3 ++ kotlin-stdlib/api/jvm/kotlin-stdlib.api | 3 ++ .../com/javiersc/kotlin/stdlib/graph/Graph.kt | 28 +++++++++++++++++ .../com/javiersc/kotlin/stdlib/GraphTest.kt | 31 +++++++++++++++++++ 5 files changed, 67 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9184f87c..0ab3dbf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added +- `Graph.toGraphSortedByEdges: Graph` + ### Changed ### Deprecated diff --git a/kotlin-stdlib/api/android/kotlin-stdlib.api b/kotlin-stdlib/api/android/kotlin-stdlib.api index 18118bac..a6ae3ee0 100644 --- a/kotlin-stdlib/api/android/kotlin-stdlib.api +++ b/kotlin-stdlib/api/android/kotlin-stdlib.api @@ -206,6 +206,7 @@ public abstract interface class com/javiersc/kotlin/stdlib/graph/Graph : java/ut public abstract fun renderer (Lkotlin/jvm/functions/Function1;)V public abstract fun setRenderer (Lkotlin/jvm/functions/Function1;)V public abstract fun toGraph ()Lcom/javiersc/kotlin/stdlib/graph/Graph; + public abstract fun toGraphSortedByEdges ()Lcom/javiersc/kotlin/stdlib/graph/Graph; public abstract fun vertexesFor (Ljava/lang/Object;)Ljava/util/List; public abstract fun vertexesFor ([Ljava/lang/Object;)Ljava/util/List; } @@ -222,6 +223,7 @@ public final class com/javiersc/kotlin/stdlib/graph/Graph$DefaultImpls { public static fun getHasMissingVertexes (Lcom/javiersc/kotlin/stdlib/graph/Graph;)Z public static fun renderer (Lcom/javiersc/kotlin/stdlib/graph/Graph;Lkotlin/jvm/functions/Function1;)V public static fun toGraph (Lcom/javiersc/kotlin/stdlib/graph/Graph;)Lcom/javiersc/kotlin/stdlib/graph/Graph; + public static fun toGraphSortedByEdges (Lcom/javiersc/kotlin/stdlib/graph/Graph;)Lcom/javiersc/kotlin/stdlib/graph/Graph; public static fun vertexesFor (Lcom/javiersc/kotlin/stdlib/graph/Graph;Ljava/lang/Object;)Ljava/util/List; public static fun vertexesFor (Lcom/javiersc/kotlin/stdlib/graph/Graph;[Ljava/lang/Object;)Ljava/util/List; } @@ -313,6 +315,7 @@ public final class com/javiersc/kotlin/stdlib/graph/MutableGraph : com/javiersc/ public fun setRenderer (Lkotlin/jvm/functions/Function1;)V public final fun size ()I public fun toGraph ()Lcom/javiersc/kotlin/stdlib/graph/Graph; + public fun toGraphSortedByEdges ()Lcom/javiersc/kotlin/stdlib/graph/Graph; public fun toString ()Ljava/lang/String; public final fun values ()Ljava/util/Collection; public fun vertexesFor (Ljava/lang/Object;)Ljava/util/List; diff --git a/kotlin-stdlib/api/jvm/kotlin-stdlib.api b/kotlin-stdlib/api/jvm/kotlin-stdlib.api index 96265183..b7d8112b 100644 --- a/kotlin-stdlib/api/jvm/kotlin-stdlib.api +++ b/kotlin-stdlib/api/jvm/kotlin-stdlib.api @@ -212,6 +212,7 @@ public abstract interface class com/javiersc/kotlin/stdlib/graph/Graph : java/ut public abstract fun renderer (Lkotlin/jvm/functions/Function1;)V public abstract fun setRenderer (Lkotlin/jvm/functions/Function1;)V public abstract fun toGraph ()Lcom/javiersc/kotlin/stdlib/graph/Graph; + public abstract fun toGraphSortedByEdges ()Lcom/javiersc/kotlin/stdlib/graph/Graph; public abstract fun vertexesFor (Ljava/lang/Object;)Ljava/util/List; public abstract fun vertexesFor ([Ljava/lang/Object;)Ljava/util/List; } @@ -228,6 +229,7 @@ public final class com/javiersc/kotlin/stdlib/graph/Graph$DefaultImpls { public static fun getHasMissingVertexes (Lcom/javiersc/kotlin/stdlib/graph/Graph;)Z public static fun renderer (Lcom/javiersc/kotlin/stdlib/graph/Graph;Lkotlin/jvm/functions/Function1;)V public static fun toGraph (Lcom/javiersc/kotlin/stdlib/graph/Graph;)Lcom/javiersc/kotlin/stdlib/graph/Graph; + public static fun toGraphSortedByEdges (Lcom/javiersc/kotlin/stdlib/graph/Graph;)Lcom/javiersc/kotlin/stdlib/graph/Graph; public static fun vertexesFor (Lcom/javiersc/kotlin/stdlib/graph/Graph;Ljava/lang/Object;)Ljava/util/List; public static fun vertexesFor (Lcom/javiersc/kotlin/stdlib/graph/Graph;[Ljava/lang/Object;)Ljava/util/List; } @@ -319,6 +321,7 @@ public final class com/javiersc/kotlin/stdlib/graph/MutableGraph : com/javiersc/ public fun setRenderer (Lkotlin/jvm/functions/Function1;)V public final fun size ()I public fun toGraph ()Lcom/javiersc/kotlin/stdlib/graph/Graph; + public fun toGraphSortedByEdges ()Lcom/javiersc/kotlin/stdlib/graph/Graph; public fun toString ()Ljava/lang/String; public final fun values ()Ljava/util/Collection; public fun vertexesFor (Ljava/lang/Object;)Ljava/util/List; diff --git a/kotlin-stdlib/common/main/kotlin/com/javiersc/kotlin/stdlib/graph/Graph.kt b/kotlin-stdlib/common/main/kotlin/com/javiersc/kotlin/stdlib/graph/Graph.kt index 583f8065..24bdb777 100644 --- a/kotlin-stdlib/common/main/kotlin/com/javiersc/kotlin/stdlib/graph/Graph.kt +++ b/kotlin-stdlib/common/main/kotlin/com/javiersc/kotlin/stdlib/graph/Graph.kt @@ -61,6 +61,34 @@ public interface Graph : Map, List>> { public fun vertexesFor(vararg values: T): List = values.flatMap(::vertexesFor) + public fun toGraphSortedByEdges(): Graph = buildGraph { + val sortedGraph: MutableGraph = this + val graph: Graph = this@Graph + val remainingMap: MutableMap, List>> = graph.toMutableMap() + while (remainingMap.isNotEmpty()) { + val vertexesToBeRemoved: MutableList> = mutableListOf() + for ((vertex: Vertex, edges: List>) in remainingMap) { + if (edges.isEmpty()) { + sortedGraph.addVertex(vertex.value) + vertexesToBeRemoved.add(vertex) + println() + } + for (edge: Edge in edges) { + if (edge.destination.value in sortedGraph.keys.map(Vertex::value)) { + sortedGraph.addVertex(edge.source.value) + sortedGraph.addEdge(edge.source.value, edge.destination.value) + vertexesToBeRemoved.add(edge.source) + println() + } + } + } + for (vertexToBeRemoved: Vertex in vertexesToBeRemoved) { + remainingMap.remove(vertexToBeRemoved) + } + vertexesToBeRemoved.clear() + } + } + public fun renderer(block: Any?.() -> String) { this.renderer = block } diff --git a/kotlin-stdlib/common/test/kotlin/com/javiersc/kotlin/stdlib/GraphTest.kt b/kotlin-stdlib/common/test/kotlin/com/javiersc/kotlin/stdlib/GraphTest.kt index 5fccb3c1..dbf5ef5f 100644 --- a/kotlin-stdlib/common/test/kotlin/com/javiersc/kotlin/stdlib/GraphTest.kt +++ b/kotlin-stdlib/common/test/kotlin/com/javiersc/kotlin/stdlib/GraphTest.kt @@ -310,6 +310,37 @@ class GraphTest { assertTrue { graph.vertexesFor(Qux) == listOf(Quux) } assertTrue { graph.vertexesFor(Quux) == emptyList() } } + + @Test + fun vertexes_sorted_by_edges() { + val graph: Graph = buildGraph { + addVertex(Bar) + addVertex(Foo) + addVertex(Baz) + addEdge(Bar, Baz) + addEdge(Foo, Bar) + } + + assertTrue { + val actual: String = graph.toString() + val expect: String = buildString { + appendLine("Bar -> [Baz]") + appendLine("Foo -> [Bar]") + appendLine("Baz -> []") + } + expect == actual + } + + assertTrue { + val actual: String = graph.toGraphSortedByEdges().toString() + val expect: String = buildString { + appendLine("Baz -> []") + appendLine("Bar -> [Baz]") + appendLine("Foo -> [Bar]") + } + expect == actual + } + } } private object Foo : A()