示例#1
0
        protected override int Part2(string[] input)
        {
            var maze         = new PortalMaze(input);
            var shortestPath = MaxDepths().Select(d => FindMinimumDistanceBfsPlutonian(maze, d)).First(x => x != Infinite);

            return(shortestPath);
        }
示例#2
0
        protected override int Part1(string[] input)
        {
            var maze         = new PortalMaze(input);
            var graph        = PortalGraph.BuildWeightedGraphFromMaze(maze);
            var shortestPath = graph.ShortestPathDijkstra(maze.Entry, maze.Exit);

            return(shortestPath);
        }
示例#3
0
        private static int FindMinimumDistanceBfsPlutonian(PortalMaze maze, int maxDepth)
        {
            var graph    = BuildSimpleGraph(maze);
            var toplevel = new MazeLevel()
            {
                Level = 0
            };
            var entry = graph.Vertices[maze.Entry];
            var exit  = graph.Vertices[maze.Exit];

            var root = graph.Root;

            toplevel.Visited[root.Pos] = true;

            var queue = new Queue <(MazeLevel, PortalGraph.Vertex, int)>();

            queue.Enqueue((toplevel, root, 0));
            while (queue.Any())
            {
                var(level, node, distance) = queue.Dequeue();
                if (node.Pos == exit.Pos && level.Level == 0)
                {
                    return(distance);
                }
                foreach (var e in node.Edges)
                {
                    var nextnode  = e.Key;
                    var nextlevel = level;
                    if (e.Value != 0)
                    {
                        if (e.Value == -1)
                        {
                            if (level.Level > maxDepth)
                            {
                                continue;
                            }
                            if (level.Inner == null)
                            {
                                level.Inner = new MazeLevel()
                                {
                                    Level = level.Level + 1,
                                    Outer = level
                                };
                            }
                            nextlevel = level.Inner;
                        }
                        else
                        {
                            nextlevel = level.Outer;
                            if (nextlevel == null)
                            {
                                continue;
                            }
                        }
                        nextnode = graph.Vertices[nextnode.Pos];
                    }

                    if (nextlevel.Visited[nextnode.Pos])
                    {
                        continue;
                    }
                    nextlevel.Visited[nextnode.Pos] = true;

                    queue.Enqueue((nextlevel, nextnode, distance + 1));
                }
            }
            return(Infinite);
        }
示例#4
0
        private static PortalGraph BuildSimpleGraph(PortalMaze maze)
        {
            var walked = new SparseMap <PortalGraph.Vertex>();
            var graph  = new PortalGraph();

            graph.AddVertex(maze.Entry);
            BuildSimpleGraph(graph.Root);

            return(graph);

            void BuildSimpleGraph(PortalGraph.Vertex node)
            {
                while (walked[node.Pos] == null)
                {
                    walked[node.Pos] = node;
                    var positions = node.Pos
                                    .LookAround()
                                    .Select(p => new { Pos = p, Dest = maze.Transform(p) })
                                    .Where(x => maze.Map[x.Dest] == '.')
                                    .Where(x => walked[x.Dest] == null || !walked[x.Dest].Edges.ContainsKey(node))
                                    .ToList();

                    foreach (var p in positions.Where(x => walked[x.Dest] != null).ToList())
                    {
                        var existing    = walked[p.Dest];
                        var portal      = maze.Portals[p.Pos];
                        var portalValue = portal == null ? 0 : portal.IsDownward ? -1 : 1;
                        var portalName  = portal == null ? null : portal.Name;
                        node.Value           = portal;
                        existing.Value       = portal;
                        node.Edges[existing] = portalValue;
                        existing.Edges[node] = -portalValue;
                        positions.Remove(p);
                    }

                    switch (positions.Count())
                    {
                    case 0:
                        return;

                    case 1:
                        var p    = positions.First();
                        var next = graph.AddVertex(p.Dest);
                        //graph.Vertices.Add(next);
                        var portal      = maze.Portals[p.Pos];
                        var portalValue = portal == null ? 0 : portal.IsDownward ? -1 : 1;
                        node.Value       = portal;
                        next.Value       = portal;
                        node.Edges[next] = portalValue;
                        next.Edges[node] = -portalValue;
                        node             = next;
                        break;

                    default:
                        var forks = positions.Select(x => graph.AddVertex(x.Dest)).ToList();
                        foreach (var fork in forks)
                        {
                            BuildSimpleGraph(fork);
                        }
                        return;
                    }
                }
            }
        }