private FactoryState Clone()
        {
            FactoryState newState = new FactoryState();

            newState.cost = cost;
            newState.buildingSources.AddRange(buildingSources);
            newState.beltSources.AddRange(beltSources);
            newState.buildingConsumers.AddRange(buildingConsumers);
            return(newState);
        }
Example #2
0
        public static FactoryState MakeBasicText(int size)
        {
            FactoryState startState = new FactoryState();

            for (int i = 0; i < size; i++)
            {
                startState.buildingSources.Add(new FactoryState.BuildingSource(i * 3, 0, 1));
                startState.buildingSources.Add(new FactoryState.BuildingSource(i * 3, 6, 2));
            }
            startState.buildingConsumers.Add(new FactoryState.BuildingConsumer(size * 3, 3, 1, 2));
            Console.WriteLine(5 * size - 2); // expectedCost
            return(startState);
        }
Example #3
0
        public static int Solve(FactoryState startState)
        {
            HashSet <FactoryState> explored = new HashSet <FactoryState>();
            SortedList <int, List <FactoryState> > priorityQueue = new SortedList <int, List <FactoryState> >();

            priorityQueue.Add(startState.cost + startState.Heuristic(), new List <FactoryState>()
            {
                startState
            });
            while (true)
            {
                var headList = priorityQueue.First().Value;
                var head     = headList.Last();
                headList.RemoveAt(headList.Count - 1);
                if (explored.Contains(head))
                {
                    continue;
                }
                explored.Add(head);
                if (priorityQueue.First().Value.Count == 0)
                {
                    priorityQueue.RemoveAt(0);
                }
                if (head.Heuristic() == 0)
                {
                    int totalCount = priorityQueue.Sum(x => x.Value.Count);
                    return(head.cost);
                }
                foreach (var nextState in head.NextStates())
                {
                    if (explored.Contains(nextState))
                    {
                        continue;
                    }
                    int newCost = nextState.cost + nextState.Heuristic();
                    if (!priorityQueue.ContainsKey(newCost))
                    {
                        priorityQueue.Add(newCost, new List <FactoryState>());
                    }
                    if (newCost > 13)
                    {
                        continue;
                    }
                    priorityQueue[newCost].Add(nextState);
                }
            }
            throw new NotImplementedException();
        }
        public override bool Equals(object obj)
        {
            FactoryState that = obj as FactoryState;

            if (cost != that.cost)
            {
                return(false);
            }
            if (buildingSources.Count != that.buildingSources.Count)
            {
                return(false);
            }
            if (beltSources.Count != that.beltSources.Count)
            {
                return(false);
            }
            if (buildingConsumers.Count != that.buildingConsumers.Count)
            {
                return(false);
            }
            for (int i = 0; i < buildingSources.Count; i++)
            {
                if (buildingSources[i].x != that.buildingSources[i].x)
                {
                    return(false);
                }
                if (buildingSources[i].y != that.buildingSources[i].y)
                {
                    return(false);
                }
                if (buildingSources[i].itemType != that.buildingSources[i].itemType)
                {
                    return(false);
                }
            }
            for (int i = 0; i < beltSources.Count; i++)
            {
                if (beltSources[i].x != that.beltSources[i].x)
                {
                    return(false);
                }
                if (beltSources[i].y != that.beltSources[i].y)
                {
                    return(false);
                }
                if (beltSources[i].itemType1 != that.beltSources[i].itemType1)
                {
                    return(false);
                }
                if (beltSources[i].itemType2 != that.beltSources[i].itemType2)
                {
                    return(false);
                }
                if (beltSources[i].direction != that.beltSources[i].direction)
                {
                    return(false);
                }
            }
            for (int i = 0; i < buildingConsumers.Count; i++)
            {
                if (buildingConsumers[i].x != that.buildingConsumers[i].x)
                {
                    return(false);
                }
                if (buildingConsumers[i].y != that.buildingConsumers[i].y)
                {
                    return(false);
                }
                if (buildingConsumers[i].itemType1 != that.buildingConsumers[i].itemType1)
                {
                    return(false);
                }
                if (buildingConsumers[i].itemType2 != that.buildingConsumers[i].itemType2)
                {
                    return(false);
                }
            }
            return(true);
        }
 internal IEnumerable <FactoryState> NextStates()
 {
     // extract from a building onto a belt
     for (int i = 0; i < buildingSources.Count; i++)
     {
         // 48 ways to export from a building onto a new belt
         for (int j = 0; j < 12; j++)
         {
             int  newx              = buildingSources[i].x + bxOffset[j];
             int  newy              = buildingSources[i].y + byOffset[j];
             int  newx2             = buildingSources[i].x + bxOffset2[j];
             int  newy2             = buildingSources[i].y + byOffset2[j];
             bool beltExistsAlready = beltSources.Any(x => x.x == newx && x.y == newy);
             if (beltExistsAlready)
             {
                 int          theBelt   = beltSources.FindIndex(x => x.x == newx && x.y == newy);
                 FactoryState nextState = this.Clone();
                 nextState.buildingSources.RemoveAt(i);
                 bool isLeft         = bIsLeft[j / 3 * 4 + beltSources[theBelt].direction];
                 int  itemTypeInLane = isLeft ? beltSources[theBelt].itemType1 : beltSources[theBelt].itemType2;
                 if (itemTypeInLane == 0 || itemTypeInLane == buildingSources[i].itemType)
                 {
                     BeltSource moddedBelt = beltSources[theBelt];
                     if (isLeft)
                     {
                         moddedBelt.itemType1 = buildingSources[i].itemType;
                     }
                     else
                     {
                         moddedBelt.itemType2 = buildingSources[i].itemType;
                     }
                     nextState.beltSources[theBelt] = moddedBelt;
                     nextState.cost++;
                     nextState.Finalize();
                     yield return(nextState);
                 }
             }
             else
             {
                 for (int k = 0; k < 4; k++) // direction of new belt
                 {
                     FactoryState nextState = this.Clone();
                     nextState.buildingSources.RemoveAt(i);
                     bool isLeft = bIsLeft[j / 3 * 4 + k];
                     nextState.beltSources.Add(new BeltSource(newx, newy, isLeft ? buildingSources[i].itemType : 0, isLeft ? 0 : buildingSources[i].itemType, k));
                     nextState.cost += 2;
                     nextState.Finalize();
                     yield return(nextState);
                 }
             }
         }
     }
     //if (buildingSources.Count > 0) yield break; // force building export exploration first (can't do this yet)
     // progress a belt
     for (int i = 0; i < beltSources.Count; i++)
     {
         int newx = beltSources[i].x + xOffset[beltSources[i].direction];
         int newy = beltSources[i].y + yOffset[beltSources[i].direction];
         for (int j = 0; j < 4; j++)
         {
             if (new int[] { 1, 0, 3, 2 }[beltSources[i].direction] == j)
             {
                 continue;                                                          // let's not go backwards
             }
             FactoryState nextState    = this.Clone();
             BeltSource   moddedSource = nextState.beltSources[i];
             moddedSource.x         = newx;
             moddedSource.y         = newy;
             moddedSource.direction = j;
             int colx = moddedSource.x + xOffset[moddedSource.direction];
             int coly = moddedSource.y + yOffset[moddedSource.direction];
             if (beltSources.Any(x => x.x == colx && x.y == coly && x.direction == j && x.itemType1 == moddedSource.itemType1 && x.itemType2 == moddedSource.itemType2))
             {
                 // the two belts combine
                 nextState.beltSources.RemoveAt(i);
                 nextState.cost++;
                 nextState.Finalize();
                 yield return(nextState);
             }
             else
             {
                 nextState.beltSources[i] = moddedSource;
                 nextState.cost++;
                 nextState.Finalize();
                 yield return(nextState);
             }
         }
     }
     // TODO: merge 2 belts
     // consume from belt
     // TODO: do occupied for this
     for (int i = 0; i < beltSources.Count; i++)
     {
         var  nextState    = this.Clone();
         var  belt         = beltSources[i];
         var  moddedBelt   = nextState.beltSources[i];
         bool anyConsumer1 = buildingConsumers.Any(x => (x.itemType1 == belt.itemType1 || x.itemType2 == belt.itemType1) && Math.Abs(x.x - belt.x) == 3 && Math.Abs(x.y - belt.y) < 2);
         anyConsumer1 |= buildingConsumers.Any(x => (x.itemType1 == belt.itemType1 || x.itemType2 == belt.itemType1) && Math.Abs(x.y - belt.y) == 3 && Math.Abs(x.x - belt.x) < 2);
         bool anyConsumer2 = buildingConsumers.Any(x => (x.itemType1 == belt.itemType2 || x.itemType2 == belt.itemType2) && Math.Abs(x.x - belt.x) == 3 && Math.Abs(x.y - belt.y) < 2);
         anyConsumer2 |= buildingConsumers.Any(x => (x.itemType1 == belt.itemType2 || x.itemType2 == belt.itemType2) && Math.Abs(x.y - belt.y) == 3 && Math.Abs(x.x - belt.x) < 2);
         if (anyConsumer1)
         {
             moddedBelt.itemType1 = 0;
         }
         if (anyConsumer2)
         {
             moddedBelt.itemType2 = 0;
         }
         nextState.beltSources[i] = moddedBelt;
         if (moddedBelt.itemType1 == 0 && moddedBelt.itemType2 == 0)
         {
             nextState.beltSources.RemoveAt(i);
         }
         nextState.cost++;
         nextState.Finalize();
         yield return(nextState);
     }
     // TODO: consume from building
 }