Java Program: Redeem Coupon


Objectives:  


Object-oriented programming  


Task statement: 


In general there are two types of coupons: cash coupon and discount coupon. Cash coupon has a face value greater than 1, and can be used as cash to buy things. However, the price after discount cannot be less than zero. 

For example, if you use a $10.00 coupon to buy a pen worth $5.80, you would spend $0 in cash. However, you will not get any change from the shop. However, there is an “theoretical amount” involved. In the above example, the “theoretical amount” you need to pay is -$4.20, which means you will “lose” $4.20 if you use a  $10 coupon to buy the pen. If you use a $8 coupon instead, the “theoretical amount” will be - $2.20, which means you “lose” less money. The better choice is hence the $8 coupon, since you can save the $10 coupon for something more expensive. 

Discount coupon has a discount rate smaller than 1. For example, if the discount rate is 0.2, it means 20% off the price. If you buy a pen worth $5.80 with this coupon, you would pay $4.64.

 You are to create a Java service class Coupon to represent coupon. The attributes are name of a coupon, and rate which represents either the face value or discount rate of the coupon. You also need to create a method inside this class to calculate what you need to pay (the “theoretical amount”) when you use a coupon.  You are also to write a client class Redeem to read inputs as described below, and compute the best option. If there are two or more options that give the best result, you will pick the first one among them that appears in the input (as illustrated in sample input #3 below).  


Input:


The first line of the input contains two positive numbers, an amount (of type double) and an integer N (1 ≤ N ≤ 10) which indicates the number of coupons. In the subsequent N lines, each line contains information about a coupon: its name followed by face value or discount rate.  (The above symbol N is used to ease explanation. In your program, you should give more descriptive variable names and follow Java naming convention.) 


Output:


The output contains a single line, stating which is the best coupon to use, and the amount you need to pay, correct to 2 decimal places. 

Sample Input #1
123.35 3
sapphire 20.5
vip 0.3 
ruby 30 

Sample Output #1
Best choice: vip 
You need to pay $86.34  

Sample Input #2 
100.0 3 
coupon1 120
coupon2 140 
coupon3 110 

Sample Output #2 
Best choice: coupon3 
You need to pay $0.00  

Sample Input #3 
100.0 4 
coupon1 0.05 
coupon2 120 
coupon3 0.1 
coupon4 120 

Sample Output #3 
Best choice: coupon2 
You need to pay $0.00  

Solution:


// Define a coupon with rate
//   rate > 1: cash coupon with face value = rate
//   rate < 1: discount coupon with rate of discount

import java.util.*;

class Coupon {

 /********* Data attributes **********/
 private String name;
 private double rate;

 /********** Constructors **********/
 public Coupon(){        
 }

 public Coupon(String name, double rate) {
  this.name = name;
  this.rate = rate;
 }

 /********* Accessors ************/
 public String getName() {
  return name;
 }

 public double getRate() {
  return rate;
 }

 // Computes the amount to pay.
 // If payment calculated is negative, it means that
 // the coupon's value is larger than the price.
 public double payment(double price) {
  if (rate > 1)
   return price-rate;
  else
   return (1-rate)*price;
 }
}

// This program reads in an item's cost and some coupons' information,
// and then determines which is the best coupon to use and the amount 
// to pay.

public class Redeem {

 public static void main(String[] args) {
  Scanner sc = new Scanner(System.in);
  
  double price = sc.nextDouble();
  int numCoupons = sc.nextInt();

  Coupon[] coupons = new Coupon[numCoupons];

  for (int i=0; i<numCoupons; i++) 
   coupons[i] = new Coupon(sc.next(), sc.nextDouble());

  int minIndex = 0;
  double minPrice = coupons[0].payment(price), couponPrice;

  for (int i=1; i<numCoupons; i++) {
   couponPrice = coupons[i].payment(price);
   if ((couponPrice > 0 && minPrice > 0 && couponPrice < minPrice) || (couponPrice < 0 && (minPrice > 0 || (minPrice < 0 && couponPrice > minPrice)))) {
    minPrice = couponPrice;
    minIndex = i;
   }
  }
  
  // Output the result
  
  System.out.println("Best choice: " + coupons[minIndex].getName());
  System.out.printf("You need to pay $%.2f\n",((minPrice < 0)? 0 : minPrice));
 }
}