Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Threading.Tasks;
- using System.Linq;
- namespace Program
- {
- public class Fruits
- {
- public enum InventoryFruitType
- {
- Apple,
- Banana,
- Strawberry,
- Other,
- }
- const int BasketCapacity = 5;
- const int InventoryCapacity = 28;
- const double AppleProbability = 0.38;
- const double BananaProbability = 0.17;
- const double StrawberryProbability = 0.04;
- public struct FruitInventoryStatus : IEquatable<FruitInventoryStatus>
- {
- public byte FullBaskets;
- public byte Remainder;
- public bool IsRemainderInBasket;
- public int InventorySpace => FullBaskets + (IsRemainderInBasket ? 1 : Remainder);
- public int FruitCount => FullBaskets * BasketCapacity + Remainder;
- public void AddFruit(byte count = 1)
- {
- Remainder += count;
- if (IsRemainderInBasket && Remainder >= BasketCapacity)
- {
- FullBaskets++;
- Remainder -= BasketCapacity;
- IsRemainderInBasket = false;
- }
- }
- public bool UseEmptyBasket()
- {
- if (IsRemainderInBasket || Remainder == 0)
- return false;
- if (Remainder < BasketCapacity)
- IsRemainderInBasket = true;
- else
- {
- Remainder -= BasketCapacity;
- FullBaskets++;
- }
- return true;
- }
- public double GetBasketPriority(double fruitProbability)
- {
- if (Remainder >= BasketCapacity)
- return 1;
- if (IsRemainderInBasket || Remainder < 1)
- return 0;
- return Math.Pow(fruitProbability, BasketCapacity - Remainder);
- }
- public override bool Equals(object obj) => obj is FruitInventoryStatus other && Equals(other);
- public bool Equals(FruitInventoryStatus other) => other.FullBaskets == FullBaskets && other.Remainder == Remainder && other.IsRemainderInBasket == IsRemainderInBasket;
- public override int GetHashCode()
- {
- return FullBaskets * InventoryCapacity + Remainder + (IsRemainderInBasket ? InventoryCapacity * InventoryCapacity : 0);
- }
- public static bool operator ==(FruitInventoryStatus self, FruitInventoryStatus other) => self.Equals(other);
- public static bool operator !=(FruitInventoryStatus self, FruitInventoryStatus other) => !(self == other);
- public override string ToString() => ToString('#');
- public string ToString(char fruitText)
- {
- StringBuilder result = new StringBuilder();
- for (int i = 0; i < FullBaskets; i++)
- result.Append(BasketText(BasketCapacity, fruitText));
- if (Remainder > 0)
- {
- if (IsRemainderInBasket)
- result.Append(BasketText(Remainder, fruitText));
- else for (int i = 0; i < Remainder; i++)
- result.AppendFormat(FruitText(fruitText));
- }
- return result.ToString();
- }
- }
- public static string BasketText(int count, char fruitText) => $"B{count}{fruitText} ";
- public static string FruitText(char fruitText) => $"({fruitText}) ";
- public const string EmptyText = "___ ";
- public struct Inventory : IEquatable<Inventory>
- {
- FruitInventoryStatus AppleStatus;
- FruitInventoryStatus BananaStatus;
- FruitInventoryStatus StrawberryStatus;
- public byte OtherTotal;
- public byte EmptyBaskets;
- public int FruitTotalCount => AppleStatus.FruitCount + BananaStatus.FruitCount + StrawberryStatus.FruitCount + OtherTotal;
- public int InventoryTotalUsed => AppleStatus.InventorySpace + BananaStatus.InventorySpace + StrawberryStatus.InventorySpace + OtherTotal + EmptyBaskets;
- public int SpareCapacity => InventoryCapacity - InventoryTotalUsed;
- public bool AddSingleFruit(InventoryFruitType fruitType)
- {
- if (SpareCapacity < 1)
- return false; // no space for a single fruit (needs call to MakeSpace first)
- switch (fruitType)
- {
- case InventoryFruitType.Apple:
- AppleStatus.AddFruit();
- break;
- case InventoryFruitType.Banana:
- BananaStatus.AddFruit();
- break;
- case InventoryFruitType.Strawberry:
- StrawberryStatus.AddFruit();
- break;
- case InventoryFruitType.Other:
- OtherTotal++;
- return true;
- default:
- throw new ArgumentOutOfRangeException();
- }
- return true;
- }
- public bool MakeSpace()
- {
- if (SpareCapacity >= 1)
- return true; // already has space - let fruit accumulate
- if (EmptyBaskets < 1)
- return false; // cannot make space as no empty baskets
- double priorityForApple = AppleStatus.GetBasketPriority(AppleProbability);
- double priorityForBanana = BananaStatus.GetBasketPriority(BananaProbability);
- double priorityForStrawberry = StrawberryStatus.GetBasketPriority(StrawberryProbability);
- if (priorityForApple >= Math.Max(priorityForBanana, priorityForStrawberry) && priorityForApple > 0)
- {
- AppleStatus.UseEmptyBasket();
- EmptyBaskets--;
- return true;
- }
- else if (priorityForBanana >= priorityForStrawberry && priorityForBanana > 0)
- {
- BananaStatus.UseEmptyBasket();
- EmptyBaskets--;
- return true;
- }
- else if (priorityForStrawberry > 0)
- {
- StrawberryStatus.UseEmptyBasket();
- EmptyBaskets--;
- return true;
- }
- else // none of the remaining fruits can be put in a basket
- return false;
- }
- public override bool Equals(object obj) => obj is Inventory other && Equals(other);
- public bool Equals(Inventory other) => other.AppleStatus == AppleStatus && other.BananaStatus == BananaStatus && other.StrawberryStatus == StrawberryStatus && other.OtherTotal == OtherTotal && other.EmptyBaskets == EmptyBaskets;
- public override int GetHashCode()
- {
- const int factor = InventoryCapacity * InventoryCapacity + 1;
- return (((AppleStatus.GetHashCode() * factor) + BananaStatus.GetHashCode()) * factor + StrawberryStatus.GetHashCode()) * factor + OtherTotal * InventoryCapacity + EmptyBaskets;
- }
- public static bool operator ==(Inventory self, Inventory other) => self.Equals(other);
- public static bool operator !=(Inventory self, Inventory other) => !(self == other);
- public override string ToString()
- {
- StringBuilder result = new StringBuilder();
- for (int i = 0; i < EmptyBaskets; i++)
- result.Append(BasketText(0, '_'));
- result.Append(AppleStatus.ToString('A'));
- result.Append(BananaStatus.ToString('B'));
- result.Append(StrawberryStatus.ToString('S'));
- for (int i = 0; i < OtherTotal; i++)
- result.Append(FruitText('?'));
- for (int i = SpareCapacity; i-- > 0;)
- result.Append(EmptyText);
- return result.ToString();
- }
- }
- static Random rand = new Random();
- static InventoryFruitType GetRandomFruit()
- {
- double value = rand.NextDouble();
- if (value < AppleProbability)
- return InventoryFruitType.Apple;
- value -= AppleProbability;
- if (value < BananaProbability)
- return InventoryFruitType.Banana;
- value -= BananaProbability;
- if (value < StrawberryProbability)
- return InventoryFruitType.Strawberry;
- value -= StrawberryProbability;
- return InventoryFruitType.Other;
- }
- public static int Main()
- {
- for(byte basketCount = 0; basketCount < 28; basketCount++)
- {
- var resultFrequency = new int[100];
- for(int trial = 0; trial < 1000000;trial++)
- {
- Inventory inv = new Inventory { EmptyBaskets = basketCount };
- int addedCount = 0;
- do
- {
- var fruit = GetRandomFruit();
- inv.AddSingleFruit(fruit);
- addedCount++;
- } while (inv.MakeSpace());
- resultFrequency[inv.FruitTotalCount]++;
- }
- Console.WriteLine($"{basketCount}: {string.Join(" ", resultFrequency)}");
- }
- return 0;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement