public static void Register(CommandLineApplication app)
        {
            app.Command(
                "solve",
                (command) =>
            {
                command.Description = "Solve all problems with all solvers";
                command.HelpOption("-?|-h|--help");

                var solverOption = command.Option(
                    "-s|--solver",
                    "Solver name prefix",
                    CommandOptionType.SingleValue);

                var problemsOption = command.Option(
                    "-p|--problems",
                    "Single problem id or problem ids range",
                    CommandOptionType.SingleValue);

                command.OnExecute(
                    () =>
                {
                    var solvers = RunnableSolvers
                                  .Enumerate()
                                  .Select(x => x.Invoke())
                                  .Where(x => !solverOption.HasValue() || solverOption.HasValue() && x.GetName().StartsWith(solverOption.Value()))
                                  .ToList();

                    var problemIds = new List <int>();
                    if (problemsOption.HasValue())
                    {
                        if (int.TryParse(problemsOption.Value(), out var problemId))
                        {
                            problemIds.Add(problemId);
                        }
                        else
                        {
                            var parts  = problemsOption.Value().Split(new [] { ".." }, StringSplitOptions.RemoveEmptyEntries);
                            var pStart = int.Parse(parts[0]);
                            var pEnd   = int.Parse(parts[1]);
                            problemIds.AddRange(Enumerable.Range(pStart, pEnd - pStart + 1));
                            Console.WriteLine($"Will solve problems: {string.Join(", ", problemIds)}");
                        }
                    }

                    solvers.ForEach(
                        solver =>
                    {
                        ProblemReader
                        .ReadAll()
                        .Where(x => !problemIds.Any() || problemIds.Contains(x.ProblemId))
                        .ToList()
                        .ForEach(problemMeta => Common.Solve(solver, problemMeta));
                    });

                    return(0);
                });
            });
        }
Esempio n. 2
0
        public static void Register(CommandLineApplication app)
        {
            app.Command(
                "solve-unsolved",
                (command) =>
            {
                command.Description = "Create solutions for all nonexistent problem-solver pairs";
                command.HelpOption("-?|-h|--help");

                var threadsOption = command.Option(
                    "-t|--threads",
                    "Number of worker threads",
                    CommandOptionType.SingleValue);

                command.OnExecute(
                    () =>
                {
                    var threadsCount = threadsOption.HasValue() ? int.Parse(threadsOption.Value()) : Environment.ProcessorCount;
                    var threads      = Enumerable.Range(0, threadsCount).ToList();
                    Parallel.ForEach(
                        threads,
                        new ParallelOptions {
                        MaxDegreeOfParallelism = threadsCount
                    },
                        thread =>
                    {
                        while (true)
                        {
                            var solvers = RunnableSolvers
                                          .Enumerate()
                                          .OrderBy(_ => Guid.NewGuid())
                                          .Select(x => x.Invoke())
                                          .ToList();

                            var problems = ProblemReader.ReadAll();

                            solvers.ForEach(
                                solver =>
                            {
                                var solved   = Storage.EnumerateSolved(solver).Select(x => x.ProblemId);
                                var unsolved = problems
                                               .Select(x => x.ProblemId)
                                               .Except(solved)
                                               .OrderBy(_ => Guid.NewGuid())
                                               .ToList()
                                               .First();

                                Common.Solve(solver, problems.Find(x => x.ProblemId == unsolved), thread);
                            });
                        }
                    });

                    return(0);
                });
            });
        }
        public static void Solve(ISolver solver, ProblemMeta problemMeta, int?thread = null)
        {
            var prefix = thread.HasValue ? $"#{thread.Value}: " : string.Empty;

            Console.WriteLine($"{prefix}{DateTime.Now}: Solving {problemMeta.ProblemId} with {solver.GetName()} v{solver.GetVersion()}... ");

            new SolutionInProgress(problemMeta.ProblemId, solver.GetName(), solver.GetVersion()).SaveToDb();
            try
            {
                var solutionMeta = RunnableSolvers.Solve(solver, problemMeta);
                solutionMeta.SaveToDb();
                Console.WriteLine($"{prefix}Done in {solutionMeta.CalculationTookMs} ms, {solutionMeta.OurTime} time units");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
        private static async Task <int> SolveBlock(CommandOption blockNumberOption, CommandOption submitOption)
        {
            BlockchainBlock block;

            if (blockNumberOption.HasValue())
            {
                block = await Api.GetBlockchainBlock(int.Parse(blockNumberOption.Value()));
            }
            else
            {
                block = await Api.GetBlockchainBlock();
            }
            Console.WriteLine($"Solving block #{block.BlockNumber} ... {DateTime.Now}");

            var blockProblemPath = Path.Combine(FileHelper.PatchDirectoryName("problems"), "puzzles", $"block{block.BlockNumber:000}_orig.desc");

            if (submitOption.HasValue() && File.Exists(blockProblemPath))
            {
                Console.WriteLine("Already solved.");
                Thread.Sleep(TimeSpan.FromSeconds(10));
                return(0);
            }

            File.WriteAllText(blockProblemPath, block.Problem.ToString());

            var puzzlePath = Path.Combine(FileHelper.PatchDirectoryName("problems"), "puzzles", $"block{block.BlockNumber:000}.cond");

            File.WriteAllText(puzzlePath, block.Puzzle.ToString());

            Console.WriteLine($"Solving puzzle ...");

            var puzzleSolvers = new List <IPuzzleSolver>
            {
                new MstPuzzleSolver(),
            };

            var puzzleSolved   = false;
            var ourProblemPath = Path.Combine(FileHelper.PatchDirectoryName("problems"), "puzzles", $"block{block.BlockNumber:000}.desc");

            foreach (var puzzleSolver in puzzleSolvers)
            {
                var ourProblem = puzzleSolver.Solve(block.Puzzle);
                if (!ourProblem.IsValidForPuzzle(block.Puzzle))
                {
                    continue;
                }

                puzzleSolved = true;
                File.WriteAllText(ourProblemPath, ourProblem.ToString());
            }

            if (!puzzleSolved)
            {
                throw new Exception("Puzzle not solved.");
            }

            var solvers = RunnableSolvers
                          .PuzzleSolvers()
                          .Select(x => x.Invoke())
                          //.Take(1)
                          .ToList();

            var mapSize = block.Problem.ToState().Map;

            Console.WriteLine($"Solving problem {mapSize.SizeX}x{mapSize.SizeY} with {solvers.Count} solvers ...");

            var results   = new List <Tuple <ISolver, List <List <ActionBase> > > >();
            var stopwatch = Stopwatch.StartNew();

            foreach (var solver in solvers)
            {
                if (stopwatch.Elapsed > TimeSpan.FromMinutes(10))
                {
                    break;
                }

                var solved          = solver.Solve(block.Problem.ToState().Clone());
                var calculationTime = stopwatch.ElapsedMilliseconds;

                var actions      = solved.Actions;
                var time         = solved.CalculateTime();
                var solutionBlob = solved.FormatSolution();

                var path = Path.Combine(FileHelper.PatchDirectoryName("problems"), "puzzles", $"block{block.BlockNumber:000}_sol_{solver.GetName()}_v{solver.GetVersion()}_{time}.sol");
                File.WriteAllText(path, solutionBlob);

                Console.WriteLine($"{solver.GetName()}_v{solver.GetVersion()} score = {time} time = {stopwatch.Elapsed}");

                new SolutionMeta(
                    block.BlockNumber,
                    solutionBlob,
                    time,
                    solver.GetName(),
                    solver.GetVersion(),
                    calculationTime,
                    null,
                    0
                    ).SaveToDb(isBlockSolution: true);

                results.Add(Tuple.Create(solver, actions));
            }

            var(bestSolver, bestActions) = results
                                           .OrderBy(x => x.Item2.CalculateTime())
                                           .First();

            var solutionPath = Path.Combine(FileHelper.PatchDirectoryName("problems"), "puzzles", $"block{block.BlockNumber:000}_best_{bestSolver.GetName()}_v{bestSolver.GetVersion()}_{bestActions.CalculateTime()}.sol");

            File.WriteAllText(solutionPath, bestActions.Format());

            Console.WriteLine($"Best score = {bestActions.CalculateTime()}");

            if (submitOption.HasValue())
            {
                Console.WriteLine("Submitting block ...");
                var submissionResult = await Api.Submit(block.BlockNumber, solutionPath, ourProblemPath);

                if (submissionResult.Errors != null && submissionResult.Errors.Count > 0)
                {
                    submissionResult.Errors.ToList()
                    .ForEach(
                        e => { Console.WriteLine($"Error {e.Key}: {e.Value}"); });
                }
            }

            Console.WriteLine("Done.");
            return(0);
        }