public static void Day13() { //int favoriteNum = 10; //var destination = new Day13Location() {location = new Tuple<int, int>(7, 4)}; int favoriteNum = 1358; var destination = new Day13Location() { location = new Tuple <int, int>(31, 39) }; Func <Day13Location, Day13Location, double> distanceFunc = (Day13Location l1, Day13Location l2) => Math.Sqrt((l2.x - l1.x) * (l2.x - l1.x) + (l2.y - l1.y) * (l2.y - l1.y)); int [,] officeSpace = new int[255, 255]; var cameFrom = new Dictionary <Day13Location, Day13Location>(); var currentLocation = new Day13Location() { location = new Tuple <int, int>(1, 1), gScore = 0 }; currentLocation.fScore = distanceFunc(currentLocation, destination); Func <int, int, bool> IsSpace = (x, y) => { int z = (x * x + 3 * x + 2 * x * y + y + y * y) + favoriteNum; int onBits = 0; for (int i = 0; i < 15; i++) { if ((z & (int)Math.Pow(2, i)) > 0) { onBits++; } } return(onBits % 2 == 0); }; var openSet = new List <Day13Location>(); openSet.Add(currentLocation); var closedSet = new List <Day13Location>(); bool success = false; while (openSet.Count > 0) { openSet.Sort(); currentLocation = openSet.First(); if (currentLocation.Equals(destination)) { Console.WriteLine("Success!"); success = true; break; } openSet.Remove(currentLocation); closedSet.Add(currentLocation); double nextGScore = currentLocation.gScore + 1; for (int x = -1; x < 2; x++) { for (int y = -1; y < 2; y++) { if ((x != 0 && y != 0) || x == 0 && y == 0) { continue; // cardinal directions only, no diagonal and avoid the current location } var neighborTuple = new Tuple <int, int>(currentLocation.x + x, currentLocation.y + y); if (neighborTuple.Item1 < 0 || neighborTuple.Item2 < 0) { continue; // negative values are invalid } if (IsSpace(currentLocation.x + x, currentLocation.y + y)) { double possibleFScore = distanceFunc(currentLocation, destination) + currentLocation.gScore; var neighbor = openSet.FirstOrDefault(l => l.Equals(new Day13Location() { location = neighborTuple })); if (neighbor != null && neighbor.gScore > nextGScore) { openSet.Remove(neighbor); } neighbor = closedSet.FirstOrDefault(l => l.Equals(new Day13Location() { location = neighborTuple })); if (neighbor != null && neighbor.gScore > nextGScore) { closedSet.Remove(neighbor); } if (!closedSet.Contains(neighbor) && !openSet.Contains(neighbor)) { if (null == neighbor) { neighbor = new Day13Location() { location = neighborTuple } } ; openSet.Add(neighbor); neighbor.gScore = nextGScore; neighbor.fScore = nextGScore + possibleFScore; cameFrom[neighbor] = currentLocation; } } } } } // print out the path Console.WriteLine(currentLocation); int steps = 0; while (cameFrom.TryGetValue(currentLocation, out currentLocation)) { Console.WriteLine(currentLocation); steps++; } Console.WriteLine($"Took {steps} steps"); }
public static void Day13Part2() { int favoriteNum = 1358; Func <Day13Location, Day13Location, double> distanceFunc = (Day13Location l1, Day13Location l2) => Math.Sqrt((l2.x - l1.x) * (l2.x - l1.x) + (l2.y - l1.y) * (l2.y - l1.y)); var currentLocation = new Day13Location() { location = new Tuple <int, int>(1, 1), gScore = 0 }; Func <int, int, bool> IsSpace = (x, y) => { int z = (x * x + 3 * x + 2 * x * y + y + y * y) + favoriteNum; int onBits = 0; for (int i = 0; i < 15; i++) { if ((z & (int)Math.Pow(2, i)) > 0) { onBits++; } } return(onBits % 2 == 0); }; var openSet = new List <Day13Location>(); openSet.Add(currentLocation); var closedSet = new List <Day13Location>(); bool success = false; while (openSet.Count > 0) { currentLocation = openSet.First(); openSet.Remove(currentLocation); closedSet.Add(currentLocation); double nextGScore = currentLocation.gScore + 1; if (nextGScore > 50) { continue; } for (int x = -1; x < 2; x++) { for (int y = -1; y < 2; y++) { if ((x != 0 && y != 0) || x == 0 && y == 0) { continue; // cardinal directions only, no diagonal and avoid the current location } var neighborTuple = new Tuple <int, int>(currentLocation.x + x, currentLocation.y + y); if (neighborTuple.Item1 < 0 || neighborTuple.Item2 < 0) { continue; // negative values are invalid } if (IsSpace(currentLocation.x + x, currentLocation.y + y)) { var neighbor = new Day13Location() { location = neighborTuple, gScore = nextGScore }; if (!closedSet.Contains(neighbor) && !openSet.Contains(neighbor)) { openSet.Add(neighbor); neighbor.gScore = nextGScore; } } } } } // print out the path var gScore50Locs = closedSet.Where(l => l.gScore <= 50); Console.WriteLine($"There are {gScore50Locs.Count()} locations within 50 steps from the start"); }