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 EvaluatePositions(Map map) { this.map = map; for (int y = 0; y < map.Height; ++y) { var emptyCellsInLine = new List<Cell>(); for (int x=0; x<map.Width; ++x) if (!map[x, y].filled) emptyCellsInLine.Add(map[x,y]); emptyCellsInLines.Add(emptyCellsInLine); } }
public EvaluatePositions2(Map map) { this.map = map; for (int y = 0; y < map.Height; ++y) { var emptyCellsInLine = new List<Cell>(); for (int x = 0; x < map.Width; ++x) if (!map[x, y].filled) { emptyCellsInLine.Add(map[x, y]); freeInputsForCells[map[x, y]] = CountFreeInputs(map[x,y]); } emptyCellsInLines.Add(emptyCellsInLine); int countLockedInLine = emptyCellsInLine.Count(c => freeInputsForCells[c] == 0); foreach (var c in emptyCellsInLine) UsabilityForCells[c] = 0.1 + 1.0/emptyCellsInLine.Count - ((double)countLockedInLine)/map.Width; } }
public EvaluatePositions3(Map map) { this.map = map; emptyCells = new Cell[map.Height][]; blockedCells = new int[map.Height]; inputsOfCells = new Dictionary<Cell, Cell[]>(); for (int y = 0; y < map.Height; ++y) { var emptyCellsInLine = new List<Cell>(); for (int x = 0; x < map.Width; ++x) if (!map[x, y].filled) { emptyCellsInLine.Add(map[x, y]); inputsOfCells[map[x, y]] = FreeInputs(map[x, y]).ToArray(); } emptyCells[y] = emptyCellsInLine.ToArray(); blockedCells[y] = emptyCellsInLine.Count(c => CountFreeInputs(c) == 0); } }
public EvaluatePositions22(Map map) { this.map = map; this.maxLenPath = Math.Min(Math.Min(map.Width, map.Height)/3, 6); for (int y = 0; y < map.Height; ++y) { var emptyCellsInLine = new List<Cell>(); for (int x = 0; x < map.Width; ++x) { var cell = map[x, y]; if (!cell.filled) { emptyCellsInLine.Add(map[x, y]); freeInputsForCells[map[x, y]] = CountFreeInputs(map[x, y]); accessablityOfCell[cell] = new Access() { E = FindFreeLinearPath(cell, MoveType.E), W = FindFreeLinearPath(cell, MoveType.W), NE = FindFreeLinearPath(cell, MoveType.NE), NW = FindFreeLinearPath(cell, MoveType.NW) }; } } emptyCellsInLines.Add(emptyCellsInLine); int countLockedInLine = emptyCellsInLine.Count(c => freeInputsForCells[c] == 0); countLockedCellsInLines.Add(countLockedInLine); int countBadAccessedInLine = emptyCellsInLine.Count(c => accessablityOfCell[c].Accessability().Max() < maxLenPath); foreach (var c in emptyCellsInLine) { usabilityOfCells[c] = 0.1 + 1.0/emptyCellsInLine.Count - ((double)countLockedInLine) / map.Width; } } for (int y = 0; y < map.Height/3; ++y) for (int x = map.Width / 3; x <= map.Width * 3 / 4; ++x) usabilityOfCells[new Cell() { x = x, y = y }] = -map.Height/4 /(1.0 + Math.Min(y, x)); }
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; }
public virtual void ReStart() { var filledCells = problem.filled.ToDictionary(cell => Tuple.Create<int, int>(cell.x, cell.y), cell => cell.Fill()); map = new Map(problem.width, problem.height); for (int x = 0; x < problem.width; x++) for (int y = 0; y < problem.height; y++) { Cell cell; if (filledCells.TryGetValue(Tuple.Create(x, y), out cell)) map[x, y] = cell; else map[x, y] = new Cell { x = x, y = y }; } units = problem.units; for (int i = 0; i < units.Length; i++) { units[i] = SpawnUnit(units[i], problem); } randomGenerator = new LinearCongruentalGenerator(seed); UnitIndeces = new int[problem.sourceLength]; for (int i = 0; i < problem.sourceLength; i++) { UnitIndeces[i] = randomGenerator.GetNext()%units.Length; } state = State.WaitUnit; step = 0; currentUnit = null; forbiddenSequenceChecker = null; moves = null; currentUnitIndex = 0; currentMovesScore = 0; currentSpellsScore = 0; previouslyExplodedLines = 0; enteredString = new StringBuilder(); EnteredMagicSpells = new List<string>(); }
public void DrawMap(Map map, Unit unit, bool locked = false) { for (int i = 0; i < 3 * map.Height + 1; i++) { var row = i / 3; if (i % 3 == 0) { console.BackgroundColor = ConsoleColor.Black; console.Write(" "); for (int col = 0; col < map.Width; ++col) { if (row % 2 == 1) { var viewInfo = GetViewInfo(map, unit, col, row - 1, locked); console.ForegroundColor = viewInfo.ForegroundColor; console.BackgroundColor = viewInfo.BackgroundColor; console.Write(new string(viewInfo.Char, 2)); } if (row < map.Height) { var viewInfo = GetViewInfo(map, unit, col, row, locked); console.ForegroundColor = viewInfo.ForegroundColor; console.BackgroundColor = viewInfo.BackgroundColor; console.Write(new string(viewInfo.Char, 2)); } else { console.BackgroundColor = ConsoleColor.Black; console.Write(" "); } if (row == 0) { console.BackgroundColor = ConsoleColor.Black; console.Write(" "); } else if (row % 2 == 0) { var viewInfo = GetViewInfo(map, unit, col, row - 1, locked); console.ForegroundColor = viewInfo.ForegroundColor; console.BackgroundColor = viewInfo.BackgroundColor; console.Write(new string(viewInfo.Char, 2)); } } } else { if (row % 2 == 1) { console.BackgroundColor = ConsoleColor.Black; console.Write(" "); } for (int col = 0; col < map.Width; ++col) { var viewInfo = GetViewInfo(map, unit, col, row, locked); console.ForegroundColor = viewInfo.ForegroundColor; console.BackgroundColor = viewInfo.BackgroundColor; console.Write(new string(viewInfo.Char, 4)); } } console.WriteLine(); } }
private CellViewInfo GetViewInfo(Map map, Unit unit, int col, int row, bool locked) { var result = GetMapViewInfo(map[col, row]); if (unit != null) { var unitCell = unit.members.SingleOrDefault(x => x.x == col && x.y == row); if (unitCell != null) { result = new CellViewInfo { BackgroundColor = locked ? ConsoleColor.Green : ConsoleColor.Red, Char = ' ' }; } var isPivot = unit.pivot.x == col && unit.pivot.y == row; if (isPivot) result.Char = 'X'; } return result; }
public void DrawUnit(Unit unit) { var minY = unit.members.Concat(new[]{unit.pivot}).Min(cell => cell.y); while (minY > 0) { unit = unit.Move(MoveType.NE); minY--; } while (minY < 0) { unit = unit.Move(MoveType.SE); minY++; } var minX = unit.members.Min(cell => cell.x); while (minX > 0) { unit = unit.Move(MoveType.W); minX--; } while (minX < 0) { unit = unit.Move(MoveType.E); minX++; } var map = new Map(unit.members.Concat(new[] { unit.pivot }).Max(cell => cell.x) + 1, unit.members.Concat(new[] { unit.pivot }).Max(cell => cell.y) + 1); console.WriteLine(); DrawMap(map, unit); }
public ReachablePositionsWithWords(Map map, string[] powerPhrases, bool[] powerPhrasesSpelled) { this.map = map; this.powerPhrases = powerPhrases; this.powerPhrasesSpelled = powerPhrasesSpelled; }
public ReachablePositions(Map map) { this.map = map; }
public bool IsCorrect(Map map) { return !members.Any(cell => cell.x < 0 || cell.y < 0 || cell.x >= map.Width || cell.y >= map.Height || map[cell.x, cell.y].filled); }