Skip to content

Instantly share code, notes, and snippets.

@ningthoujam-lokhendro
Created July 18, 2023 09:19
Show Gist options
  • Save ningthoujam-lokhendro/b79bc3806d790e84af9b74de430e6c03 to your computer and use it in GitHub Desktop.
Save ningthoujam-lokhendro/b79bc3806d790e84af9b74de430e6c03 to your computer and use it in GitHub Desktop.
Sample Solution
enum Currency {
CZK, EUR, GBP
}
abstract class Fund {
Currency currency;
BigDecimal amount;
public Fund() {}
public Fund(String currency, String balance) {
this.setCurrency(currency);
this.setAmount(balance);
}
private static Currency getValidCurrency(String currency) {
for (Currency c:Currency.values()){
if (c.name().equals(currency))
return Currency.valueOf(currency);
}
throw new IllegalArgumentException("Invalid Currency : " + currency);
}
private static BigDecimal getValidAmount(String amount) {
BigDecimal amt = new BigDecimal(amount);
if (amt.signum() > 0) {
return amt;
}
throw new IllegalArgumentException("Invalid amount :" + amount);
}
public Currency getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = getValidCurrency(currency);
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = getValidAmount(amount);
}
}
class Account extends Fund implements Comparable<Account> {
private Account() {
}
private Account(String currency, String balance) {
super(currency, balance);
}
private static BigDecimal GBP_PC = BigDecimal.ONE.divide(BigDecimal.valueOf(300),5, RoundingMode.UP);
private static BigDecimal OTHER_PC = BigDecimal.ONE.divide(BigDecimal.valueOf(200),5, RoundingMode.UP);
// Factory Class to get valid Account
public static Account of(String strings) {
try {
String[] tokens = strings.split(":");
if (tokens.length == 2)
return new Account(tokens[0],tokens[1]);
else
throw new IllegalArgumentException("Invalid input : " + strings);
}
catch (Exception ex) {
System.out.println(ex.getMessage());
}
return new Account();
}
public String debitWithPercentage(Payment payment) {
BigDecimal toPay = new BigDecimal(0);
if (this.getCurrency().equals(Currency.GBP)) {
toPay = payment.getAmount().subtract(payment.getAmount().multiply(GBP_PC));
}
else {
toPay = payment.getAmount().subtract(payment.getAmount().multiply(OTHER_PC));
}
this.amount = this.amount.subtract(toPay);
return new StringBuilder().append(payment.getId())
.append(":")
.append(payment.getCurrency())
.append(":")
.append(toPay.setScale(2, RoundingMode.UP)).toString();
}
@Override
public int compareTo(Account a) {
return a.getCurrency().compareTo(this.getCurrency());
}
}
class Payment extends Fund implements Comparable<Payment> {
int id;
private Payment() {}
private Payment(String id, String currency, String balance) {
super(currency, balance);
this.setId(id);
}
public static Payment of(String strings) {
try {
String[] tokens = strings.split(":");
if (tokens.length == 3) {
return new Payment(tokens[0],tokens[1],tokens[2]);
}
else
throw new IllegalArgumentException("Invalid input : " + strings);
}
catch (Exception ex) {
System.out.println(ex.getMessage());
}
return new Payment();
}
private int getValidId(String string) {
Integer integer = Integer.parseInt(string);
if (Integer.signum(integer) > 0)
return integer.intValue();
throw new IllegalArgumentException("Invalid id :" + string);
}
public int getId() {
return id;
}
public void setId(String id) {
this.id = getValidId(id);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.getId()).append(":").append(this.getCurrency()).append(":").append(this.getAmount());
return sb.toString();
}
@Override
public int compareTo(Payment p) {
return this.getAmount().compareTo(p.getAmount());
}
}
public class Problem {
// Build Accounts Map in sorted {currency : fund}
private static TreeMap<Currency,Account> getAccount(String string) {
return Arrays.stream(string.split(","))
.map(s -> Account.of(s))
.filter(account -> account.getCurrency() != null)
.collect(Collectors.toMap(Account::getCurrency, Function.identity(), (k1,k2)->k1, TreeMap::new));
}
// Build Payment Map in sorted payment batch
// { currency : [ currency : batch ] }
private static TreeMap<Currency,TreeSet<Payment>> getSortedPaymentList(String payments) {
List<Payment> paymentList = Arrays.stream(payments.split(","))
.map(token -> Payment.of(token))
.filter(p->p.getCurrency() != null)
.collect(Collectors.toList());
TreeMap<Currency,TreeSet<Payment>> paymentSortedMap = paymentList.stream()
.collect(Collectors.groupingBy(Payment::getCurrency, TreeMap::new, Collectors.toCollection(TreeSet::new)));
return paymentSortedMap;
}
public static String GeneratePaymentBatches(String fundsAndPayments) {
String[] input = fundsAndPayments.split(Pattern.quote("|"));
String funds = input[0];
String payments = input[1];
// Get Funds
Map<Currency,Account> accountMap = getAccount(funds);
TreeMap<Currency,TreeSet<Payment>> payList = getSortedPaymentList(payments);
System.out.println(payList);
// Build Payment batch
StringBuilder result = new StringBuilder();
for (Map.Entry<Currency, Account> entry:accountMap.entrySet()) {
result.append(batchProcess(entry.getValue(),payList.get(entry.getKey())));
}
return result.toString();
}
static String batchProcess(Account account, TreeSet<Payment> paymentBatch ) {
if (account == null) return "";
StringBuilder sb = new StringBuilder();
for (Payment payment : paymentBatch) {
BigDecimal balance = account.getAmount().subtract(payment.getAmount());
if ( balance.signum() == 1) {
if (sb.indexOf(account.currency.name()) == -1) sb.append(account.currency.name()).append("\n");
sb.append(account.debitWithPercentage(payment)).append("\n");
}
}
return sb.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment