Last active
December 31, 2015 02:49
-
-
Save 0x1b-xyz/7923448 to your computer and use it in GitHub Desktop.
Print a hierarchical tree from a direct relationship model
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Tree { | |
| private model = new HashMap<String, Set<String>>() | |
| void add(String node, String dep) { | |
| if (!model[node]) | |
| model[node] = new HashSet<String>(); | |
| model[node] << dep | |
| } | |
| /** | |
| * Finds each node with no incoming edges and treats it as a root of the printed tree. | |
| */ | |
| String toString() { | |
| def buf = new StringBuilder() | |
| model.keySet().findAll { node -> !model.values().find { deps -> deps.contains(node)} } | |
| .each { node -> | |
| render(buf, true, node, '', '') | |
| } | |
| buf.toString() | |
| } | |
| private void render(Stack<String> ancestry = [], StringBuilder buf, | |
| boolean isRoot, String node, String lead, String tick) { | |
| def isCyclic = ancestry.contains(node) | |
| buf.append("${lead}${tick}${isRoot ? '' : '_ '}${node}${isCyclic ? ' *' : ''}\n") | |
| if (isCyclic) return; | |
| def deps = model[node] | |
| if (deps) | |
| ancestry.push(node) | |
| else return | |
| def spacing = isRoot ? lead : "${lead} " | |
| deps.sort().eachWithIndex { String dep, int i -> | |
| def isLast = (i == (deps.size() - 1)) | |
| render(ancestry, buf, false, dep, | |
| isLast ? spacing : "${spacing}|", | |
| isLast && isRoot ? '|' : isLast ? '\\' : '') | |
| } | |
| for (def ancestor; ancestor != node; ancestor = ancestry.pop()); | |
| } | |
| } | |
| /** | |
| * A->B format | |
| */ | |
| Tree load(String edges) { | |
| new Tree().with { | |
| edges.eachLine { link -> | |
| if (!link) return; | |
| (link =~ /([\w]++)->([\w]++)/).with { matcher -> | |
| if (!matcher.matches()) | |
| throw new IOException("Invalid input line: ${link}") | |
| add(matcher.group(1), matcher.group(2)) | |
| } | |
| } | |
| it | |
| } | |
| } | |
| def ex1 = load(''' | |
| A->B | |
| A->C | |
| B->C | |
| B->D | |
| ''') | |
| println ex1 | |
| println '' | |
| def pr1 = '''A | |
| |_ B | |
| | |_ C | |
| | \\_ D | |
| |_ C | |
| ''' | |
| assert ex1.toString().equals(pr1) | |
| def ex2 = load(''' | |
| A->B | |
| A->C | |
| B->C | |
| B->D | |
| C->B | |
| D->B | |
| D->C | |
| ''') | |
| println ex2 | |
| println '' | |
| def pr2 = '''A | |
| |_ B | |
| | |_ C | |
| | | \\_ B * | |
| | \\_ D | |
| | |_ B * | |
| | \\_ C | |
| | \\_ B * | |
| |_ C | |
| \\_ B | |
| |_ C * | |
| \\_ D | |
| |_ B * | |
| \\_ C * | |
| ''' | |
| assert ex2.toString().equals(pr2) | |
| def ex3 = load(''' | |
| A->B | |
| A->J | |
| B->C | |
| B->D | |
| C->E | |
| D->F | |
| D->G | |
| D->J | |
| E->H | |
| E->M | |
| F->H | |
| H->L | |
| I->O | |
| I->P | |
| I->K | |
| J->I | |
| J->Q | |
| K->N | |
| K->L | |
| L->I | |
| M->N | |
| M->H | |
| O->P | |
| P->Q | |
| ''') | |
| println ex3 | |
| def pr3 = '''A | |
| |_ B | |
| | |_ C | |
| | | \\_ E | |
| | | |_ H | |
| | | | \\_ L | |
| | | | \\_ I | |
| | | | |_ K | |
| | | | | |_ L * | |
| | | | | \\_ N | |
| | | | |_ O | |
| | | | | \\_ P | |
| | | | | \\_ Q | |
| | | | \\_ P | |
| | | | \\_ Q | |
| | | \\_ M | |
| | | |_ H | |
| | | | \\_ L | |
| | | | \\_ I | |
| | | | |_ K | |
| | | | | |_ L * | |
| | | | | \\_ N | |
| | | | |_ O | |
| | | | | \\_ P | |
| | | | | \\_ Q | |
| | | | \\_ P | |
| | | | \\_ Q | |
| | | \\_ N | |
| | \\_ D | |
| | |_ F | |
| | | \\_ H | |
| | | \\_ L | |
| | | \\_ I | |
| | | |_ K | |
| | | | |_ L * | |
| | | | \\_ N | |
| | | |_ O | |
| | | | \\_ P | |
| | | | \\_ Q | |
| | | \\_ P | |
| | | \\_ Q | |
| | |_ G | |
| | \\_ J | |
| | |_ I | |
| | | |_ K | |
| | | | |_ L | |
| | | | | \\_ I * | |
| | | | \\_ N | |
| | | |_ O | |
| | | | \\_ P | |
| | | | \\_ Q | |
| | | \\_ P | |
| | | \\_ Q | |
| | \\_ Q | |
| |_ J | |
| |_ I | |
| | |_ K | |
| | | |_ L | |
| | | | \\_ I * | |
| | | \\_ N | |
| | |_ O | |
| | | \\_ P | |
| | | \\_ Q | |
| | \\_ P | |
| | \\_ Q | |
| \\_ Q | |
| ''' | |
| assert ex3.toString().equals(pr3) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment