public static int Solve(string fileName, char shapeChar) { string[] lines = File.ReadAllLines(fileName); var rows = int.Parse(lines[0]); var cols = int.Parse(lines[1]); lines = lines.Skip(2).ToArray(); UnionFindNode <char>[] nodes = new UnionFindNode <char> [rows * cols]; for (int r = 0; r < rows; r++) { string line = lines[r]; for (int c = 0; c < cols; c++) { UnionFindNode <char> current = new UnionFindNode <char>(line[c]); nodes[c * rows + r] = current; if (c > 0) { Combine(current, nodes[(c - 1) * rows + r], current.Value); } if (r > 0) { Combine(current, nodes[c * rows + r - 1], current.Value); } } } return(nodes.Where(x => x.Value == shapeChar).Select(x => x.Find()).Distinct().Count()); }
public static int CountClusters(ImplicitClusterInfo info, List <BitVector32> data) { //locations of all values in original data var locations = new Dictionary <BitVector32, List <int> >(); for (int i = 0; i < data.Count; i++) { if (!locations.ContainsKey(data[i])) { locations.Add(data[i], new List <int>() { i + 1 }); } else { locations[data[i]].Add(i + 1); } } (var graph, var clusters) = ExplicitClusterLoader.GenerateInitialClusters(info.Nodes); foreach (var localCluster in locations) { var same = localCluster.Value; //merge localCluster for (int i = 0; i < same.Count - 1; i++) { for (int j = i + 1; j < same.Count; j++) { var n1 = graph[same[i]]; var n2 = graph[same[j]]; if (n1.ParentId != n2.ParentId) { UnionFindNode.MergeClusters(clusters, n1, n2); } } } var parent = same[0]; var key = localCluster.Key; //merge all similar (distances 1, 2) nodes to this local cluster var candidate = new BitVector32(key); for (int i = 0; i < info.Bits; i++) { //merge any single bit differences candidate = FlipBit(candidate, i); TryMerge(locations, graph, clusters, candidate, parent); for (int j = i + 1; j < info.Bits; j++) { //merge any double bit differences candidate = FlipBit(candidate, j); TryMerge(locations, graph, clusters, candidate, parent); candidate = FlipBit(candidate, j); } candidate = FlipBit(candidate, i); } } return(clusters.Count); }
public bool Unite(UnionFindNode other) { var thisRoot = this.FindRoot(); var otherRoot = other.FindRoot(); if (thisRoot == otherRoot) { return(false); } if (thisRoot._height < otherRoot._height) { thisRoot._parent = otherRoot; otherRoot._groupSize += thisRoot._groupSize; otherRoot._height = Math.Max(thisRoot._height + 1, otherRoot._height); return(true); } else { otherRoot._parent = thisRoot; thisRoot._groupSize += otherRoot._groupSize; thisRoot._height = Math.Max(otherRoot._height + 1, thisRoot._height); return(true); } }
public UnionFindNode(int id) { _height = 0; _groupSize = 1; _parent = this; ID = id; }
public bool Union(UnionFindNode p2) { var root1 = Find(); var root2 = p2.Find(); if (ReferenceEquals(root1, root2)) { return(false); } if (root1.rank < root2.rank) { root1._parent = root2; } else if (root1.rank > root2.rank) { root2._parent = root1; } else { root2._parent = root1; root1.rank++; } return(true); }
private EasilyConfusedKana(IEnumerable <IEnumerable <CodePoint> > input) { var similaritySets = new ConcurrentDictionary <CodePoint, UnionFindNode>(); foreach (var group in input) { UnionFindNode first = null; foreach (var cp in group) { var set = similaritySets.GetOrAdd(cp, x => new UnionFindNode()); if (first != null) { set.Union(first); } first = set; } } var uniqueLists = new Dictionary <UnionFindNode, List <CodePoint> >(); foreach (var kvp in similaritySets) { uniqueLists[kvp.Value.Find()] = new List <CodePoint>(); } similarityGroups = new Dictionary <CodePoint, List <CodePoint> >(); foreach (var kvp in similaritySets) { var list = uniqueLists[similaritySets[kvp.Key].Find()]; list.Add(kvp.Key); similarityGroups[kvp.Key] = list; } }
// Union/Find Algorithm - The find routine. // // Implemented with Path Compression (inner loops are only // visited and collapsed once, however, deep nests would still // result in significant traversals). // public UnionFindNode findSet() { List <UnionFindNode> nodeList = new List <UnionFindNode>(2); UnionFindNode node = this; while (node != node.getParent()) { if (node.getParent() != node.getParent().getParent()) { nodeList.Add(node); } node = node.getParent(); } // Path Compression, all nodes' parents point to the 1st level parent. int len = nodeList.Count; for (int i = 0; i < len; i++) { // for (UnionFindNode iter : nodeList) UnionFindNode iter = nodeList[i]; iter.setParent(node.getParent()); } return(node); }
public void UnionFindNode_CreateNode() { UnionFindNode <int> a = new UnionFindNode <int> { Label = 6 }; Assert.AreEqual(6, a.Label); }
/// <summary> /// Returns the current representative of the set this node is in. /// Note that the representative is only accurate untl the next Union operation. /// </summary> public UnionFindNode <T> Find() { if (!ReferenceEquals(_parent, this)) { _parent = _parent.Find(); } return(_parent); }
public void TestTrivial() { var n1 = new UnionFindNode(); var n2 = new UnionFindNode(); Assert.True(n1.IsUnionedWith(n1)); Assert.False(n1.IsUnionedWith(n2)); }
private static UnionFindNode AddPerson(int id, Dictionary <int, UnionFindNode> people) { if (!people.ContainsKey(id)) { people[id] = new UnionFindNode(id); } return(people[id]); }
/// <summary> /// Determines whether or not this node and the other node are in the same set. /// </summary> public bool IsUnionedWith(UnionFindNode <T> other) { if (other == null) { throw new ArgumentNullException("other"); } return(ReferenceEquals(Find(), other.Find())); }
public void UnionFindNode_MergeTwo() { UnionFindNode <string> nodeA = CreateStringNode("A"); UnionFindNode <string> nodeB = CreateStringNode("B"); UnionFindNode <string> .Merge(nodeA, nodeB); Assert.AreEqual(nodeB.Label, nodeA.FindSet()); }
public UnionFindNode <string> CreateStringNode(string label) { UnionFindNode <string> node = new UnionFindNode <string> { Label = label }; Assert.AreEqual(label, node.Label); return(node); }
private static UnionFindNode Union(UnionFindNode n1, UnionFindNode n2) { UnionFindNode smaller = n1.size < n2.size ? n1 : n2; UnionFindNode larger = n1 == smaller ? n2 : n1; smaller.parent = larger; larger.size += smaller.size; return(larger); }
private static UnionFindNode Advance(List <UnionFindNode> path, UnionFindNode node, int count) { while (count > 0) { count--; node = allNodes[node.parentId]; path.Add(node); } return(node); }
public UnionFindNode FindRoot() { if (_parent != this) // not ref equals { var root = _parent.FindRoot(); _parent = root; } return(_parent); }
public UnionFindNode GetRoot() { UnionFindNode root = this; while (root.parent != root) { root = root.parent; } return(root); }
private static int DistanceToRoot(UnionFindNode node) { int distance = 0; while (node.id != node.parentId) { distance++; node = allNodes[node.parentId]; } return(distance); }
public void Trivial_Test() { var n1 = new UnionFindNode(); var n2 = new UnionFindNode(); Assert.True(n1.IsUnionedWith(n1)); Assert.False(n1.IsUnionedWith(n2)); Assert.Throws <ArgumentNullException>(() => n1.Union(null)); Assert.Throws <ArgumentNullException>(() => n1.IsUnionedWith(null)); }
private static UnionFindNode GetOrCreateNode(int road, bool isMachine) { if (!allNodes.ContainsKey(road)) { allNodes[road] = roots[road] = new UnionFindNode(road, isMachine); if (isMachine) { allNodes[road].machineNode = allNodes[road]; } } return(allNodes[road]); }
public void UnionFindNode_MergeThree_Chained() { UnionFindNode <string> nodeA = CreateStringNode("A"); UnionFindNode <string> nodeB = CreateStringNode("B"); UnionFindNode <string> nodeC = CreateStringNode("C"); UnionFindNode <string> .Merge(nodeA, nodeB); UnionFindNode <string> .Merge(nodeB, nodeC); Assert.AreEqual(nodeC.Label, nodeA.FindSet()); Assert.AreEqual(nodeC.Label, nodeB.FindSet()); Assert.AreEqual(nodeC.Label, nodeC.FindSet()); }
private static UnionFindNode Find(UnionFindNode node) { while (node.id != node.parentId) { UnionFindNode parent = allNodes[node.parentId]; if (node.containsMachine) { parent.containsMachine = true;; parent.machineNode = node.machineNode; } node = parent; } return(node); }
public void TestTrivial() { var r1 = new UnionFindNode(); var r2 = new UnionFindNode(); Assert.IsTrue(r1.IsUnionedWith(r1)); Assert.IsTrue(r2.IsUnionedWith(r2)); Assert.IsTrue(!r1.IsUnionedWith(r2)); Assert.IsTrue(r1.Union(r2)); Assert.IsTrue(r1.IsUnionedWith(r1)); Assert.IsTrue(r2.IsUnionedWith(r2)); Assert.IsTrue(r1.IsUnionedWith(r2)); }
GenerateInitialClusters(int numNodes) { var graph = new Dictionary <int, UnionFindNode>(); var clusters = new Dictionary <int, List <UnionFindNode> >(); for (int i = 1; i <= numNodes; i++) { var node = new UnionFindNode(i); graph.Add(i, node); clusters.Add(i, new List <UnionFindNode>() { node }); } return(graph, clusters); }
public void UnionFindNode_MergeFour_TwoSets() { UnionFindNode <string> nodeA = CreateStringNode("A"); UnionFindNode <string> nodeB = CreateStringNode("B"); UnionFindNode <string> nodeC = CreateStringNode("C"); UnionFindNode <string> nodeD = CreateStringNode("D"); UnionFindNode <string> .Merge(nodeA, nodeB); UnionFindNode <string> .Merge(nodeC, nodeD); UnionFindNode <string> .Merge(nodeB, nodeD); Assert.AreEqual(nodeD.Label, nodeA.FindSet()); Assert.AreEqual(nodeD.Label, nodeB.FindSet()); Assert.AreEqual(nodeD.Label, nodeC.FindSet()); Assert.AreEqual(nodeD.Label, nodeD.FindSet()); }
private IEnumerable <LocationSet> getCurrentLocationSets(ILayoutAccess layout) { HashSet <Location> locs = new HashSet <Location>(); foreach (WireSegment w in layout.Wires) { locs.Add(w.End0); locs.Add(w.End1); } foreach (Component c in layout.Components) { Location cloc = c.GetLocation(layout); foreach (ConnectionPoint p in c.Connections) { locs.Add(cloc.Translate(p.Dx, p.Dy)); } } UnionFind <Location> allNodes = new UnionFind <Location>(locs); foreach (WireSegment w in layout.Wires) { UnionFindNode <Location> e0 = allNodes[w.End0]; UnionFindNode <Location> e1 = allNodes[w.End1]; e0.Unite(e1); } IEnumerable <UnionFindNode <Location> > roots = allNodes.Roots; List <LocationSet> result = new List <LocationSet>(); foreach (UnionFindNode <Location> root in roots) { IEnumerable <UnionFindNode <Location> > rootMembers = root.GetSetMembers(); List <Location> setMembers = new List <Location>(); foreach (UnionFindNode <Location> n in rootMembers) { setMembers.Add(n.Value); } result.Add(new LocationSet(setMembers)); } return(result); }
public static int CalculateSpacing(int numNodes, List <EdgeData> edges) { (var graph, var clusters) = GenerateInitialClusters(numNodes); edges.Sort((x, y) => x.Cost - y.Cost); foreach (var edge in edges) { if (clusters.Count <= 4) { break; } var n1 = graph[edge.NodeId1]; var n2 = graph[edge.NodeId2]; if (n1.ParentId != n2.ParentId) { UnionFindNode.MergeClusters(clusters, n1, n2); } } return(MaxSpacing(graph, edges)); }
private static int ProcessRoads(int[][] sortedRoads, HashSet <int> machineSet) { int minTime = 0; Init(sortedRoads.Length + 1, machineSet); for (int i = 0; i < sortedRoads.Length; i++) { int[] road = sortedRoads[i]; UnionFindNode source = allNodes[road[0]]; UnionFindNode target = allNodes[road[1]]; UnionFindNode sourceRoot = Find(source); UnionFindNode targetRoot = Find(target); if (sourceRoot.id != targetRoot.id) { minTime += Union(sourceRoot, targetRoot, road); } } return(minTime); }
private static void TryMerge(Dictionary <BitVector32, List <int> > locations, Dictionary <int, UnionFindNode> graph, Dictionary <int, List <UnionFindNode> > clusters, BitVector32 candidate, int parent) { if (!locations.ContainsKey(candidate)) { return; } var n1 = graph[parent]; foreach (var location in locations[candidate]) { var n2 = graph[location]; if (n1.ParentId != n2.ParentId) { UnionFindNode.MergeClusters(clusters, n1, n2); } } }
// // DFS - Depth-First-Search // // DESCRIPTION: // Simple depth first traversal along out edges with node numbering. // int doDFS(BasicBlock currentNode, UnionFindNode[] nodes, Dictionary<BasicBlock, int> number, int[] last, /*final*/ int current) { nodes[current].initNode(currentNode, current); number.Add(currentNode, current); int lastid = current; // for (BasicBlock target : currentNode.getOutEdges()) { int len = currentNode.getOutEdges().size(); for (int i = 0; i < len; i++) { BasicBlock target = currentNode.getOutEdges().get(i); if (number[target] == UNVISITED) { lastid = doDFS(target, nodes, number, last, lastid + 1); } } last[number[currentNode]] = lastid; return lastid; }
// // findLoops // // Find loops and build loop forest using Havlak's algorithm, which // is derived from Tarjan. Variable names and step numbering has // been chosen to be identical to the nomenclature in Havlak's // paper (which, in turn, is similar to the one used by Tarjan). // public void findLoops() { if (cfg.getStartBasicBlock() == null) { return; } long startMillis = CurrentTimeMillis(); int size = cfg.getNumNodes(); nonBackPreds.Clear(); backPreds.Clear(); number.Clear(); if (size > maxSize) { header = new int[size]; type = new BasicBlockClass[size]; last = new int[size]; nodes = new UnionFindNode[size]; maxSize = size; } /* List<Set<Integer>> nonBackPreds = new ArrayList<Set<Integer>>(); List<List<Integer>> backPreds = new ArrayList<List<Integer>>(); Map<BasicBlock, Integer> number = new HashMap<BasicBlock, Integer>(); int[] header = new int[size]; BasicBlockClass[] type = new BasicBlockClass[size]; int[] last = new int[size]; UnionFindNode[] nodes = new UnionFindNode[size]; */ for (int i = 0; i < size; ++i) { //nonBackPreds.Add(freeListSet.Count == 0 ? new HashSet<int>() : freeListSet.RemoveFirst().Clear()); if (freeListList.Count == 0) { nonBackPreds.Add(new HashSet<int>()); } else { var node = freeListSet.First; freeListSet.RemoveFirst(); node.Value.Clear(); nonBackPreds.Add(node.Value); } //backPreds.Add(freeListList.Count == 0 ? new List<int>() : freeListList.RemoveFirst().Clear()); if (freeListList.Count == 0) { backPreds.Add(new List<int>()); } else { var node = freeListList.First; freeListList.RemoveFirst(); node.Value.Clear(); backPreds.Add(node.Value); } nodes[i] = new UnionFindNode(); } // Step a: // - initialize all nodes as unvisited. // - depth-first traversal and numbering. // - unreached BB's are marked as dead. // foreach (var bbIter in cfg.getBasicBlocks().values()) { number.Add(bbIter, UNVISITED); } doDFS(cfg.getStartBasicBlock(), nodes, number, last, 0); // Step b: // - iterate over all nodes. // // A backedge comes from a descendant in the DFS tree, and non-backedges // from non-descendants (following Tarjan). // // - check incoming edges 'v' and add them to either // - the list of backedges (backPreds) or // - the list of non-backedges (nonBackPreds) // for (int w = 0; w < size; w++) { header[w] = 0; type[w] = BasicBlockClass.BB_NONHEADER; BasicBlock nodeW = nodes[w].getBb(); if (nodeW == null) { type[w] = BasicBlockClass.BB_DEAD; continue; // dead BB } if (nodeW.getNumPred() > 0) { int len1 = nodeW.getInEdges().size(); for (int i = 0; i < len1; i++) { // for (BasicBlock nodeV : nodeW.getInEdges()) { BasicBlock nodeV = nodeW.getInEdges().get(i); int v = number[nodeV]; if (v == UNVISITED) { continue; // dead node } if (isAncestor(w, v, last)) { backPreds[w].Add(v); } else { nonBackPreds[w].Add(v); } } } } // Start node is root of all other loops. header[0] = 0; // Step c: // // The outer loop, unchanged from Tarjan. It does nothing except // for those nodes which are the destinations of backedges. // For a header node w, we chase backward from the sources of the // backedges adding nodes to the set P, representing the body of // the loop headed by w. // // By running through the nodes in reverse of the DFST preorder, // we ensure that inner loop headers will be processed before the // headers for surrounding loops. // for (int w = size - 1; w >= 0; w--) { // this is 'P' in Havlak's paper LinkedList<UnionFindNode> nodePool = new LinkedList<UnionFindNode>(); BasicBlock nodeW = nodes[w].getBb(); if (nodeW == null) { continue; // dead BB } // Step d: int len = backPreds[w].Count; for (int i = 0; i < len; i++) { int v = backPreds[w][i]; // for (int v : backPreds.get(w)) { if (v != w) { nodePool.AddLast(nodes[v].findSet()); } else { type[w] = BasicBlockClass.BB_SELF; } } // Copy nodePool to workList. // LinkedList<UnionFindNode> workList = new LinkedList<UnionFindNode>(); foreach (var niter in nodePool) workList.AddLast(niter); if (nodePool.Count != 0) { type[w] = BasicBlockClass.BB_REDUCIBLE; } // work the list... // while (workList.Count != 0) // while (!workList.isEmpty()) { LinkedListNode<UnionFindNode> x = workList.First; workList.RemoveFirst(); // Step e: // // Step e represents the main difference from Tarjan's method. // Chasing upwards from the sources of a node w's backedges. If // there is a node y' that is not a descendant of w, w is marked // the header of an irreducible loop, there is another entry // into this loop that avoids w. // // The algorithm has degenerated. Break and // return in this case. // int nonBackSize = nonBackPreds[x.Value.getDfsNumber()].Count; if (nonBackSize > MAXNONBACKPREDS) { return; } HashSet<int> curr = nonBackPreds[x.Value.getDfsNumber()]; foreach (var iter in curr) { UnionFindNode y = nodes[iter]; UnionFindNode ydash = y.findSet(); if (!isAncestor(w, ydash.getDfsNumber(), last)) { type[w] = BasicBlockClass.BB_IRREDUCIBLE; nonBackPreds[w].Add(ydash.getDfsNumber()); } else { if (ydash.getDfsNumber() != w) { if (!nodePool.Contains(ydash)) { workList.AddLast(ydash); nodePool.AddLast(ydash); } } } } } // Collapse/Unionize nodes in a SCC to a single node // For every SCC found, create a loop descriptor and link it in. // if ((nodePool.Count > 0) || (type[w] == BasicBlockClass.BB_SELF)) { SimpleLoop loop = lsg.createNewLoop(); loop.setHeader(nodeW); loop.setIsReducible(type[w] != BasicBlockClass.BB_IRREDUCIBLE); // At this point, one can set attributes to the loop, such as: // // the bottom node: // iter = backPreds[w].begin(); // loop bottom is: nodes[iter].node); // // the number of backedges: // backPreds[w].size() // // whether this loop is reducible: // type[w] != BasicBlockClass.BB_IRREDUCIBLE // nodes[w].setLoop(loop); foreach (var node in nodePool) { // Add nodes to loop descriptor. header[node.getDfsNumber()] = w; node.union(nodes[w]); // Nested loops are not added, but linked together. if (node.getLoop() != null) { node.getLoop().setParent(loop); } else { loop.addNode(node.getBb()); } } lsg.addLoop(loop); } // nodePool.size } // Step c long totalMillis = CurrentTimeMillis() - startMillis; if (totalMillis > maxMillis) { maxMillis = totalMillis; } if (totalMillis < minMillis) { minMillis = totalMillis; } for (int i = 0; i < size; ++i) { freeListSet.AddLast(nonBackPreds[i]); // Add() in Java LinkedList adds to the end freeListList.AddLast(backPreds[i]); nodes[i] = new UnionFindNode(); } }
public void UnionParent(UnionFindNode ufn) { Parent = ufn; }
// Initialize this node. // public void initNode(BasicBlock bb, int dfsNumber) { this.parent = this; this.bb = bb; this.dfsNumber = dfsNumber; this.loop = null; }
void setParent(UnionFindNode parent) { this.parent = parent; }
// Union/Find Algorithm - The union routine. // // Trivial. Assigning parent pointer is enough, // we rely on path compression. // void union(UnionFindNode basicBlock) { setParent(basicBlock); }