Skip to content

Instantly share code, notes, and snippets.

@saka1029
Last active February 12, 2016 23:05
Show Gist options
  • Save saka1029/54ced0d6f73128dfa577 to your computer and use it in GitHub Desktop.
Save saka1029/54ced0d6f73128dfa577 to your computer and use it in GitHub Desktop.
Dependency Algorithm - find a minimum set of packages to install
package stackoverflow.dependency;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Dependency {
public static class Node {
final String name;
final List<String> and = new ArrayList<>();
final List<String> or = new ArrayList<>();
Node(String name) {
this.name = name;
}
public Node and(String... and) {
for (String e : and)
this.and.add(e);
return this;
}
public Node or(String... or) {
for (String e : or)
this.or.add(e);
return this;
}
@Override
public String toString() {
return name + " and" + and + " or" + or;
}
}
final Map<String, Node> map = new HashMap<>();
public Node node(String name) {
Node node = map.get(name);
if (node == null)
map.put(name, node = new Node(name));
return node;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Node e : map.values())
sb.append(e).append("\n");
return sb.toString();
}
public Node get(String name) {
return map.get(name);
}
static void expand(List<List<String>> targetOr, int index, List<String> set, List<Set<String>> expanded) {
int size = targetOr.size();
if (index >= size)
expanded.add(new HashSet<>(set));
else
for (String s : targetOr.get(index)) {
set.add(s);
expand(targetOr, index + 1, set, expanded);
set.remove(set.size() - 1);
}
}
public List<String> dependents(String start) {
List<String> targetAnd = new ArrayList<>();
List<List<String>> targetOr = new ArrayList<>();
List<String> result = new ArrayList<>();
targetAnd.add(start);
while (!targetAnd.isEmpty()) {
System.out.println("target=AND" + targetAnd + " OR" + targetOr + ", result=" + result);
String single = targetAnd.remove(0);
Node singleNode = get(single);
result.add(single);
for (Iterator<List<String>> i = targetOr.iterator(); i.hasNext(); )
if (i.next().contains(single))
i.remove();
System.out.println("target=AND" + targetAnd + " OR" + targetOr + ", result=" + result);
targetAnd.addAll(singleNode.and);
if (singleNode.or.size() > 0)
targetOr.add(singleNode.or);
}
if (!targetOr.isEmpty()) {
List<Set<String>> expanded = new ArrayList<>();
expand(targetOr, 0, new ArrayList<>(), expanded);
System.out.println("expanded=OR" + expanded);
int min = Integer.MAX_VALUE;
Set<String> minSet = null;
for (Set<String> set : expanded)
if (set.size() < min) {
min = set.size();
minSet = set;
}
result.addAll(minSet);
}
return result;
}
public static void main(String[] args) {
Dependency d = new Dependency();
d.node("X").and("A").or("E", "C");
d.node("E").and("B").or("Y", "Z");
d.node("A").and("E").or("H", "Y");
d.node("C").or("A", "K");
d.node("Z");
d.node("B");
d.node("H");
d.node("K");
System.out.println(d);
List<String> result = d.dependents("X");
System.out.println(result);
// A and[E] or[H, Y]
// B and[] or[]
// C and[] or[A, K]
// E and[B] or[Y, Z]
// X and[A] or[E, C]
// H and[] or[]
// Z and[] or[]
// K and[] or[]
//
// target=AND[X] OR[], result=[]
// target=AND[] OR[], result=[X]
// target=AND[A] OR[[E, C]], result=[X]
// target=AND[] OR[[E, C]], result=[X, A]
// target=AND[E] OR[[E, C], [H, Y]], result=[X, A]
// target=AND[] OR[[H, Y]], result=[X, A, E]
// target=AND[B] OR[[H, Y], [Y, Z]], result=[X, A, E]
// target=AND[] OR[[H, Y], [Y, Z]], result=[X, A, E, B]
// expanded=OR[[H, Y], [H, Z], [Y], [Y, Z]]
// [X, A, E, B, Y]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment