private static Tuple<double, Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[]> FindBestPositions_Recursive(int unitsAhead, Map map, Unit[] units, int unitIndex, string[] powerPhrases, bool[] spelledPhrases) { if (unitsAhead < 0 || unitIndex >= units.Length) { return Tuple.Create(0.0, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); } var reachablePositions = new ReachablePositionsWithWords(map, powerPhrases, spelledPhrases); //var reachablePositions = new ReachablePositions(map); var evaluatePositions = new EvaluatePositions2(map); var unit = units[unitIndex]; var endPositions = reachablePositions.SingleEndPositions(unit); var estimated = new Dictionary<Unit, double>(); double? bestScore = null; var topOrderedPositions = endPositions .Select(p => { double value; if (estimated.TryGetValue(p.Item1, out value)) return Tuple.Create(value, p); var score = estimated[p.Item1] = evaluatePositions.Evaluate(p.Item1); return Tuple.Create(score, p); }) //.OrderByDescending(t => t.Item1) .OrderByDescending(t => (int)Math.Round(t.Item1 * 100)) .ThenByDescending(t => t.Item2.Item2.score) .TakeWhile(tt => { if (!bestScore.HasValue) { bestScore = tt.Item1; return true; } return Math.Abs(tt.Item1 - bestScore.Value) < 1e-6; }).ToList(); if (!topOrderedPositions.Any()) { return Tuple.Create(-1e3, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); } var bestPosistions = Tuple.Create(double.MinValue, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); foreach (var position in topOrderedPositions) { var newMap = map.Clone(); newMap.LockUnit(position.Item2.Item1); newMap.RemoveLines(); var nextPositions = FindBestPositions_Recursive(unitsAhead - 1, newMap, units, unitIndex + 1, powerPhrases, position.Item2.Item2.spelledWords); var score = position.Item1 + nextPositions.Item1; if (bestPosistions.Item1 < score) { bestPosistions = Tuple.Create(score, new[] {position.Item2}.Concat(nextPositions.Item2).ToArray()); } } return bestPosistions; }
public string Solve(Problem problem, int seed, string[] powerPhrases) { var finalPowerPhraseBuilder = new SimplePowerPhraseBuilder(powerPhrases); var spelledPhrases = new bool[powerPhrases.Length]; var solution = new List<MoveType>(); var game = new SolverGame(problem, seed, powerPhrases); while (true) { switch (game.state) { case GameBase.State.WaitUnit: game.Step(); break; case GameBase.State.UnitInGame: var reachablePositions = new ReachablePositionsWithWords(game.map, powerPhrases, spelledPhrases); var evaluatePositions = new EvaluatePositions2(game.map); var endPositions = reachablePositions.EndPositions(game.currentUnit); var estimated = new Dictionary<Unit, double>(); var bestPosition = endPositions.ArgMax(p => { double value; if (estimated.TryGetValue(p.Item1, out value)) return value; return estimated[p.Item1] = evaluatePositions.Evaluate(p.Item1); }); var score = evaluatePositions.Evaluate(bestPosition.Item1); var wayToBestPosition = bestPosition.Item2; var unitSolution = staticPowerPhraseBuilder.Build(wayToBestPosition.path); SolutionAdded(game, unitSolution); game.ApplyUnitSolution(unitSolution); spelledPhrases = wayToBestPosition.spelledWords; solution.AddRange(wayToBestPosition.path); break; case GameBase.State.EndInvalidCommand: case GameBase.State.EndPositionRepeated: throw new InvalidOperationException(string.Format("Invalid state: {0}", game.state)); case GameBase.State.End: return finalPowerPhraseBuilder.Build(solution); default: throw new ArgumentOutOfRangeException(); } } }
private IEnumerable<State> FindNextStates(State state) { var map = state.lastmap.Clone(); map.LockUnit(state.lastUnit); map.RemoveLines(); var nextUnit = units[state.nunits]; var reachablePositions = new ReachablePositionsWithWords(map, powerPhrases, state.spelledPhrases); var evaluatePositions = new EvaluatePositions2(map); var endPositions = reachablePositions.EndPositions(nextUnit); var estimated = new Dictionary<Unit, Tuple<double, int>>(); Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[] bestPositions = endPositions.OrderByDescending( p => { Tuple<double, int> value; var unit = p.Item1; if (!estimated.TryGetValue(unit, out value)) value = estimated[p.Item1] = evaluatePositions._Evaluate(p.Item1); return value.Item1; }).Take(100).ToArray(); foreach (var position in bestPositions) { var unit = position.Item1; var ndropped = estimated[unit].Item2; var move_score = CountPoints(unit.members.Count, state.lastDroopedLines, estimated[unit].Item2); var score = state.score + move_score; yield return new State() { lastmap = map, lastUnit = unit, nunits = state.nunits + 1, lastDroopedLines = ndropped, score = score, solution = state.solution.Concat(position.Item2.path).ToArray(), spelledPhrases = position.Item2.spelledWords, sumPositionEstimates = state.sumPositionEstimates + 10 + estimated[unit].Item1 }; } }
private Tuple<double, Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[]> FindBestPositions_Recursive(int unitsAhead, Map map, Unit[] units, int unitIndex, string[] powerPhrases, bool[] spelledPhrases) { if (unitsAhead < 0 || unitIndex >= units.Length) { return Tuple.Create(0.0, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); } var reachablePositions = new ReachablePositionsWithWords(map, powerPhrases, spelledPhrases); //var reachablePositions = new ReachablePositions(map); // var evaluatePositions = new EvaluatePositions(map); var evaluatePositions = new EvaluatePositions2(map); var unit = units[unitIndex]; var endPositions = reachablePositions.SingleEndPositions(unit); var estimated = new Dictionary<Unit, double>(); var topOrderedPositions = endPositions .Select(p => { double value; if (estimated.TryGetValue(p.Item1, out value)) return Tuple.Create(value, p); var score = estimated[p.Item1] = evaluatePositions.Evaluate(p.Item1); return Tuple.Create(score, p); }) //.OrderByDescending(t => t.Item1) .OrderByDescending(t => (int)Math.Round(t.Item1 * 100) + t.Item2.Item2.score) .ToList(); var equallyTop = GetEquallyGoodTop(topOrderedPositions); var positionsForLookingAhead = topOrderedPositions.Take(Math.Max(equallyTop, minTopUnitCount)).ToList(); if (!positionsForLookingAhead.Any()) { return Tuple.Create(-1e3, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); } var bestPosistions = Tuple.Create(double.MinValue, new Tuple<Unit, ReachablePositionsWithWords.VisitedInfo>[0]); foreach (var position in positionsForLookingAhead) { var newMap = map.Clone(); newMap.LockUnit(position.Item2.Item1); newMap.RemoveLines(); var nextPositions = FindBestPositions_Recursive(unitsAhead - 1, newMap, units, unitIndex + 1, powerPhrases, position.Item2.Item2.spelledWords); var score = position.Item1 + nextPositions.Item1; if (bestPosistions.Item1 < score) { bestPosistions = Tuple.Create(score, new[] {position.Item2}.Concat(nextPositions.Item2).ToArray()); } } return bestPosistions; }