All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jtransc.util.explore.kt Maven / Gradle / Ivy

/*
 * Copyright 2016 Carlos Ballesteros Velasco
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jtransc.util

import com.jtransc.ds.Queue
import com.jtransc.error.InvalidOperationException
import java.util.*

fun  recursiveExploration(initialItems: Set, performExploration: (item: T) -> Iterable): Set {
	return recursiveExploration(initialItems, null, performExploration)
}

fun  recursiveExploration(initialItems: Set, extra: ((item:T) -> Iterable)?, performExploration: (item: T) -> Iterable): Set {
	val explored = HashSet(initialItems)
	val toExploreList = Queue(initialItems)

	fun explore(item: T?) {
		if (item != null && item !in explored) {
			explored.add(item)
			toExploreList.queue(item)
		}
	}

	do {
		while (toExploreList.hasMore) {
			val toExplore = toExploreList.dequeue()
			for (item in performExploration(toExplore)) explore(item)
		}
		if (extra != null) {
			explored.toList().forEach {
				extra(it).forEach {
					explore(it)
				}
			}
		}
	} while (toExploreList.hasMore)

	return explored
}

fun  List.dependencySorter(allowCycles:Boolean = false, getDependencies: (item:T) -> List):List {
	return this.dependencySorterOld(allowCycles, getDependencies)
}

// @TODO: Optimize this
// This could construct a tree with a root node all items depend on.
// We should remove items that depend on root but also depends on other stuff.
// Later we should iterate the tree from leafs to root. This should be order
// of magnitudes faster with lots of items.
fun  List.dependencySorterOld(allowCycles:Boolean = false, getDependencies: (item:T) -> List):List {
	val all = this
	val usages = LinkedHashMap>()
	val dependencies = LinkedHashMap>()
	for (it in all) usages[it] = arrayListOf()

	for (it in all) {
		val deps = getDependencies(it).toSet() - it
		dependencies[it] = deps.toCollection(arrayListOf())
		for (dep in deps) usages[dep]?.add(it)
	}

	// @TODO: Optimize this
	val out = arrayListOf()
	while (usages.isNotEmpty()) {
		//println("Usages:" + usages.size)
		//val emptyItem = usages.entries.firstOrNull { it.value.isEmpty() } ?: usages.entries.first()
		val emptyItem = if (allowCycles) {
			usages.entries.firstOrNull { it.value.isEmpty() } ?: usages.entries.first()

		} else {
			usages.entries.firstOrNull { it.value.isEmpty() } ?: throw InvalidOperationException("Cycle detected!")
		}
		val item = emptyItem.key
		usages.remove(item)
		for (a in dependencies[item]!!) {
			usages[a]?.remove(item)
		}
		out.add(item)
		//println(item)
	}

	return out.reversed()
}



fun  sortDependenciesSimple(entry:T, getDependencies: (item:T) -> List):List {
	var out = arrayListOf()
	fun step(item:T, used:MutableSet = hashSetOf()) {
		if (item in used) return
		used.add(item)
		for (dep in getDependencies(item)) step(dep, used)
		out.add(item)
	}
	step(entry)
	return out
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy