private static async Task SolveCurrentBlockAsync() { var balanceInfo = int.Parse(await FetchApiAsync("getbalance", "83")); var metaInfo = JObject.Parse(await FetchApiAsync("getblockchaininfo", null)); var blockNum = metaInfo["block"].Value <int>(); var blockSubs = metaInfo["block_subs"].Value <int>(); var blockInfo = JObject.Parse(await FetchApiAsync("getblockinfo", blockNum.ToString())); var blockTs = DateTimeOffset.FromUnixTimeSeconds((int)blockInfo["block_ts"].Value <double>()); var blockAge = DateTimeOffset.UtcNow - blockTs; var puzzleText = blockInfo["puzzle"].Value <string>(); var taskText = blockInfo["task"].Value <string>(); Console.WriteLine($"Current block: #{blockNum}, aged {blockAge}, {blockSubs} submissions, our balance: {balanceInfo}"); var solutionDir = FindSolutionDir(); var blockDir = Path.Combine(solutionDir, $@"Data\blocks\{blockNum}"); if (!Directory.Exists(blockDir)) { Console.WriteLine("This is a totally new block; creating a new directory"); Directory.CreateDirectory(blockDir); } var puzzleFile = Path.Combine(blockDir, "puzzle.cond"); if (!File.Exists(puzzleFile)) { Console.WriteLine($"Writing the original puzzle: {puzzleText}"); File.WriteAllText(puzzleFile, puzzleText); } var puzzleSolutionFile = $"{puzzleFile}.desc"; if (!File.Exists(puzzleSolutionFile)) { Console.WriteLine("Solving puzzle"); var seed = 3133337; var tries = 0; while (true) { if (++tries == 200) { throw new Exception("Faile to solve puzzle!"); } Console.WriteLine($"Solving puzzle with seed {seed}"); var puzzle = new Puzzle(puzzleText, seed); File.WriteAllText(puzzleSolutionFile, puzzle.SaveToMap()); puzzle.SaveToBitmap().Save($"{puzzleFile}.png"); try { puzzle.EnsureMapIsValid(puzzleSolutionFile); Console.WriteLine("Have a valid solution"); break; } catch (Exception ex) { Console.WriteLine($"Puzzle solution is invalid: {ex.Message}"); ++seed; } } } var taskFile = Path.Combine(blockDir, "task.desc"); if (!File.Exists(taskFile)) { Console.WriteLine($"Writing the original task: {taskText}"); File.WriteAllText(taskFile, taskText); } var extSolutionFile = $"{taskFile}.ext-sol"; var solutionFile = $"{taskFile}.sol"; Console.WriteLine("Solving task"); var sw = new Stopwatch(); sw.Start(); // shuffled strategies list var strategies = StrategyFactory.GenerateStrategies().ToArray(); var rng = new Random(); strategies = new[] { new DumbBfs() }.Concat(strategies.OrderBy(s => rng.Next())).ToArray(); // Block lives for 15 minutes, lets try to solve everything by 14:00 var blockLifetimeMs = 10 * 60 * 1000; var timeToSolve = Math.Max(5000, blockLifetimeMs - blockAge.TotalMilliseconds); Console.WriteLine($"Time to solve: {timeToSolve} ms"); var map = MapParser.Parse(taskText, string.Empty); var solutions = strategies.AsParallel().WithDegreeOfParallelism(10) .Select( strategy => { var run = false; lock (sw) { run = sw.ElapsedMilliseconds < timeToSolve; } return(run ? Emulator.MakeExtendedSolution(map, strategy, string.Empty) : Emulator.MakeExtendedSolution(map, "fail", new Command[][] { }, string.Empty)); }); var numSuccess = 0; foreach (var sln in solutions) { if (sln.IsSuccessful) { ++numSuccess; } sln.SaveIfBetter(extSolutionFile); } Console.WriteLine($" Solution took: {sw.ElapsedMilliseconds} ms, {numSuccess} strategies out of {strategies.Length} successed"); var extSolution = ExtendedSolution.Load(extSolutionFile); if (!extSolution.IsSuccessful) { throw new Exception("ext solution is not successful!"); } File.WriteAllText(solutionFile, extSolution.Commands); var submissionResultFile = Path.Combine(blockDir, "submit.txt"); if (!File.Exists(submissionResultFile)) { Console.WriteLine("SUBMITTING!"); var payload = new MultipartFormDataContent(); payload.Add(new StringContent("2a78df7b478788ae4cf9d338"), "private_id"); payload.Add(new StringContent(blockNum.ToString()), "block_num"); payload.Add(new ByteArrayContent(File.ReadAllBytes(solutionFile)), "solution", "task.desc.sol"); payload.Add(new ByteArrayContent(File.ReadAllBytes(puzzleSolutionFile)), "puzzle", "puzzle.cond.desc"); var httpClient = new HttpClient(); var response = await httpClient.PostAsync($"{BlockChainUrl}/submit", payload); var submissionResult = await response.Content.ReadAsStringAsync(); Console.WriteLine($"RESULT: {submissionResult}"); File.WriteAllText(submissionResultFile, submissionResult); } }
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); } } });