private void TestOnSampleMap(string moves, bool isSuccessful, int?timeUnits) { var solution = Emulator.MakeExtendedSolution(this.sampleMap, "test", CommandsSerializer.Parse(moves), string.Empty); Assert.Equal(isSuccessful, solution.IsSuccessful); Assert.Equal(timeUnits, solution.TimeUnits); }
public void CloningSampleSolutionIsValid() { var map = MapParser.Parse("(0,0),(10,0),(10,10),(0,10)#(0,0)#(4,2),(6,2),(6,7),(4,7);(5,8),(6,8),(6,9),(5,9)#B(0,1);F(0,2);L(0,3);R(0,4);C(0,5);C(0,6);C(0,7);X(0,9)", string.Empty); var commands = CommandsSerializer.Parse("WWWWWWWWWCDDDDDDESSSSSS#CDDDDDDDDESSSSSSSS#CSSDDDESSSSS#ESSSSSSSSSQDDDDD"); var solution = Emulator.MakeExtendedSolution(map, "test", commands, string.Empty); Assert.True(solution.IsSuccessful); Assert.Equal(28, solution.TimeUnits); }
private static void TestSerialization( string serializedMoves, params Command[] [] commands) { var parsedMoves = CommandsSerializer.Parse(serializedMoves); var serializedBackMoves = CommandsSerializer.Serialize(commands); Assert.Equal(commands, parsedMoves); Assert.Equal(serializedMoves, serializedBackMoves); }
public static void Main(string[] args) { const int Iterations = 1; for (var i = 0; i < Iterations; ++i) { var baseDir = args.Length > 0 ? args[0] : FindSolutionDir(); Directory.SetCurrentDirectory(baseDir); var strategies = StrategyFactory.GenerateStrategies().ToArray(); var packFile = "Data/booster-pack.txt"; var mapToPack = File.ReadAllLines(packFile).Select(line => line.Split(' ')).ToDictionary(tokens => tokens[0], tokens => tokens[1]); var totalTimeUnits = 0; var haveFailures = false; var outputLock = new object(); Parallel.ForEach( Directory.EnumerateFiles("Data/maps", "*.desc"), new ParallelOptions { MaxDegreeOfParallelism = 10 }, mapFile => { var log = new List <string>(); var mapName = Path.GetFileNameWithoutExtension(mapFile); void Log(string msg) { if (LogImmediately) { Console.WriteLine($"{mapName}: {msg}"); } else { log.Add(msg); } } if (!mapToPack.ContainsKey(mapName)) { return; } string packedBoosters = mapToPack.ContainsKey(mapName) ? mapToPack[mapName] : string.Empty; Log($"Processing {mapName} with extra boosters: [{packedBoosters}]"); var map = MapParser.Parse(File.ReadAllText(mapFile), packedBoosters); var solutionSuffix = packedBoosters != string.Empty ? "-packed" : string.Empty; var extSolutionPath = $"Data/extended-solutions{solutionSuffix}/{mapName}.ext-sol"; // Delete broken solutions if (File.Exists(extSolutionPath)) { var oldSolution = ExtendedSolution.Load(extSolutionPath); var oldCommands = CommandsSerializer.Parse(oldSolution.Commands); if (!Emulator.MakeExtendedSolution(map, string.Empty, oldCommands, packedBoosters).IsSuccessful) { File.Delete(extSolutionPath); } } var rng = new Random(); var currentStrategies = StrategiesLimit != null ? strategies.OrderBy(s => rng.Next()).Take(StrategiesLimit.Value).ToArray() : strategies; var solutions = currentStrategies.AsParallel() .Where(strategy => !(mapName.Contains("294") && strategy.Name.Contains("DumbBfs"))) .Select(strategy => (strategy, Emulator.MakeExtendedSolution(map, strategy, packedBoosters))); var numSuccessful = 0; foreach (var pair in solutions) { var(strategy, solution) = pair; solution.SaveIfBetter(extSolutionPath); if (solution.IsSuccessful) { Log($" {strategy.Name}: {solution.TimeUnits}"); if (StrategiesLimit != null && ++numSuccessful >= StrategiesLimit) { break; } } } var best = ExtendedSolution.Load(extSolutionPath); File.WriteAllText($"Data/solutions{solutionSuffix}/{mapName}.sol", best.Commands); if (solutionSuffix != string.Empty) { File.WriteAllText($"Data/solutions{solutionSuffix}/{mapName}.buy", packedBoosters); } Log($" BEST ({best.StrategyName}): {best.IsSuccessful}/{best.TimeUnits}"); lock (outputLock) { if (best.TimeUnits.HasValue) { totalTimeUnits += best.TimeUnits.Value; } else { haveFailures = true; } foreach (var line in log) { Console.WriteLine(line); } } });
public IEnumerable <Command[]> SolveWithClones(State state) { var addedBots = new List <(int time, State.Bot bot)>(); var time = 0; var cloningCommands = MakeClones().ToList(); var cloningTime = cloningCommands.Count; var stateAfterCloning = state; var firstBotSolutionSize = this.baseStrategy .Solve(stateAfterCloning.ReplaceBots(resetBoosters: false, stateAfterCloning.GetBot(0))) .Count(); var totalBonusTime = addedBots.Sum(tup => cloningTime - tup.time); var stepsPerBot = Math.Min( firstBotSolutionSize / (1 + addedBots.Count), Math.Max(0, firstBotSolutionSize - totalBonusTime) / (1 + addedBots.Count)); while (true) { var commandsPerBot = new Command[addedBots.Count + 1][]; var botState = stateAfterCloning.ReplaceBots(resetBoosters: false, state.GetBot(0)); var bot = botState.GetBot(0); var botIdx = 0; while (true) { var bonusTime = botIdx == 0 ? 0 : cloningTime - addedBots[botIdx - 1].time; var left = stepsPerBot + bonusTime; var commandsBuf = new List <Command>(); foreach (var cmd in this.baseStrategy.Solve(botState)) { if (left-- <= 0) { break; } commandsBuf.Add(cmd.Single()); var nextState = botState.Next(cmd); if (nextState == null) { throw new Exception("shouldn't happen"); } botState = nextState; } commandsPerBot[botIdx] = commandsBuf.ToArray(); if (++botIdx >= stateAfterCloning.BotsCount) { break; } botState = botState.ReplaceBots(resetBoosters: true, addedBots[botIdx - 1].bot); } if (botState.Map.CellsToVisit.Count == botState.WrappedCellsCount) { commandsPerBot[0] = cloningCommands.Concat(commandsPerBot[0]).ToArray(); foreach (var cmds in CommandsSerializer.Transponse(commandsPerBot)) { yield return(cmds); } break; } stepsPerBot = (int)(1 + (stepsPerBot * 1.1)); } IEnumerable <Command> MakeClones() { var map = state.Map; var bfs = new BfsState(map); while (addedBots.Count < map.NumCloneBoosts) { var bot = state.GetBot(0); foreach (var cmd in FindBooster()) { ++time; state = state.Next(cmd) ?? throw new Exception("Impossible"); yield return(cmd); } while (map[bot.X, bot.Y] == Map.Cell.SpawnPoint && state.CloneBoosterCount > 0) { ++time; addedBots.Add((time, bot)); state = state.Next(Clone.Instance) ?? throw new Exception("Impossible"); yield return(Clone.Instance); } } IEnumerable <Command> FindBooster() { var bot = state.GetBot(0); ++bfs.Generation; bfs.Queue.Clear(); bfs.Queue.Enqueue((bot.X, bot.Y, bot.Dir)); bfs.Nodes[bot.X, bot.Y, 0] = new BfsState.Node(bfs.Generation, -1, 0); while (bfs.Queue.Count > 0) { var(x, y, dir) = bfs.Queue.Dequeue(); if ((map[x, y] == Map.Cell.Clone && !state.IsPickedUp(x, y) && (x, y) != (bot.X, bot.Y)) || (map[x, y] == Map.Cell.SpawnPoint && (state.CloneBoosterCount > 0 || (map[bot.X, bot.Y] == Map.Cell.Clone && !state.IsPickedUp(bot.X, bot.Y))))) { bfs.FindBackwardPath(x, y, 0, bot); return(bfs.Path); } for (var i = 0; i < Move.All.Length; ++i) { var move = Move.All[i]; var nx = x + move.Dx; var ny = y + move.Dy; if (map.IsFree(nx, ny) && bfs.Nodes[nx, ny, dir].Generation != bfs.Generation) { bfs.Nodes[nx, ny, dir] = new BfsState.Node(bfs.Generation, i, 0); bfs.Queue.Enqueue((nx, ny, dir)); } } } throw new Exception("oops"); } } }