import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Random; public class RainbowGenerator { int numEdges; int numColors; int branches; int numSeeds; public RainbowGenerator(int numEdges, int numColors, int branches, int numSeeds) { this.numEdges = numEdges; this.numColors = numColors; this.branches = branches; this.numSeeds = numSeeds; nodes = new ArrayList<>(); } /** * Run generator with arguments: * * numberOfVertices numberOfColors numberOfSeeds [branchingLimit] * * A "seed" is a deliberate change of an edge to be of the same color * as an adjacent edge. If 0, all vertices should be good. * * The branchingLimit is optional and places a limt on the number of * out edges any node in the tree can have. If not specified, defaults to * the number of colors. */ public static void main(String[] args) { int numVertices = Integer.parseInt(args[0]); int numEdges = numVertices - 1; int numColors = Integer.parseInt(args[1]); int numSeeds = Integer.parseInt(args[2]); int branches = numColors; if (args.length > 3) { branches = Integer.parseInt(args[3]); } new RainbowGenerator(numEdges, numColors, branches, numSeeds).run(); } ArrayList nodes; class TreeNode { int nodeNum; TreeNode parent; List children; int color; TreeNode (TreeNode parent, int color) { nodeNum = nodes.size(); nodes.add(this); this.parent = parent; children = new ArrayList<>(); this.color = color; } } TreeNode root; Random rand = new Random(); private void run() { root = new TreeNode(null, 0); generateTree (root, numEdges); modifyTree(); printTree(); } private void printTree() { System.out.println("" + (numEdges + 1)); for (TreeNode t: nodes.get(0).children) { traverseAndPrint(t); } } private void traverseAndPrint(TreeNode t) { for (TreeNode child: t.children) { traverseAndPrint(child); } System.out.println("" + (t.parent.nodeNum+1) + " " + (t.nodeNum+1) + " " + (t.color+1)); } private void modifyTree() { HashSet seeds = new HashSet<>(); int i = 0; while (i < numSeeds) { int seedNum = 1 + rand.nextInt(numEdges); if (!seeds.contains(seedNum)) { seeds.add(seedNum); TreeNode t = nodes.get(seedNum); if (t.children.size() > 0) { int cnum = rand.nextInt(t.children.size()); TreeNode child = t.children.get(cnum); child.color = t.color; ++i; } } } } private void generateTree(TreeNode asDescendentsOf, int numVerticesNeeded) { if (numVerticesNeeded <= 0) return; int maxChildren = Math.min(numVerticesNeeded, Math.min(numColors-1, branches)); int numChildren = (maxChildren > 1) ? 1 + rand.nextInt(maxChildren) : maxChildren; int startingColor = rand.nextInt(numColors); if (startingColor == asDescendentsOf.color) { startingColor = (startingColor + 1) % numColors; } int neededDescendents = numVerticesNeeded - numChildren; for (int child = 0; child < numChildren; ++child) { TreeNode n = new TreeNode(asDescendentsOf, startingColor); startingColor = (startingColor + 1) % numColors; if (startingColor == asDescendentsOf.color) { startingColor = (startingColor + 1) % numColors; } asDescendentsOf.children.add(n); int numDescendentsThisChild = 0; if (neededDescendents > 0) { numDescendentsThisChild = 1 + rand.nextInt(neededDescendents); if (child == numChildren - 1) { numDescendentsThisChild = neededDescendents; } generateTree(n, numDescendentsThisChild); neededDescendents -= numDescendentsThisChild; } } } }