예제 #1
0
        public override bool Equals(object obj)
        {
            if (this == obj)
            {
                return(true);
            }
            Day20GridState that = (Day20GridState)obj;

            return(this.Point.Equals(that.Point) &&
                   this.Level == that.Level);
        }
예제 #2
0
        private void Visit(
            Queue <Day20GridState> q,
            HashSet <Day20GridState> visited,
            Day20GridState state,
            int xDelta,
            int yDelta)
        {
            Day20GridState newState = null;

            int newX = state.Point.X + xDelta;
            int newY = state.Point.Y + yDelta;

            var p = new Point(newX, newY);

            if (!grid.ContainsKey(p))
            {
                // not in the grid, can't move here
                newState = null;
            }
            else
            {
                char c = grid[p];
                if (c == '.')
                {
                    // movable space
                    newState = new Day20GridState
                    {
                        FromState = state,
                        Steps     = state.Steps + 1,
                        Point     = new Point(newX, newY),
                        Level     = state.Level
                    };
                }
                else
                {
                    // hit a wall
                    newState = null;
                }
            }

            if (newState != null)
            {
                if (visited.Add(newState))
                {
                    q.Enqueue(newState);
                }
            }
        }
예제 #3
0
        private int GetDistanceBfs(Day20GridState start, bool useLevels)
        {
            Queue <Day20GridState>   q       = new Queue <Day20GridState>();
            HashSet <Day20GridState> visited = new HashSet <Day20GridState>();

            q.Enqueue(start);
            visited.Add(start);

            while (q.Any())
            {
                Day20GridState state = q.Dequeue();

                var    thisPortal = portals.FirstOrDefault(p => p.OutputLocation.Equals(state.Point));
                string portalName = (thisPortal == null ? null : thisPortal.Name);

                // we have reached a portal
                if (portalName != null)
                {
                    if (state.Level == 0 && portalName == "ZZ")
                    {
                        // this is the exit to the maze
                        return(state.Steps);
                    }

                    // get portals with this name -- there will be two
                    // unless it's AA. If it's one of the others, we
                    // need to queue up a location that is the other
                    // portal
                    var allPortals = portals.Where(p => p.Name.Equals(portalName));
                    foreach (var p in allPortals)
                    {
                        // if it's not the one we're already on
                        if (!p.OutputLocation.Equals(state.Point))
                        {
                            int newLevel = 0;
                            if (useLevels)
                            {
                                newLevel = state.Level + CalculateLevel(state.Point);
                            }

                            if (!useLevels || (useLevels && newLevel >= 0))
                            {
                                // teleport!
                                Day20GridState newState = new Day20GridState
                                {
                                    Point     = p.OutputLocation,
                                    Steps     = state.Steps + 1,
                                    FromState = state,
                                    Level     = newLevel
                                };

                                if (visited.Add(newState))
                                {
                                    q.Enqueue(newState);
                                }
                            }
                        }
                    }
                }

                Visit(q, visited, state, -1, 0);
                Visit(q, visited, state, 1, 0);
                Visit(q, visited, state, 0, -1);
                Visit(q, visited, state, 0, 1);
            }

            throw new InvalidOperationException();
        }