Mô tả bài toán
Một bộ các cuốn sách về người anh hùng nước Anh tên là Harry gồm 5 cuốn. (Cơ bản chỉ có 5 cuốn tính đến thời điểm ra đời Kata này) Trẻ em trên khắp thế giới hâm mộ Harry, và dĩ nhiên các nhà xuất bản cũng vậy. Do đó để khuyến khích bạn đọc (và để tăng doanh số bán hàng) các nhà xuất bản đã đưa ra chính sách về giá nhằm tận dụng sự lôi cuốn của người anh hùng Harry.
Mỗi cuốn sách về Harry có giá 8 EUR. Tuy nhiên nếu bạn mua 2 cuốn khác nhau (trong bộ sách 5 cuốn) bạn sẽ được giảm giá 5%. Nếu bạn mua 3 cuốn khác nhau sẽ được giảm 10%. Và giảm 20% nêu mua 4 cuốn khác nhau. Bạn sẽ được giảm 25% nếu mua trọn bộ gồm 5 cuốn.
Lưu ý, nếu bạn đặt hàng 4 cuốn nhưng chỉ thuộc 3 loại khác nhau, bạn chỉ được giảm 10% cho 3 cuốn khác hay đó, cuốn còn lại bạn vẫn phải trả đúng giá 8 EUR.
Cơn bão Harry Potter đã tràn qua các quốc gia và các bậc phụ huynh đang xếp hàng dài ở những hiệu sách để mau bộ truyện này. Bạn có nhiệm vụ viết chương trình để tính tiền cho các cửa hiệu sách theo các chính sách về giá được mô tả ở trên, chương trình đảm bảo người mua được lợi nhất về giá khi mua sách.
Ví dụ, tính giá bán của đơn hàng gồm các cuốn sách như sau:
2 cuốn Tập 1
2 cuốn Tập 2
2 cuốn Tập 3
1 cuốn Tập 4
1 cuốn Tập 5
Đáp án:
Giá bán = ( (4 x 8) – 20% [Tập 1, Tập 2, Tập 3, Tập 4] ) + ( (4 x 8) – 20% [Tập 1, Tập 2, Tập 3, Tập 5] = 25.6 * 2 = 51.20 EUR
Gợi ý:
Bạn có thể nhận thấy Kata này khá dễ để triển khai. Bạn có thể bắt đầu với test-case cho đơn hàng không có cuốn sách nào, 1 cuốn sách, 2 cuốn sách cùng tập, 2 cuốn sách khác tập, v.v… và sẽ không hề khó khăn nếu triển khai việc này với baby step và nâng dần độ phức tạp.
Tuy nhiên, sai sót sẽ dễ xảy đến khi bạn bắt tay tính toán số tiền mà sẽ cho rằng đơn hàng trên cần phải thanh toán. Đơn hàng không có giá trị là 5 x 8 x 0,75 + 3 x 8 x 0,90 = 51.6 EUR mà thực tế sẽ là 4 x 8 x 0,8 + 4 x 8 x 0,8 = 51.2 EUR. Mẹo ở đây là bạn phải viết mã đủ thông minh để lưu ý việc tính với trường hợp trên thì 2 bộ sách 4 cuốn sẽ rẻ hơn 1 bộ sách 5 cuốn và 1 bộ sách 3 cuốn.
Bạn sẽ phải đưa ra một số giải thuật thông minh để tối ưu hóa giá mua cho một đơn hàng. Đừng quá đòi hỏi một giải pháp tối ưu đầy đủ cho bài toán này. Cố gắng giải quyết bài toán này chỉ với mục tiêu chia sẻ nó cho người khác. Hãy tin rằng bạn có thể khái quát hóa và cải thiện giải pháp của mình khi có thêm các yêu cầu mới.
Gợi ý các test-case
Các test-case căn bản:
- assert_equal(0, price([])) : đơn hàng không có cuốn nào, 0 EUR
- assert_equal(8, price([0])): đơn hàng có 1 cuốn Tập 1, 8 EUR
- assert_equal(8, price([1])): đơn hàng có 1 cuốn Tập 2, 8 EUR
- assert_equal(8, price([2])): đơn hàng có 1 cuốn Tập 3, 8 EUR
- assert_equal(8, price([3])): đơn hàng có 1 cuốn Tập 4, 8 EUR
assert_equal(8, price([4])): đơn hàng có 1 cuốn Tập 5, 8 EUR - assert_equal(8 * 2, price([0, 0])): đơn hàng có 2 cuốn Tập 1, 16 EUR
- assert_equal(8 * 3, price([1, 1, 1])): đơn hàng có 3 cuốn Tập 2, 24 EUR
Các test-case một loại giảm giá:
- assert_equal(8 * 2 * 0.95, price([0, 1])): đơn hàng có 1 cuốn Tập 1, 1 cuốn Tập 2, giảm giá 5% còn 15,2 EUR.
- assert_equal(8 * 3 * 0.9, price([0, 2, 4])): đơn hàng có 1 cuốn Tập 1, 1 cuốn Tập 3 và 1 cuốn Tập 5, giảm giá 10% còn 21,6 EUR.
- assert_equal(8 * 4 * 0.8, price([0, 1, 2, 4])): đơn hàng có 1 cuốn Tập 1, 1 cuốn Tập 2, 1 cuốn Tập 3 và 1 cuốn Tập 5, giảm giá 20% còn 25,6 EUR.
- assert_equal(8 * 5 * 0.75, price([0, 1, 2, 3, 4])): đơn hàng có 1 cuốn Tập 1, 1 cuốn Tập 2, 1 cuốn Tập 3, 1 cuốn Tập 4 và 1 cuốn Tập 5, giảm giá 25% còn 30 EUR.
Các test-case có vài loại giảm giá:
- assert_equal(8 + (8 * 2 * 0.95), price([0, 0, 1])): đơn hàng có 2 cuốn Tập 1, 1 cuốn Tập 2, giá bán còn 23,2 EUR.
- assert_equal(2 * (8 * 2 * 0.95), price([0, 0, 1, 1])): đơn hàng có 2 cuốn Tập 1, 2 cuốn Tập 2, giá bán còn 30,4 EUR.
- assert_equal((8 * 4 * 0.8) + (8 * 2 * 0.95), price([0, 0, 1, 2, 2, 3])): đơn hàng có 2 cuốn Tập 1, 1 cuốn Tập 2, 2 cuốn Tập 3 và 1 cuốn Tập 4, giá bán còn 40,8 EUR.
- assert_equal(8 + (8 * 5 * 0.75), price([0, 1, 1, 2, 3, 4])): đơn hàng có 1 cuốn Tập 1, 2 cuốn Tập 2, 1 cuốn Tập 3, 1 cuốn Tập 4 và 1 cuốn Tập 5, giá bán còn 38 EUR.
Các test-case biên:
- assert_equal(2 * (8 * 4 * 0.8), price([0, 0, 1, 1, 2, 2, 3, 4])): đơn hàng có 2 cuốn Tập 1, 2 cuốn Tập 2, 2 cuốn Tập 3, 1 cuốn Tập 4 và 1 cuốn Tập 5, giá bán còn 51,2 EUR.
- assert_equal(3 * (8 * 5 * 0.75) + 2 * (8 * 4 * 0.8), price([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4])): đơn hàng có 5 cuốn Tập 1, 5 cuốn Tập 2, 4 cuốn Tập 3, 4 cuốn Tập 4 và 4 cuốn Tập 5, giá bán còn 141.2 EUR.
Nguồn: http://codingdojo.org/KataCatalogue/
0 Lời bình