public IEnumerable <Node> Neigbours(Node node) { var(point, currentTool) = node; var currentRegion = _factory.Calculate(point); var currentValidTools = GetValidTools(currentRegion.CellType); foreach (var otherTool in Tools.Where(t => t != node.Tool && currentValidTools.Contains(t))) { yield return(new Node(node.Position, otherTool)); } foreach (var neighbour in PointHelpers.GetDirectNeighbours(node.Position)) { if (neighbour.X < 0 || neighbour.Y < 0) { continue; } var regionDetails = _factory.Calculate(neighbour); var validTools = GetValidTools(regionDetails.CellType); if (validTools.Contains(currentTool)) { yield return(new Node(neighbour, node.Tool)); } } }
public override void PartOne(IInput input, IOutput output) { var map = input.As2DPoints() .ToImmutableDictionary(k => k.Point, v => v.Character - '0'); var lowPoints = new HashSet <Point2d>(); foreach (var(point, height) in map) { var neighbours = PointHelpers .GetDirectNeighbours(point); var lowest = neighbours // Go through all possible neighbours .Select(n => map.TryGetValue(n, out var neighbourHeight) ? neighbourHeight : (int?)null) // Get their height or null for missing. .Where(n => n is not null) .All(neighbourHeight => height < neighbourHeight); if (lowest) { lowPoints.Add(point); } } var score = lowPoints .Sum(point => 1 + map[point]); output.WriteProperty("Risk Level", score); }
public IEnumerable <Point2d> Neigbours(Point2d node) { return(PointHelpers.GetDirectNeighbours(node) .Where(point => point.X >= 0 && point.Y >= 0) .Where(point => _office.ContainsKey(point)) .Where(point => _office[point] is not CellType.Wall)); }
static HashSet <Point2d> FindBasinContainingPoint(Point2d source, IReadOnlyDictionary <Point2d, int> map) { var currentFrontier = new List <Point2d>(); var nextFrontier = new List <Point2d>(); currentFrontier.Add(source); var visited = new HashSet <Point2d> { source }; while (currentFrontier.Count > 0) { foreach (var current in currentFrontier) { foreach (var next in PointHelpers.GetDirectNeighbours(current)) { if (map.TryGetValue(next, out var nextHeight) && nextHeight != 9) { if (visited.Add(next) is true) { nextFrontier.Add(next); } } } } (currentFrontier, nextFrontier) = (nextFrontier, currentFrontier); nextFrontier.Clear(); } return(visited); }
static ImmutableArray <Point2d> FindPath( ImmutableDictionary <Point2d, Cell> map, Func <State, bool> goalReached, Point2d start) { var startState = new State(start, ImmutableSortedSet.Create(0)); var frontier = new PriorityQueue <State, float>(); frontier.Enqueue(startState, 0); var cameFrom = new Dictionary <State, State>() { [startState] = startState }; var costSoFar = new Dictionary <State, float>() { [startState] = 0 }; State?finishedState = null; while (frontier.TryDequeue(out var current, out _)) { if (goalReached(current)) { finishedState = current; break; } foreach (var next in PointHelpers.GetDirectNeighbours(current.Position)) { if (map.TryGetValue(next, out var nextCell) is false || nextCell.Type is CellType.Wall) { continue; } var newVisited = nextCell is PointOfInterest poi ? current.Visited.Add(poi.Number) : current.Visited; var nextState = new State(next, newVisited); var newCost = costSoFar[current] + 1; if (costSoFar.TryGetValue(nextState, out var nextCost) is false || newCost < nextCost) { costSoFar[nextState] = newCost; frontier.Enqueue(nextState, newCost); cameFrom[nextState] = current; } } } if (finishedState is null) { return(ImmutableArray <Point2d> .Empty); } return(Algorithms.ReconstructPath(startState, finishedState, cameFrom) .Select(state => state.Position) .ToImmutableArray()); }