Exemplo n.º 1
0
        public static List <int> FindShortestPath(
            HashSet <int> source,
            HashSet <int> target,
            IEnumerable <River> rivers,
            AdjacencyMap adjacencyMap)
        {
            var previousSites = new Dictionary <int, int>();

            foreach (var result in BreadthFirstSearch(source, rivers, adjacencyMap))
            {
                previousSites[result.site] = result.previousSite;

                if (target.Contains(result.site))
                {
                    var ans  = new List <int>();
                    var site = result.site;

                    while (true)
                    {
                        ans.Add(site);

                        int newSite;
                        if (!previousSites.TryGetValue(site, out newSite))
                        {
                            return(ans);
                        }

                        site = newSite;
                    }
                }
            }

            return(null);
        }
Exemplo n.º 2
0
        public static IEnumerable <BfsResult> BreadthFirstSearch(
            HashSet <int> startingSites,
            IEnumerable <River> rivers,
            AdjacencyMap adjacencyMap,
            int maxDepth = int.MaxValue)
        {
            var distances = startingSites.ToDictionary(i => i, i => 0);

            var queue = new Queue <int>(startingSites);

            while (queue.Any())
            {
                var item     = queue.Dequeue();
                var distance = distances[item];
                if (distance >= maxDepth)
                {
                    yield break;
                }

                foreach (var neighbor in adjacencyMap.GetNeighbors(item))
                {
                    if (!distances.ContainsKey(neighbor))
                    {
                        distances[neighbor] = distance + 1;
                        queue.Enqueue(neighbor);
                        yield return(new BfsResult()
                        {
                            site = neighbor,
                            previousSite = item,
                            distance = distance + 1
                        });
                    }
                }
            }
        }
Exemplo n.º 3
0
        public int ComputeLiberty(IEnumerable <River> rivers, AdjacencyMap adjacencyMap)
        {
            var myPoints = this.Trees.Sum(tree => tree.Count);

            return(myPoints + this.Trees
                   .SelectMany(tree => Utils.BreadthFirstSearch(tree, rivers, adjacencyMap, 2).Select(bfs => bfs.site))
                   .Distinct()
                   .Count());
        }
Exemplo n.º 4
0
        static Tuple <River, double> FindBestChoke(
            IEnumerable <River> allRivers,
            AdjacencyMap allRiversAdjacencyMap,
            List <River> availableRivers,
            HashSet <int> sourceMine,
            HashSet <int> targetMine,
            List <int> shortestPath)
        {
            Func <List <int>, int> lengthOrDefault = (list) => list == null ? 10000 : list.Count;

            var rivers = shortestPath.Zip(
                shortestPath.Skip(1),
                (source, target) =>
            {
                var river = new River()
                {
                    source = source, target = target
                };
                return(allRivers.Contains(river) ? river : new River()
                {
                    source = target, target = source
                });
            });

            var bestRivers = availableRivers
                             .Select(river =>
            {
                bool removedItem = allRiversAdjacencyMap.Remove(river);

                var ans = new
                {
                    river        = river,
                    shortestPath = lengthOrDefault(
                        Utils.FindShortestPath(
                            sourceMine,
                            targetMine,
                            allRivers.Where(i => !i.Equals(river)),
                            allRiversAdjacencyMap))
                };

                if (removedItem)
                {
                    allRiversAdjacencyMap.Add(river);
                }

                return(ans);
            })
                             .OrderByDescending(i => i.shortestPath);

            var bestRiver = bestRivers.First();

            return(Tuple.Create(bestRiver.river, (double)bestRiver.shortestPath / shortestPath.Count));
        }
Exemplo n.º 5
0
        static List <List <River> > FindChokes(
            List <int> mines,
            List <River> myRivers,
            List <River> availableRivers,
            DateTime deadLine)
        {
            var trees = new TreeSet(myRivers, mines);

            var treePairs =
                from tree1 in trees.Trees
                from tree2 in trees.Trees
                where tree1.First() < tree2.First()
                select Tuple.Create(tree1, tree2);

            var allRivers = availableRivers.Concat(myRivers);

            var allRiversAdjacencyMap = new AdjacencyMap(allRivers);

            var shortestPaths = treePairs
                                .Select(treePair => new
            {
                treePair     = treePair,
                shortestPath = DateTime.UtcNow > deadLine ? null : Utils.FindShortestPath(
                    treePair.Item1,
                    treePair.Item2,
                    allRivers,
                    allRiversAdjacencyMap)
            })
                                .Where(i => i.shortestPath != null)
                                .OrderBy(i => i.shortestPath.Count)
                                // .Take(map.mines.Count)
                                .ToList();

            var bestChokes = shortestPaths
                             .Select(i => DateTime.UtcNow > deadLine ? null : FindBestChoke(
                                         allRivers,
                                         allRiversAdjacencyMap,
                                         availableRivers,
                                         i.treePair.Item1,
                                         i.treePair.Item2,
                                         i.shortestPath))
                             .Where(i => i != null && i.Item2 > 1.3)
                             .GroupBy(i => i.Item1)
                             .OrderByDescending(group => group.Sum(i => i.Item2))
                             .ToList();

            return(bestChokes
                   .Select(group => new List <River>()
            {
                group.Key
            })
                   .ToList());
        }
Exemplo n.º 6
0
        public MineDistances(
            Map map,
            AdjacencyMap adjacencyMap)
        {
            foreach (int mine in map.mines)
            {
                this.distances[mine] = new Dictionary <int, int>();

                foreach (var i in Utils.BreadthFirstSearch(new HashSet <int>()
                {
                    mine
                }, map.rivers, adjacencyMap: adjacencyMap))
                {
                    this.distances[mine][i.site] = i.distance;
                }
            }
        }
Exemplo n.º 7
0
        static Move V4Strategy(
            MoveMessage message,
            SolverState solverState)
        {
            var startTime = DateTime.UtcNow;

            var deadLine = startTime.AddMilliseconds(900);

            var myId = solverState.initialState.punter.Value;

            var initialMap = solverState.initialState.map;

            var takenRivers = Utils.ConvertMovesToRivers(initialMap, solverState.moves, (id) => true)
                              .ToLookup(river => river, river => true);

            var availableRivers = initialMap.rivers
                                  .Where(river => !takenRivers.Contains(river))
                                  .ToList();

            var canUseOptions =
                solverState.initialState.settings.options &&
                solverState.moves.Count(move => move.option != null && move.option.punter == myId) < initialMap.mines.Count;

            var adjacencyMap = new AdjacencyMap(initialMap.rivers);

            var mineDistances = new MineDistances(initialMap, adjacencyMap);

            var setupDoneTime = DateTime.UtcNow;

            // if we see a choke, take it
            var chokeFindTask = Task.Run(() =>
            {
                var punters = new List <int>()
                {
                    myId
                };
                if (solverState.initialState.punters.Value == 2)
                {
                    punters.Add(1 - myId);
                }

                foreach (var punter in punters)
                {
                    var availableOptions = new List <River>();
                    if (canUseOptions && punter == myId)
                    {
                        var takenOptions = Utils.ConvertMovesToRivers(initialMap, solverState.moves.Where(move => move.option != null), (id) => true)
                                           .ToLookup(river => river, river => true);

                        availableOptions =
                            Utils.ConvertMovesToRivers(initialMap, solverState.moves, (id) => id != myId)
                            .Where(river => !takenOptions.Contains(river))
                            .ToList();
                    }

                    var chokes = FindChokes(
                        initialMap.mines,
                        Utils.ConvertMovesToRivers(initialMap, solverState.moves, (id) => id == punter).ToList(),
                        availableRivers.Concat(availableOptions).ToList(),
                        deadLine.AddMilliseconds(-100));

                    if (chokes.Any())
                    {
                        var river = chokes[0][0];

                        var chokeAnalysisDoneTime = DateTime.UtcNow;

                        Log(myId, string.Format("[{0}] [{1}] [{2}/{3}]",
                                                punter == myId ? "TakeChoke " : "BlockChoke",
                                                (int)(chokeAnalysisDoneTime - startTime).TotalMilliseconds,
                                                (int)(setupDoneTime - startTime).TotalMilliseconds,
                                                (int)(chokeAnalysisDoneTime - setupDoneTime).TotalMilliseconds));

                        return(availableOptions.Contains(river) ? CreateOptionMove(myId, river) : CreateClaimMove(myId, river));
                    }
                }

                return(null);
            });

            // otherwise just play a move that joins two trees, increases liberty, or increases score
            var trees = new TreeSet(
                Utils.ConvertMovesToRivers(initialMap, solverState.moves, (id) => id == myId),
                initialMap.mines);

            var riversToConsider = availableRivers
                                   .Where(river => trees.Contains(river.source) || trees.Contains(river.target))
                                   .DefaultIfEmpty(availableRivers.First());

            var riversConsidered =
                from river in riversToConsider
                where DateTime.UtcNow < deadLine
                let newTrees = trees.AddRiver(river)
                               let treeCount = newTrees.Trees.Count
                                               let liberty                         = newTrees.ComputeLiberty(availableRivers, adjacencyMap)
                                                                         let score = newTrees.ComputeScore(mineDistances)
                                                                                     select new { river = river, liberty = liberty, score = score, treeCount = treeCount };

            var rankedRivers = riversConsidered
                               .ToList()
                               .OrderBy(i => i.treeCount)
                               .ThenByDescending(i => i.liberty)
                               .ThenByDescending(i => i.score);

            var ans = CreateClaimMove(myId, rankedRivers.First().river);

            var analysisDoneTime = DateTime.UtcNow;

            var zero     = TimeSpan.FromTicks(0);
            var waitTime = deadLine - DateTime.UtcNow;

            waitTime = waitTime < zero ? zero : waitTime;
            chokeFindTask.Wait(waitTime);

            if (chokeFindTask.IsCompleted && chokeFindTask.Result != null)
            {
                return(chokeFindTask.Result);
            }

            var doneTime = DateTime.UtcNow;

            Log(myId, string.Format("[NormalMove] [{0}] [{1}/{2}/{3}] [Trees:{4}] [Liberties:{5}] [Score:{6}]",
                                    (int)(doneTime - startTime).TotalMilliseconds,
                                    (int)(setupDoneTime - startTime).TotalMilliseconds,
                                    (int)(analysisDoneTime - setupDoneTime).TotalMilliseconds,
                                    (int)(doneTime - analysisDoneTime).TotalMilliseconds,
                                    rankedRivers.First().treeCount,
                                    rankedRivers.First().liberty,
                                    rankedRivers.First().score));

            return(ans);
        }