/// <summary> /// Main calculation part of the GetMinRequiredPacks method. /// Do not call directly. /// Tries all combinations of 1 pack, then 2, 3, etc. /// </summary> /// <param name="tryPacksList"> /// Separate copy of packsWithCode /// </param> /// <param name="packsWithCode"> /// Packs available of the required product code /// </param> /// <param name="requiredQty">Quantity required</param> static Packs GetMinRequiredPacksCalc(List <Packs> tryPacksList, List <Pack> packsWithCode, int requiredQty) { while (tryPacksList.Count > 0) { List <Packs> toRemove = new List <Packs>(); // Try all packs in current list foreach (Packs tryPacks in tryPacksList) { if (tryPacks.TotalSize == requiredQty) { return(tryPacks); } else if (tryPacks.TotalSize > requiredQty) { toRemove.Add(tryPacks); } } // Remove impossible pack combinations from list foreach (Packs tryPacks in toRemove) { tryPacksList.Remove(tryPacks); } if (tryPacksList.Count < 1) { break; } // Add each type of pack to each pack list to be tried List <Packs> newTryPacksList = new List <Packs>(); foreach (Pack pack in packsWithCode) { foreach (Packs tryPacks in tryPacksList) { Packs newTryPacks = new Packs(); newTryPacks.TotalSize = tryPacks.TotalSize + pack.Size; List <Pack> newPackList = new List <Pack>(); foreach (Pack oldPack in tryPacks.PackList) { newPackList.Add(oldPack); } newPackList.Add(pack); newTryPacks.PackList = newPackList; newTryPacksList.Add(newTryPacks); } } tryPacksList = newTryPacksList; } return(null); }
/// <summary> /// Returns the total cost of the pack list. /// </summary> static decimal GetTotalCost(Packs requiredPacks) { decimal totalCost = 0; foreach (Pack pack in requiredPacks.PackList) { totalCost += pack.Cost; } return(totalCost); }
/// <summary> /// Gets a breakdown of one line of the order. /// Includes the total cost and amounts of each pack type. /// </summary> public static string GetCostAndPackBreakdown(Packs requiredPacks, string productCode) { decimal totalCost = GetTotalCost(requiredPacks); StringBuilder output = new StringBuilder(); output.Append(requiredPacks.TotalSize + " "); output.Append(productCode + " $" + totalCost); // Sort size descending requiredPacks.PackList.Sort( (x, y) => - 1 * x.Size.CompareTo(y.Size)); // Generate line of pack type and quantity int prevSize = 0; int packQty = 0; decimal prevCost = 0; foreach (Pack pack in requiredPacks.PackList) { if (prevSize != pack.Size && prevSize != 0) { output.Append(Environment.NewLine + " "); output.Append(packQty + " x "); output.Append(prevSize + " $" + prevCost); packQty = 1; // Current pack is different size } else { packQty += 1; } prevSize = pack.Size; prevCost = pack.Cost; } output.Append(Environment.NewLine + " "); output.Append(packQty + " x "); output.Append(prevSize + " $" + prevCost); return(output.ToString()); }
static int RunOutputTest(string expectedOutput, Packs requiredPacks, string productCode, string testName) { string output = Program.GetCostAndPackBreakdown(requiredPacks, productCode); if (output.Equals(expectedOutput)) { Console.WriteLine(testName + ": Test Success"); return(1); } else { Console.WriteLine(testName + ": Test Fail"); Console.WriteLine("Expected:"); Console.WriteLine(expectedOutput); Console.WriteLine("Actual:"); Console.WriteLine(output); return(0); } }
static int RunPackTest(int qty, List <Pack> packList, string testName, List <int> expectedSizes) { try { Packs requiredPacks = Program.GetMinRequiredPacks(qty, packList); if (expectedSizes == null) { if (requiredPacks != null) { throw new Exception("Result is not null."); } } else { foreach (Pack pack in requiredPacks.PackList) { if (!expectedSizes.Remove(pack.Size)) { throw new Exception("Unexpected size returned."); } } if (expectedSizes.Count > 0) { throw new Exception("Incorrect number of packs."); } } Console.WriteLine(testName + ": Test Success"); return(1); } catch (Exception e) { Console.WriteLine(testName + ": Test Fail - " + e.Message); return(0); } }
/// <summary> /// Gets the minimum number of packs required /// for the specified quantity. /// </summary> /// <param name="requiredQty">Quantity required</param> /// <param name="packsWithCode"> /// Packs available of the required product code /// </param> public static Packs GetMinRequiredPacks(int requiredQty, List <Pack> packsWithCode) { List <Packs> tryPacksList = new List <Packs>(); Packs tryPacks = new Packs(); foreach (Pack pack in packsWithCode) { tryPacks.TotalSize = pack.Size; List <Pack> newPackList = new List <Pack>(); newPackList.Add(pack); tryPacks.PackList = newPackList; tryPacksList.Add(tryPacks); tryPacks = new Packs(); } tryPacks = GetMinRequiredPacksCalc(tryPacksList, packsWithCode, requiredQty); return(tryPacks); }
/// <summary> /// Inputs the packs data file path and order. /// Outputs the cost and pack breakdown. /// </summary> static void Main(string[] args) { try { if (args[0] == "test") { Test.RunAllTests(); PressEnterToExit(""); } } catch { // No command line arguments } // Read the packs data file Dictionary <string, List <Pack> > packCodeDict = new Dictionary <string, List <Pack> >(); try { packCodeDict = GetPackData(); } catch (Exception e) { PressEnterToExit("Error reading packs file: " + e.Message); } Console.WriteLine("Enter a blank line to finish the order."); Console.WriteLine("Order:"); string output = ""; // Read the order and output the breakdown while (1 == 1) { string input = Console.ReadLine(); // Blank line to finish the order if (input == "") { FinishOrder(output); output = ""; continue; } string message = ValidateOrderInput(input, packCodeDict); if (message != "") { FinishOrder("Error: " + message); output = ""; continue; } string[] inputParts = input.Split(' '); int qty = Int32.Parse(inputParts[0]); string code = inputParts[1]; if (qty > MAX_QTY) { FinishOrder("Error: Quantity cannot be above " + MAX_QTY); output = ""; continue; } Packs requiredPacks = GetMinRequiredPacks(qty, packCodeDict[code]); if (requiredPacks == null) { FinishOrder("Error: Quantity ordered cannot " + "be packed completely."); output = ""; continue; } else { output += GetCostAndPackBreakdown(requiredPacks, code); output += Environment.NewLine; } } }
public static void RunAllTests() { int numSuccess = 0; int numTests = 0; List <Pack> packListSH3 = new List <Pack>(); packListSH3.Add(new Pack("Sliced Ham", "SH3", "3", "2.99")); packListSH3.Add(new Pack("Sliced Ham", "SH3", "5", "4.49")); List <Pack> packListYT2 = new List <Pack>(); packListYT2.Add(new Pack("Yoghurt", "YT2", "4", "4.95")); packListYT2.Add(new Pack("Yoghurt", "YT2", "10", "9.95")); packListYT2.Add(new Pack("Yoghurt", "YT2", "15", "13.95")); List <Pack> packListTR = new List <Pack>(); packListTR.Add(new Pack("Toilet Rolls", "TR", "3", "2.95")); packListTR.Add(new Pack("Toilet Rolls", "TR", "5", "4.45")); packListTR.Add(new Pack("Toilet Rolls", "TR", "9", "7.99")); // Pack tests Console.WriteLine("Test pack breakdown..."); numSuccess += RunPackTest(30, packListYT2, "30 YT2 (2 packs)", new List <int> { 15, 15 }); numTests += 1; numSuccess += RunPackTest(28, packListYT2, "28 YT2 (4 packs)", new List <int> { 10, 10, 4, 4 }); numTests += 1; numSuccess += RunPackTest(17, packListYT2, "17 YT2 (0 packs)", null); numTests += 1; numSuccess += RunPackTest(86, packListYT2, "86 YT2 (9 packs)", new List <int> { 15, 15, 15, 15, 10, 4, 4, 4, 4 }); numTests += 1; // Output tests Console.WriteLine(); Console.WriteLine("Test final output..."); string expectedOutput = "10 SH3 $8.98" + Environment.NewLine; expectedOutput += " 2 x 5 $4.49"; Packs requiredPacks = Program.GetMinRequiredPacks(10, packListSH3); numSuccess += RunOutputTest(expectedOutput, requiredPacks, "SH3", "10 SH3"); numTests += 1; expectedOutput = "28 YT2 $29.80" + Environment.NewLine; expectedOutput += " 2 x 10 $9.95" + Environment.NewLine; expectedOutput += " 2 x 4 $4.95"; requiredPacks = Program.GetMinRequiredPacks(28, packListYT2); numSuccess += RunOutputTest(expectedOutput, requiredPacks, "YT2", "28 YT2"); numTests += 1; expectedOutput = "12 TR $10.94" + Environment.NewLine; expectedOutput += " 1 x 9 $7.99" + Environment.NewLine; expectedOutput += " 1 x 3 $2.95"; requiredPacks = Program.GetMinRequiredPacks(12, packListTR); numSuccess += RunOutputTest(expectedOutput, requiredPacks, "TR", "12 TR "); numTests += 1; Console.WriteLine(); Console.WriteLine(numSuccess + "/" + numTests + " successful"); }