Part 1
In this puzzle, we have a list of accounts with their initial amount and a list of transactions. Each transaction is in the same format: "FROM A TO B AMT C". This means person A sends a certain amount of money to person B. We should perform all the transactions and return the sum of the balance of the 3 highest accounts.
We first parse the initial balances and create a dictionary entry for each person. Afterwards, we go through each transaction and simply subtract the amount from balance A and add it to balance B:
for from_acct, to_acct, amount in transfers:
balances[from_acct] -= amount
balances[to_acct] += amount
Finally we get the answer using the highest balances:
highest_accounts = list(sorted(balances.values(), reverse=True))
sum_3_highest_accounts = sum(highest_accounts[:3])
Part 2
In part 2, we have a more complicated way to perform transactions. Previously, balances could get negative during a transaction. Now we cap the amount transfered so person A's balance cannot get negative. The answer is still the sum of the balance of the 3 highest accounts.
We write a different function to perform this new kind of transaction. Most of the code is the same, but we first limit the amount transfered to the balance of account A:
for from_acct, to_acct, amount in transfers:
amount = min(amount, balances[from_acct])
balances[from_acct] -= amount
balances[to_acct] += amount
Part 3
In part 3, we have an even more complicated way to perform transactions. Whenever the amount for a transaction is limited because A has not enough money in their account, we note the remaining amount as a debt from A to B. Whenever person A gets money, they immediately need to spend it to pay down their debt. This need not be the full amount, but can be a partial repayment. If the recipient also had debt, this can trigger new repayments from person B's account. The debt has a priority based on the time, so earlier debt is payed back first.
We perform the transactions as usual, but create list of debts with the amount of transactions we could not perform until now:
transfer_amount = min(amount, balances[from_account])
debt = amount - transfer_amount
balances[from_account] -= transfer_amount
balances[to_account] += transfer_amount
elif debt > 0:
debts.append((from_account, to_account, debt))
After each regular transaction, we iterate the list of debts remaining and try if anyone has enough money now. This is repeated until no one can pay down debts, then we go to the next regular transaction.
There might be a better checking if there are debts payable instead of a list, such as a list per account owner, but the length of the transaction list was short enough.
No comments:
Post a Comment