Problem Solving: Allotment calculator
Problem Statement:
Suppose the Government plans to issue up to $10,000 of Savings Bonds. Four individuals applied for a total of $18,000 of Savings Bonds: A ($2,000), B ($4,000) C ($5,500) and D ($6,500).
The available bonds will be spread out among as many investors as possible in the following manner:
- Applications are filled in denominations of $500 upwards.
- After Round 4, $8,000 of Savings Bonds have been allotted, and Investor A's application has been fully met. $2,000 of Savings Bonds are left.
- In Round 5, $1,500 of Savings Bonds are allotted.
- In Round 6, the remaining $500 is insufficient to fill all applications.
- One person among Investor B, Investor C and Investor D is randomly allotted the remaining $500. In this case, Investor C gets it.
The cutoff amount in this case is $2,500. In the final allotment:
- Investor A is allotted $2,000.
- Investor B and Investor D get $2,500 each.
- Investor C gets $3,000.
limitations:
1. The minimum individual investment amount is $500
2. The maximum individual investment amount is $200000
3. The individual investment amount always should be multiplies of $500
Find out the allotment amount issued to each individual investor.
The Solution:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
public class SbPlanningCalculator {
private final static Integer MIN = 500;
private final static Integer MAX = 2_00_000;
private final static Predicate<List<User>> isAllValid = users -> {
int allCount = users.size();
int validCount = (int)users.stream().
map(User::getValue).
filter(value -> value >= MIN && value <= MAX && value % MIN == 0).
count();
return allCount == validCount;
};
public static Map<String, Integer> calculateMyPotential(List<User> users, Integer issuedAmount){
if(!isAllValid.test(users)){
System.err.print("Found Invalid Amounts among the users. ");
return null;
}
int total = 0;
Map<String, Integer> allotments = new HashMap<>(0);
int rounds = Math.divideExact(issuedAmount, users.size() * MIN);
int i = 0;
while(i <= rounds) {
for (User user : users) {
int issuedBalanceTotal = issuedAmount - total;
if (issuedBalanceTotal == 0) {
break;
}
if (user.getValue() >= MIN) {
total = total + MIN;
user.setValue(user.getValue() - MIN);
if (allotments.containsKey(user.getName())) {
int userAllotment = allotments.get(user.getName());
allotments.put(user.getName(), userAllotment + MIN);
} else {
allotments.put(user.getName(), MIN);
}
}
}
i++;
}
return allotments;
}
}
Test Cases:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class SbPlanningCalculatorTest {
@Test
void testCalculateMyPotentialCase1(){
List<User> users = new ArrayList<>(0);
users.add(new User("A", 2000));
users.add(new User("B", 4000));
users.add(new User("C", 5500));
users.add(new User("D", 6500));
Map<String, Integer> allotments = SbPlanningCalculator.calculateMyPotential(users, 10000);
System.out.println(allotments);
assert allotments != null;
var x = allotments.entrySet().stream().collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.counting()));
long sum = x.entrySet().stream().map(e -> e.getKey() * e.getValue()).mapToLong(l -> l).sum();
Assertions.assertEquals(10000, sum);
}
@Test
void testCalculateMyPotentialCase2(){
List<User> users = new ArrayList<>(0);
users.add(new User("A", 2000));
users.add(new User("B", 4000));
users.add(new User("C", 5500));
users.add(new User("D", 26000));
Map<String, Integer> allotments = SbPlanningCalculator.calculateMyPotential(users, 1_000_000_000);
System.out.println(allotments);
assert allotments != null;
var x = allotments.entrySet().stream().collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.counting()));
long sum = x.entrySet().stream().map(e -> e.getKey() * e.getValue()).mapToLong(l -> l).sum();
Assertions.assertEquals(37500, sum);
}
@Test
void testCalculateMyPotentialCase3(){
List<User> users = new ArrayList<>(0);
users.add(new User("A", 500));
users.add(new User("B", 2_00_000));
users.add(new User("C", 14000));
users.add(new User("D", 26000));
Map<String, Integer> allotments = SbPlanningCalculator.calculateMyPotential(users, 1_000_000_000);
System.out.println(allotments);
assert allotments != null;
var x = allotments.entrySet().stream().collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.counting()));
long sum = x.entrySet().stream().map(e -> e.getKey() * e.getValue()).mapToLong(l -> l).sum();
Assertions.assertEquals(2_40_500, sum);
}
@Test
void testCalculateMyPotentialCase4(){
List<User> users = new ArrayList<>(0);
users.add(new User("A", 1_000_000));
users.add(new User("B", 2_00_000));
users.add(new User("C", 250));
users.add(new User("D", 26000));
Map<String, Integer> allotments = SbPlanningCalculator.calculateMyPotential(users, 1_000_000_000);
System.out.println(allotments);
Assertions.assertNull(allotments);
}
@Test
void testCalculateMyPotentialCase5(){
List<User> users = new ArrayList<>(0);
users.add(new User("A", 2_00_000));
users.add(new User("B", 2_00_000));
users.add(new User("C", 2_00_000));
users.add(new User("D", 26000));
for(int x = 0; x < 5500; x++){
users.add(new User("X" + x, 2_00_000));
}
Map<String, Integer> allotments = SbPlanningCalculator.calculateMyPotential(users, 1_000_000_000);
assert allotments != null;
var x = allotments.entrySet().stream().collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.counting()));
System.out.println(x);
long sum = x.entrySet().stream().map(e -> e.getKey() * e.getValue()).mapToLong(l -> l).sum();
Assertions.assertEquals(1_000_000_000, sum);
}
}
Comments
Post a Comment