import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

class BookStore {

  private static final int BOOK_PRICE = 8, MAX_GROUP_SIZE = 5;

  private static double[] DISCOUNT_TIERS = {0, 5, 10, 20, 25};

  double calculateBasketCost(final List<Integer> books) {
    return calculateBasketCost(books, 0);
  }

  private double calculateBasketCost(final List<Integer> books, final double priceSoFar) {
    if (books.size() == 0) {
      return priceSoFar;
    }

    List<Integer> availableBookNumbers = books.stream()
        .distinct()
        .collect(Collectors.toList());

    double minPrice = Double.MAX_VALUE;

    for (int i = 0; i < availableBookNumbers.size(); i++) {
      List<Integer> newGroupBooks = new ArrayList<>(availableBookNumbers.subList(0, i + 1));
      List<Integer> remainingBooks = new ArrayList<>(books);

      for (final Integer newGroupBook : newGroupBooks) {
        //noinspection UseBulkOperation - we want to remove _one_ of each book number, not _all_ of each book number.
        remainingBooks.remove(newGroupBook);
      }

      double price = calculateBasketCost(remainingBooks, priceSoFar + costOfGroupSize(newGroupBooks.size()));
      minPrice = Math.min(minPrice, price);
    }

    return minPrice;
  }

  private double costOfGroupSize(int groupSize) {
    if (groupSize < 1 || groupSize > MAX_GROUP_SIZE) {
      throw new IllegalStateException("Invalid group size : " + groupSize);
    }

    return BOOK_PRICE * groupSize * (100 - DISCOUNT_TIERS[groupSize - 1]) / 100;
  }

}

@@ -100,16 +100,18 @@
 tore %7B%0A%0A
+  
   privat
@@ -164,24 +164,26 @@
 IZE = 5;%0A%0A  
+ 
+ 
 private stat
@@ -234,16 +234,18 @@
 25%7D;%0A%0A  
+ 
+ 
 double c
@@ -292,24 +292,28 @@
 ooks) %7B%0A    
+   
+ 
 return calcu
@@ -338,21 +338,25 @@
 ks, 0);%0A
+  
   %7D%0A%0A
+  
   privat
@@ -438,24 +438,28 @@
 oFar) %7B%0A    
+   
+ 
 if (books.si
@@ -467,24 +467,30 @@
 e() == 0) %7B%0A
+      
       return
@@ -502,27 +502,35 @@
 eSoFar;%0A    
+ 
-%7D%0A%0A
+   %7D%0A%0A    
     List%3CInt
@@ -581,16 +581,20 @@
         
+ 
+   
 .distinc
@@ -597,16 +597,20 @@
 tinct()%0A
+    
         
@@ -641,24 +641,28 @@
 st());%0A%0A    
+  
+  
 double minPr
@@ -686,16 +686,20 @@
 VALUE;%0A%0A
+    
     for 
@@ -752,24 +752,30 @@
 ++) %7B%0A      
+  
+    
 List%3CInteger
@@ -845,24 +845,30 @@
 0, i + 1));%0A
+      
       List%3CI
@@ -913,24 +913,30 @@
 %3C%3E(books);%0A%0A
+      
       for (f
@@ -972,32 +972,40 @@
 ewGroupBooks) %7B%0A
+        
         //noinsp
@@ -1106,16 +1106,24 @@
 number.%0A
+        
         
@@ -1161,27 +1161,39 @@
 ook);%0A      
+ 
-%7D%0A%0A
+     %7D%0A%0A      
       double
@@ -1296,16 +1296,22 @@
 ;%0A      
+     
+ 
 minPrice
@@ -1336,35 +1336,43 @@
 ce, price);%0A    
-%7D%0A%0A
+    %7D%0A%0A    
     return minPr
@@ -1376,21 +1376,25 @@
 nPrice;%0A
+  
   %7D%0A%0A
+  
   privat
@@ -1431,24 +1431,28 @@
 roupSize) %7B%0A
+    
     if (grou
@@ -1490,24 +1490,30 @@
 OUP_SIZE) %7B%0A
+      
       throw 
@@ -1576,27 +1576,35 @@
 pSize);%0A    
+  
+  
 %7D%0A%0A
+    
     return B
@@ -1672,15 +1672,17 @@
  / 100;%0A
+  
   %7D%0A%0A%7D%0A

change indent from 2 to 4 spaces (#1029)