Created
July 18, 2023 09:19
-
-
Save ningthoujam-lokhendro/b79bc3806d790e84af9b74de430e6c03 to your computer and use it in GitHub Desktop.
Sample Solution
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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