Fixed recyclers not built next to each other

This commit is contained in:
Michael Chen 2022-12-21 01:19:53 +01:00
parent 9bd9a063f8
commit 80781f7eef
Signed by: cnml
GPG Key ID: 5845BF3F82D5F629

View File

@ -20,7 +20,9 @@ namespace Codingame {
state.MyMatter = int.Parse(inputs[0]); state.MyMatter = int.Parse(inputs[0]);
state.OppMatter = int.Parse(inputs[1]); state.OppMatter = int.Parse(inputs[1]);
for (var i = 0; i < height; i++) for (var j = 0; j < width; j++) { for (var i = 0; i < height; i++) for (var j = 0; j < width; j++) {
ref var field = ref state.Fields[j, i]; Coordinate2D coord = new(j, i);
ref var field = ref state[coord];
field.Coordinates = coord;
inputs = ReadInput().Split(' '); inputs = ReadInput().Split(' ');
field.ScrapAmount = int.Parse(inputs[0]); field.ScrapAmount = int.Parse(inputs[0]);
field.Owner = (Owner)int.Parse(inputs[1]); field.Owner = (Owner)int.Parse(inputs[1]);
@ -42,10 +44,12 @@ namespace Codingame {
public static IEnumerable<Command> GetCommands(GameState state) { public static IEnumerable<Command> GetCommands(GameState state) {
var units = state.FindUnits(); var units = state.FindUnits();
var enemies = state.FindUnits(Owner.Enemy);
var neutral = state.FindFields(Owner.Neutral); var neutral = state.FindFields(Owner.Neutral);
var recyclers = state.FindFields(i => i.Recycler).Keys.ToList(); var recyclers = state.FindFields(i => i.Recycler).Keys.ToList();
var possibleBuilds = state.PossibleRecyclerSpots(recyclers).OrderByDescending(i => i.Value).Take(1).ToList(); var possibleBuilds = state.PossibleRecyclerSpots(recyclers).OrderByDescending(i => i.Value).Take(1).ToList();
while (possibleBuilds.Count > 0) { while (possibleBuilds.Count > 0) {
Console.Error.WriteLine(string.Join("\n", state.PossibleRecyclerSpots(recyclers).OrderByDescending(i => i.Value).Select(i => $"Recycler at {i.Key} yields {i.Value} resources!")));
var possibleBuild = possibleBuilds.First(); var possibleBuild = possibleBuilds.First();
if (state.MyMatter < GameState.RecyclerCost) break; if (state.MyMatter < GameState.RecyclerCost) break;
state.MyMatter -= GameState.RecyclerCost; state.MyMatter -= GameState.RecyclerCost;
@ -54,13 +58,15 @@ namespace Codingame {
recyclers.Add(possibleBuild.Key); recyclers.Add(possibleBuild.Key);
possibleBuilds = state.PossibleRecyclerSpots(recyclers).OrderByDescending(i => i.Value).Take(1).ToList(); possibleBuilds = state.PossibleRecyclerSpots(recyclers).OrderByDescending(i => i.Value).Take(1).ToList();
} }
while (state.MyMatter >= GameState.RobotCost) {
var maxRobots = state.MyMatter / GameState.RobotCost;
var cost = maxRobots * GameState.RobotCost;
yield return new Spawn(maxRobots, units.First().Key);
state.MyMatter -= cost;
}
foreach (var (position, amount) in units) { foreach (var (position, amount) in units) {
for (int i = 0; i < amount; i++) { var (enemyPosition, enemyAmount) = enemies.MinBy(i => (i.Key - position).ManhattanDistance);
if (neutral.Count == 0) yield break; yield return new Move(amount, position, enemyPosition);
var emptySpot = neutral.Keys.First();
if (!neutral.Remove(emptySpot, out var field)) throw new InvalidProgramException();
yield return new Move(1, position, emptySpot);
}
} }
} }
} }
@ -108,6 +114,7 @@ namespace Codingame {
} }
public record struct GameState(int Width, int Height, FieldState[,] Fields, int MyMatter = 0, int OppMatter = 0) { public record struct GameState(int Width, int Height, FieldState[,] Fields, int MyMatter = 0, int OppMatter = 0) {
public const int RecyclerCost = 10; public const int RecyclerCost = 10;
public const int RobotCost = 10;
public FieldState FieldAt(Coordinate2D coord) => this[coord]; public FieldState FieldAt(Coordinate2D coord) => this[coord];
public ref FieldState this[Coordinate2D coord] => ref Fields[coord.X, coord.Y]; public ref FieldState this[Coordinate2D coord] => ref Fields[coord.X, coord.Y];
public Dictionary<Coordinate2D, int> PossibleRecyclerSpots(IReadOnlyCollection<Coordinate2D> recyclers) { public Dictionary<Coordinate2D, int> PossibleRecyclerSpots(IReadOnlyCollection<Coordinate2D> recyclers) {
@ -116,21 +123,19 @@ namespace Codingame {
for (int x = 0; x < Width; x++) { for (int x = 0; x < Width; x++) {
Coordinate2D coord = new(x, y); Coordinate2D coord = new(x, y);
var field = this[coord]; var field = this[coord];
if (!field.CanBuild) continue; if (!field.CanBuild || field.InRangeOfRecycler) continue;
var potentialMaterial = coord.Neighbors().Append(coord) var potentialMaterial = coord.Neighbors().Append(coord)
.Where(WithinBounds) .Where(WithinBounds)
.Where(i => !NearRecycler(recyclers, i))
.Select(FieldAt) .Select(FieldAt)
.Where(i => !i.InRangeOfRecycler && !NearRecycler(recyclers, i.Coordinates))
.Sum(i => i.ScrapAmount); .Sum(i => i.ScrapAmount);
if (potentialMaterial != 0) if (potentialMaterial != 0)
found[coord] = potentialMaterial; found[coord] = potentialMaterial;
} }
return found; return found;
} }
public static bool NearRecycler(IReadOnlyCollection<Coordinate2D> recyclers, Coordinate2D coord) public static bool NearRecycler(IReadOnlyCollection<Coordinate2D> recyclers, Coordinate2D coord)
=> recyclers.Any(i => (i - coord).ManhattanDistance < 2); => recyclers.Any(i => (i - coord).ManhattanDistance <= 1);
public Dictionary<Coordinate2D, int> FindWhere(Func<FieldState, int> find) { public Dictionary<Coordinate2D, int> FindWhere(Func<FieldState, int> find) {
Dictionary<Coordinate2D, int> found = new(); Dictionary<Coordinate2D, int> found = new();
for (int y = 0; y < Height; y++) for (int y = 0; y < Height; y++)
@ -170,5 +175,5 @@ namespace Codingame {
public static Coordinate2D operator +(Coordinate2D left, Coordinate2D right) => new(left.X + right.X, left.Y + right.Y); public static Coordinate2D operator +(Coordinate2D left, Coordinate2D right) => new(left.X + right.X, left.Y + right.Y);
public int ManhattanDistance => Math.Abs(X) + Math.Abs(Y); public int ManhattanDistance => Math.Abs(X) + Math.Abs(Y);
} }
public record struct FieldState(int ScrapAmount, Owner Owner, int Units, bool Recycler, bool CanBuild, bool CanSpawn, bool InRangeOfRecycler); public record struct FieldState(int ScrapAmount, Owner Owner, int Units, bool Recycler, bool CanBuild, bool CanSpawn, bool InRangeOfRecycler, Coordinate2D Coordinates);
} }