/// <summary> /// Calculates the distance in orbits between two objects, /// i.e. the number of "jumps" for A to get in the same orbit as B, and vice versa. /// </summary> /// <param name="obj1">The 1st object</param> /// <param name="obj2">The 2nd object</param> /// <returns></returns> public int OrbitalJumpsBetween(OrbitObject obj1, OrbitObject obj2) { List <OrbitObject> obj1ToHead = obj1.ObjectsToHead(); List <OrbitObject> obj2ToHead = obj2.ObjectsToHead(); OrbitObject nearestObject = null; foreach (OrbitObject _obj1 in obj1ToHead) { foreach (OrbitObject _obj2 in obj2ToHead) { if (_obj1 == _obj2) { nearestObject = _obj1; break; } } if (nearestObject != null) { break; } } // This exception should never happen, because the head should be shared by all orbiting objects. if (nearestObject == null) { throw new InvalidOperationException($"Objects {obj1} and {obj2} do not orbit a shared object."); } int obj1Distance = obj1ToHead.IndexOf(nearestObject) + 1; int obj2Distance = obj2ToHead.IndexOf(nearestObject) + 1; return(obj1Distance + obj2Distance); }
/// <summary> /// Takes a map entry like "FOO)BAR" and adds an OrbitObject named "BAR" to parent "FOO". /// - If "FOO" does not exist, it creates it. /// - If "BAR" exists, it makes "FOO" its parent node. /// - If "BAR" does not exist, it creates it, and sets "FOO" as its parent. /// </summary> /// <param name="entry">A map entry,e.g. "FOO)BAR"</param> /// <param name="delimiter">The character to use to split the values</param> public void ProcessMapEntry(string entry, char delimiter = ')') { string[] orbit = entry.Split(delimiter); string orbitedName = orbit[0]; string orbitingName = orbit[1]; OrbitObject orbitedObj = FindOrbitingObject(orbitedName); if (orbitedObj == null) { orbitedObj = new OrbitObject(orbitedName); AddObject(orbitedObj); } OrbitObject orbitingObj = FindOrbitingObject(orbitingName); if (orbitingObj != null) { orbitingObj.SetParent(orbitedObj); orbitedObj.AddChild(orbitingObj); } else { orbitingObj = new OrbitObject(orbitingName, orbitedObj); AddObject(orbitingObj); orbitedObj.AddChild(orbitingObj); } }
public int OrbitTransfersRequired(string start, string end) { HashSet <OrbitObject> visited = new HashSet <OrbitObject>(); OrbitObject startOrbitObject = ObjectsInSpace[start].ParentOrbitObject; OrbitObject endOrbitObject = ObjectsInSpace[end].ParentOrbitObject; visited.Add(startOrbitObject); Queue <Tuple <OrbitObject, int> > objectsToVisit = new Queue <Tuple <OrbitObject, int> >(); objectsToVisit.Enqueue(new Tuple <OrbitObject, int>(startOrbitObject.ParentOrbitObject, 1)); startOrbitObject.Moons.ForEach(m => objectsToVisit.Enqueue(new Tuple <OrbitObject, int>(m.ParentOrbitObject, 1))); while (objectsToVisit.Count > 0) { var currentOrbitObjectAndPathLength = objectsToVisit.Dequeue(); var currentOrbitObject = currentOrbitObjectAndPathLength.Item1; var pathLength = currentOrbitObjectAndPathLength.Item2; if (currentOrbitObject == endOrbitObject) { return(pathLength); } visited.Add(currentOrbitObject); if (!visited.Contains(currentOrbitObject.ParentOrbitObject) && currentOrbitObject.ParentOrbitObject != null) { objectsToVisit.Enqueue(new Tuple <OrbitObject, int>(currentOrbitObject.ParentOrbitObject, pathLength + 1)); } currentOrbitObject.Moons.ForEach(m => { if (!visited.Contains(m)) { objectsToVisit.Enqueue(new Tuple <OrbitObject, int>(m, pathLength + 1)); } }); } throw new Exception("Path from " + start + " to " + end + " not found."); }
public void AddMoon(OrbitObject o) { Moons.Add(o); }
public OrbitObject(string name, OrbitObject parentOrbitObject) { this.Name = name; this.ParentOrbitObject = parentOrbitObject; Moons = new List <OrbitObject>(); }
/// <summary> /// Add an object to the objects in this map. /// </summary> /// <param name="obj">The OrbitObject to add</param> public void AddObject(OrbitObject obj) => OrbitingObjects.Add(obj);