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(); }
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"); } } }
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()); }
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); }