public IEnumerable <ICommand> Solve()
        {
            // ! красить можно то, что не покрашено, и после покраски станет граундед
            // строим список того, что можно красить, сортированный по расстоянию до бота (candidates)
            // while !empty (candidates)
            //   для каждой:
            //      перебираем near-позиции с которых красить, сортировано по расстоянию до бота
            //         выбираем ту, с которой оракул разрешает красить
            //   перемещаемся в ту точку, красим, обновляем список (добавляем ноды и сортируем заново)
            // в конце возвращаемся в 0 и HALT
            Commands.Clear();
            HashSet <Vec> candidates = BuildCandidates();

            while (candidates.Any())
            {
                candidatesCount.Add(candidates.Count);
                var candidatesAndPositions = OrderCandidates(candidates);
                var any = false;
                foreach (var(candidate, nearPosition) in candidatesAndPositions)
                {
                    if (Move(nearPosition))
                    {
                        any = true;
                        Fill(candidate);
                        candidates.Remove(candidate);
                        foreach (var n in neighbors)
                        {
                            var neighbor = candidate + n;
                            if (neighbor.IsInCuboid(R) &&
                                whatToFill.Get(neighbor) &&
                                !state.Get(neighbor))
                            {
                                candidates.Add(neighbor);
                            }
                        }
                        break;
                    }
                }
                foreach (var command in Commands)
                {
                    yield return(command);
                }
                Commands.Clear();
                if (!any)
                {
                    throw new Exception("Can't move");
                }
            }
            Move(Vec.Zero);
            Commands.Add(new Halt());
            foreach (var command in Commands)
            {
                yield return(command);
            }
            Commands.Clear();
        }
Example #2
0
        private IEnumerable <ICommand> SolveSingle(int bot)
        {
            var candidates = BuildCandidates(bot);

            while (candidates.Any())
            {
                var commands = new List <ICommand>();
                var candidatesAndPositions = OrderCandidates(bot, candidates);
                var any = false;
                foreach (var(candidate, nearPosition) in candidatesAndPositions)
                {
                    if (Move(bot, nearPosition, commands))
                    {
                        any = true;
                        Fill(bot, candidate, commands);
                        candidates.Remove(candidate);
                        foreach (var n in neighbors)
                        {
                            var neighbor = candidate + n;
                            if (neighbor.IsInCuboid(R) &&
                                neighbor.IsInRegion(regions[bot]) &&
                                whatToFill.Get(neighbor) &&
                                !state.Get(neighbor))
                            {
                                candidates.Add(neighbor);
                            }
                        }
                        break;
                    }
                }
                foreach (var command in commands)
                {
                    yield return(command);
                }
                if (!any)
                {
                    throw new Exception("Can't move");
                }
            }
        }
Example #3
0
        public IEnumerable <ICommand> Solve()
        {
            for (int i = 0; i < N - 1; i++)
            {
                for (int k = 0; k < i; k++)
                {
                    yield return(new Wait());
                }
                yield return(new Fission(new NearDifference(new Vec(0, 0, 1)), N - i - 2));
            }
            pos     = new Vec[N];
            regions = new Region[N];
            for (int i = 0; i < N; i++)
            {
                pos[i]     = new Vec(0, 0, i);
                regions[i] = Region.ForShift(new Vec(i % Nx * BlockSizeX, 0, i / Nx * BlockSizeZ), new Vec(BlockSizeX - 1, R - 1, BlockSizeZ - 1));
            }

            for (int i = N - 1; i >= 0; i--)
            {
                var volatiles = pos.ToHashSet();
                var target    = regions[i].Start;
                var commands  = new PathFinder(state, pos[i], target, volatiles, null).TryFindPath();
                if (commands == null)
                {
                    throw new InvalidOperationException($"Failed to find path from {pos[i]} to {target}");
                }
                foreach (var command in commands)
                {
                    for (int k = 0; k < i; k++)
                    {
                        yield return(new Wait());
                    }
                    yield return(command);

                    for (int k = i + 1; k < N; k++)
                    {
                        yield return(new Wait());
                    }
                }
                pos[i] = target;
            }

            var enumerators = new IEnumerator <ICommand> [N];

            while (true)
            {
                for (int bot = 0; bot < N; bot++)
                {
                    if (enumerators[bot] == null)
                    {
                        enumerators[bot] = SolveSingle(bot).GetEnumerator();
                    }
                }

                var tickCommands = new ICommand[N];
                for (int bot = 0; bot < N; bot++)
                {
                    if (enumerators[bot].MoveNext())
                    {
                        tickCommands[bot] = enumerators[bot].Current;
                    }
                    else
                    {
                        enumerators[bot].Dispose();
                        enumerators[bot] = null;
                    }
                }

                if (tickCommands.All(c => c == null))
                {
                    break;
                }

                foreach (var tickCommand in tickCommands)
                {
                    yield return(tickCommand ?? new Wait());
                }
            }

            for (int bot = N - 1; bot >= 1; bot--)
            {
                var             parentPos = pos[bot - 1];
                List <ICommand> commands  = null;
                foreach (var near in parentPos.GetNears().OrderBy(n => n.MDistTo(pos[bot])))
                {
                    if (near.IsInCuboid(R) && !state.Get(near))
                    {
                        var pathFinder = new PathFinder(state, pos[bot], near, null, null);
                        commands = pathFinder.TryFindPath();
                        if (commands != null)
                        {
                            pos[bot] = near;
                            break;
                        }
                    }
                }
                if (commands == null)
                {
                    throw new InvalidOperationException($"Couldn't find path for fusion from {pos[bot]} to near of {parentPos}");
                }
                foreach (var command in commands)
                {
                    for (int k = 0; k < bot; k++)
                    {
                        yield return(new Wait());
                    }
                    yield return(command);
                }
                for (int k = 0; k < bot - 1; k++)
                {
                    yield return(new Wait());
                }
                yield return(new FusionP(new NearDifference(pos[bot] - parentPos)));

                yield return(new FusionS(new NearDifference(parentPos - pos[bot])));
            }

            var cmds = new List <ICommand>();

            Move(0, Vec.Zero, cmds);
            foreach (var command in cmds)
            {
                yield return(command);
            }
            yield return(new Halt());
        }
Example #4
0
        public List <ICommand> TryFindPath()
        {
            var used = new Dictionary <Vec, (Vec prev, ICommand command)>();

            if (source == target)
            {
                return(new List <ICommand>());
            }

            if (!isAllowedPosition(target) || state.Get(target))
            {
                return(null);
            }

            var queue = new SortedSet <Vec>(Comparer <Vec> .Create((a, b) =>
            {
                var compareTo = a.MDistTo(target).CompareTo(b.MDistTo(target));
                if (compareTo != 0)
                {
                    return(compareTo);
                }
                return(Comparer <int> .Default.Compare(a.GetHashCode(), b.GetHashCode()));
            }));

            queue.Add(source);
            used.Add(source, (null, null));
            while (queue.Any())
            {
                var current = queue.First();
                if (current == target)
                {
                    var result = new List <ICommand>();
                    for (var v = target; v != null; v = used[v].prev)
                    {
                        if (used[v].command != null)
                        {
                            result.Add(used[v].command);
                        }
                    }
                    result.Reverse();
                    return(result);
                }
                queue.Remove(current);
                foreach (var(command, next) in IteratePossibleCommands(current))
                {
                    if (!used.ContainsKey(next))
                    {
                        used.Add(next, (current, command));
                        queue.Add(next);
                    }
                }
            }
            //var s = "";
            //for (int y = 0; y < R; y++)
            //{
            //    for (int z = 0; z < R; z++)
            //    {
            //        for (int x = R - 1; x >= 0; x--)
            //            s += used.ContainsKey(new Vec(x, y, z)) ? "X" : ".";
            //        s += "\r\n";
            //    }
            //    s += "===r\n";
            //}
            //File.WriteAllText(@"c:\2.txt", s);
            return(null);
        }