private void GetMinPrice(TrolleyCalculatorInput input, decimal maxPrice, List <Special> specials, Dictionary <string, long> shoppedProducts, ref decimal minPrice, int i, ref bool minPriceUpdated, int j) { var specialCounts = new List <int>(); specialCounts.InitList(i, specials.Count); var more = true; for (var k = j; more; ++k) { int oldValue = specialCounts[j]; specialCounts[j] = oldValue + k; if (this.IsApplicable(shoppedProducts, specials, specialCounts)) { var priceForSpecials = this.GetPriceForSpecials(specials, specialCounts); if (maxPrice > priceForSpecials) { var priceForRest = this.GetPriceForNonSpecials(input.Products, specials, specialCounts, shoppedProducts); var price = priceForSpecials + priceForRest; if (price < minPrice) { minPrice = price; minPriceUpdated = true; } specialCounts[j] = oldValue; } } else { more = false; } } }
public void TestGetMinPriceWith0() { var service = new ProductService(new MockResourceService()); var input = new TrolleyCalculatorInput() { Products = new List <Product>() { new Product { Name = MockResourceService.ProductNameA, Price = 0 } }, Quantities = new List <Product>() { new Product { Name = MockResourceService.ProductNameA, Quantity = 0 } }, Specials = new List <Special>() { new Special { Total = 5, Quantities = new List <Product>() { new Product { Name = MockResourceService.ProductNameA, Quantity = 0 } } } } }; Assert.AreEqual(service.GetMinPrice(input).Total, 0); Assert.AreEqual(service.GetMinPriceAsDecimal(input), 0); }
/// <summary> /// Returns the lowest possible total based on provided lists of prices, specials and quantities. /// </summary> /// <param name="input">An instance of TrolleyCalculatorInput with prices, specials and quantities</param> /// <returns>An instance of TrolleyCalculatorOutput with the lowest possible total</returns> public TrolleyCalculatorOutput GetMinPrice(TrolleyCalculatorInput input) { if (input == null) { return(this.CreateTrolleyCalculatorOutput(0)); } var maxPrice = this.GetMaxPrice(input); if (maxPrice == 0) { return(this.CreateTrolleyCalculatorOutput(0)); } var specials = this.GetApplicableSpecials(input, maxPrice); var shoppedProducts = this.GetShoppedProducts(input); var minPrice = maxPrice; var i = 0; var minPriceUpdated = false; while (!minPriceUpdated) { minPriceUpdated = false; for (var j = 0; j < specials.Count; ++j) { this.GetMinPrice(input, maxPrice, specials, shoppedProducts, ref minPrice, i, ref minPriceUpdated, j); } i++; } return(this.CreateTrolleyCalculatorOutput(minPrice)); }
private List <Special> GetApplicableSpecials(TrolleyCalculatorInput input, decimal maxPrice) { // The price is less than the max price when buying the individual items. var result = input.Specials.Where(s => s.Total < maxPrice).ToList(); // Should not to have any products that are not in the shopping cart. var shoppedProductNames = input.Quantities.Select(q => q.Name).ToList(); result = result.Where(s => s.Quantities.All(q => shoppedProductNames.Contains(q.Name))).ToList(); // Should not to have more products than the requested quantity. var shoppedProductQuntities = input.Quantities.ToDictionary(q => q.Name, q => q.Quantity); return(result.Where(s => s.Quantities.All(q => { shoppedProductQuntities.TryGetValue(q.Name, out long v); return v >= q.Quantity; })).ToList()); }
private decimal GetMaxPrice(TrolleyCalculatorInput input) { decimal price = 0; foreach (Product quantity in input.Quantities) { foreach (Product product in input.Products) { if (product.Name == quantity.Name) { price += quantity.Quantity * product.Price; break; } } } return(price); }
/// <summary> /// Returns the lowest possible total based on provided lists of prices, specials and quantities. /// </summary> /// <param name="input">An instance of TrolleyCalculatorInput with prices, specials and quantities</param> /// <returns>The lowest possible total as decimal</returns> public decimal GetMinPriceAsDecimal(TrolleyCalculatorInput input) => (decimal)this.GetMinPrice(input).Total;
private Dictionary <string, long> GetShoppedProducts(TrolleyCalculatorInput input) { return(input.Quantities.ToDictionary(q => q.Name, q => q.Quantity)); }