While doing a code Kata, I've run into a slight logical problem that I can't figure out a solution to. It isn't a hard-and-fast requirement of completing the task but it has me intrigued as to how it could be handled.
The Kata is simulating applying pricing discounts and a supermarket checkout (see full Kata here) through a collection of pricing rules. To play around with some inheritance and interface capabilities, I've added a "Buy X, get Y free" rule. It works fine when the Y
in question is 1
, but starts getting a little hazy after that...
For example, I experimented with the idea of "Buy 3
, get 2
free". I tried doing this by grouping the items in groups of 5, and working out the discount of each group by subtracting the price of two of the items:
public override double CalculateDiscount(Item[] items)
{
//per the example described above
//_groupSize = 5, _buy = 3
//meaning 2 out of every group of 5 items should be free
var discountGroups = new List<IEnumerable<Item>>();
for (var i = 0; i < items.Length / _groupSize; i )
{
discountGroups.Add(items.Skip(i * _groupSize).Take(_groupSize));
}
return discountGroups
.Sum(group => group
.Skip(_buy)
.Sum(item => item.Price)
);
}
What I found is that the above code works as expected (if each item has a Price
property of 1.00
, the above would return 2.00
). An edge case that I am looking to solve is that it doesn't take affect until the fifth item is added (so the price as you ad each item would go 1.00
, 2.00
, 3.00
, 4.00
, 3.00
).
What I would ideally like is that, once you have three items in your collection, the next two items are free, whether you choose to take just one or two of them shouldn't affect the price. I understand this isn't hugely realistic to the domain, but I was interested in trying to solve it as a technical problem.
I've had a few cracks at it but haven't successfully gotten any closer than the above code. I figure that what I need to do is group the array into the minimum number of bought items required, then a variable number of free items. I could probably hard-code something to solve the issue once, but this gets complicated if I were to simulate buying 3 items and getting 2 free, then buying 3 items but only taking one free one.
Any advice on how to go about this would be really appreciated!
Thanks, Mark
CodePudding user response:
Your discount-calculation has some bugs, for example you dont create groups if the item-count is less than groupSize. So change i <
to i <=
:
for (var i = 0; i <= items.Length / groupSize; i )
{
discountGroups.Add(items.Skip(i * groupSize).Take(groupSize));
}
Maybe that's already all.