Advertisement
Guest User

fruits.cs

a guest
Feb 21st, 2025
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.33 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Threading.Tasks;
  5. using System.Linq;
  6.  
  7. namespace Program
  8. {
  9.   public class Fruits
  10.   {
  11.     public enum InventoryFruitType
  12.     {
  13.       Apple,
  14.       Banana,
  15.       Strawberry,
  16.       Other,
  17.     }
  18.  
  19.     const int BasketCapacity = 5;
  20.     const int InventoryCapacity = 28;
  21.  
  22.     const double AppleProbability = 0.38;
  23.     const double BananaProbability = 0.17;
  24.     const double StrawberryProbability = 0.04;
  25.  
  26.     public struct FruitInventoryStatus : IEquatable<FruitInventoryStatus>
  27.     {
  28.       public byte FullBaskets;
  29.       public byte Remainder;
  30.       public bool IsRemainderInBasket;
  31.  
  32.       public int InventorySpace => FullBaskets + (IsRemainderInBasket ? 1 : Remainder);
  33.  
  34.       public int FruitCount => FullBaskets * BasketCapacity + Remainder;
  35.  
  36.       public void AddFruit(byte count = 1)
  37.       {
  38.         Remainder += count;
  39.         if (IsRemainderInBasket && Remainder >= BasketCapacity)
  40.         {
  41.           FullBaskets++;
  42.           Remainder -= BasketCapacity;
  43.           IsRemainderInBasket = false;
  44.         }
  45.       }
  46.  
  47.       public bool UseEmptyBasket()
  48.       {
  49.         if (IsRemainderInBasket || Remainder == 0)
  50.           return false;
  51.         if (Remainder < BasketCapacity)
  52.           IsRemainderInBasket = true;
  53.         else
  54.         {
  55.           Remainder -= BasketCapacity;
  56.           FullBaskets++;
  57.         }
  58.         return true;
  59.       }
  60.  
  61.       public double GetBasketPriority(double fruitProbability)
  62.       {
  63.         if (Remainder >= BasketCapacity)
  64.           return 1;
  65.         if (IsRemainderInBasket || Remainder < 1)
  66.           return 0;
  67.         return Math.Pow(fruitProbability, BasketCapacity - Remainder);
  68.       }
  69.  
  70.       public override bool Equals(object obj) => obj is FruitInventoryStatus other && Equals(other);
  71.  
  72.       public bool Equals(FruitInventoryStatus other) => other.FullBaskets == FullBaskets && other.Remainder == Remainder && other.IsRemainderInBasket == IsRemainderInBasket;
  73.  
  74.       public override int GetHashCode()
  75.       {
  76.         return FullBaskets * InventoryCapacity + Remainder + (IsRemainderInBasket ? InventoryCapacity * InventoryCapacity : 0);
  77.       }
  78.  
  79.       public static bool operator ==(FruitInventoryStatus self, FruitInventoryStatus other) => self.Equals(other);
  80.       public static bool operator !=(FruitInventoryStatus self, FruitInventoryStatus other) => !(self == other);
  81.  
  82.       public override string ToString() => ToString('#');
  83.        
  84.       public string ToString(char fruitText)
  85.       {
  86.         StringBuilder result = new StringBuilder();
  87.         for (int i = 0; i < FullBaskets; i++)
  88.           result.Append(BasketText(BasketCapacity, fruitText));
  89.         if (Remainder > 0)
  90.         {
  91.           if (IsRemainderInBasket)
  92.             result.Append(BasketText(Remainder, fruitText));
  93.           else for (int i = 0; i < Remainder; i++)
  94.               result.AppendFormat(FruitText(fruitText));
  95.         }
  96.         return result.ToString();
  97.       }
  98.     }
  99.  
  100.     public static string BasketText(int count, char fruitText) => $"B{count}{fruitText} ";
  101.  
  102.     public static string FruitText(char fruitText) => $"({fruitText}) ";
  103.  
  104.     public const string EmptyText = "___ ";
  105.  
  106.  
  107.     public struct Inventory : IEquatable<Inventory>
  108.     {
  109.       FruitInventoryStatus AppleStatus;
  110.       FruitInventoryStatus BananaStatus;
  111.       FruitInventoryStatus StrawberryStatus;
  112.       public byte OtherTotal;
  113.       public byte EmptyBaskets;
  114.  
  115.       public int FruitTotalCount => AppleStatus.FruitCount + BananaStatus.FruitCount + StrawberryStatus.FruitCount + OtherTotal;
  116.       public int InventoryTotalUsed => AppleStatus.InventorySpace + BananaStatus.InventorySpace + StrawberryStatus.InventorySpace + OtherTotal + EmptyBaskets;
  117.  
  118.       public int SpareCapacity => InventoryCapacity - InventoryTotalUsed;
  119.  
  120.       public bool AddSingleFruit(InventoryFruitType fruitType)
  121.       {
  122.         if (SpareCapacity < 1)
  123.           return false; // no space for a single fruit (needs call to MakeSpace first)
  124.         switch (fruitType)
  125.         {
  126.           case InventoryFruitType.Apple:
  127.             AppleStatus.AddFruit();
  128.             break;
  129.           case InventoryFruitType.Banana:
  130.             BananaStatus.AddFruit();
  131.             break;
  132.           case InventoryFruitType.Strawberry:
  133.             StrawberryStatus.AddFruit();
  134.             break;
  135.           case InventoryFruitType.Other:
  136.             OtherTotal++;
  137.             return true;
  138.           default:
  139.             throw new ArgumentOutOfRangeException();
  140.         }
  141.         return true;
  142.       }
  143.  
  144.       public bool MakeSpace()
  145.       {
  146.         if (SpareCapacity >= 1)
  147.           return true; // already has space - let fruit accumulate
  148.  
  149.         if (EmptyBaskets < 1)
  150.           return false; // cannot make space as no empty baskets
  151.  
  152.         double priorityForApple = AppleStatus.GetBasketPriority(AppleProbability);
  153.         double priorityForBanana = BananaStatus.GetBasketPriority(BananaProbability);
  154.         double priorityForStrawberry = StrawberryStatus.GetBasketPriority(StrawberryProbability);
  155.  
  156.         if (priorityForApple >= Math.Max(priorityForBanana, priorityForStrawberry) && priorityForApple > 0)
  157.         {
  158.           AppleStatus.UseEmptyBasket();
  159.           EmptyBaskets--;
  160.           return true;
  161.         }
  162.         else if (priorityForBanana >= priorityForStrawberry && priorityForBanana > 0)
  163.         {
  164.           BananaStatus.UseEmptyBasket();
  165.           EmptyBaskets--;
  166.           return true;
  167.         }
  168.         else if (priorityForStrawberry > 0)
  169.         {
  170.           StrawberryStatus.UseEmptyBasket();
  171.           EmptyBaskets--;
  172.           return true;
  173.         }
  174.         else // none of the remaining fruits can be put in a basket
  175.           return false;
  176.       }
  177.  
  178.       public override bool Equals(object obj) => obj is Inventory other && Equals(other);
  179.  
  180.       public bool Equals(Inventory other) => other.AppleStatus == AppleStatus && other.BananaStatus == BananaStatus && other.StrawberryStatus == StrawberryStatus && other.OtherTotal == OtherTotal && other.EmptyBaskets == EmptyBaskets;
  181.  
  182.       public override int GetHashCode()
  183.       {
  184.         const int factor = InventoryCapacity * InventoryCapacity + 1;
  185.         return (((AppleStatus.GetHashCode() * factor) + BananaStatus.GetHashCode()) * factor + StrawberryStatus.GetHashCode()) * factor + OtherTotal * InventoryCapacity + EmptyBaskets;
  186.       }
  187.  
  188.       public static bool operator ==(Inventory self, Inventory other) => self.Equals(other);
  189.       public static bool operator !=(Inventory self, Inventory other) => !(self == other);
  190.  
  191.       public override string ToString()
  192.       {
  193.         StringBuilder result = new StringBuilder();
  194.         for (int i = 0; i < EmptyBaskets; i++)
  195.           result.Append(BasketText(0, '_'));
  196.         result.Append(AppleStatus.ToString('A'));
  197.         result.Append(BananaStatus.ToString('B'));
  198.         result.Append(StrawberryStatus.ToString('S'));
  199.         for (int i = 0; i < OtherTotal; i++)
  200.           result.Append(FruitText('?'));
  201.         for (int i = SpareCapacity; i-- > 0;)
  202.           result.Append(EmptyText);
  203.  
  204.         return result.ToString();
  205.       }
  206.     }
  207.  
  208.  
  209.     static Random rand = new Random();
  210.  
  211.     static InventoryFruitType GetRandomFruit()
  212.     {
  213.       double value = rand.NextDouble();
  214.       if (value < AppleProbability)
  215.         return InventoryFruitType.Apple;
  216.       value -= AppleProbability;
  217.       if (value < BananaProbability)
  218.         return InventoryFruitType.Banana;
  219.       value -= BananaProbability;
  220.       if (value < StrawberryProbability)
  221.         return InventoryFruitType.Strawberry;
  222.       value -= StrawberryProbability;
  223.       return InventoryFruitType.Other;
  224.     }
  225.  
  226.     public static int Main()
  227.     {
  228.       for(byte basketCount = 0; basketCount < 28; basketCount++)
  229.       {
  230.         var resultFrequency = new int[100];
  231.         for(int trial = 0; trial < 1000000;trial++)
  232.         {
  233.           Inventory inv = new Inventory { EmptyBaskets = basketCount };
  234.  
  235.           int addedCount = 0;
  236.  
  237.           do
  238.           {
  239.             var fruit = GetRandomFruit();
  240.             inv.AddSingleFruit(fruit);
  241.             addedCount++;
  242.           } while (inv.MakeSpace());
  243.  
  244.           resultFrequency[inv.FruitTotalCount]++;
  245.         }
  246.         Console.WriteLine($"{basketCount}: {string.Join(" ", resultFrequency)}");
  247.       }
  248.       return 0;
  249.     }
  250.   }
  251. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement