Out-of-Order Loan Ledger
Reported by candidates from Valon's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
The mistake that sinks a first attempt on this Valon OA, reported September 2026, is recomputing the whole ledger after every event and then wondering why the big tests time out. The problem is Out-of-Order Loan Ledger. Fees and payments arrive in receive order but have to be applied in accounting-sequence order, and you print a full snapshot after each one. It's a sorting problem wearing a finance costume. With up to 100000 events, the naive version dies. If you blank mid-assessment, StealthCoder runs invisibly on your screen as a safety net while you get your footing back.
The problem
A loan starts with initialPrincipal and a zero fee balance. Process events in receive order. Each event has a unique accounting sequence: FEE adds its amount to the fee balance. PAYMENT pays the fee balance first and then principal. Any amount remaining after both balances reach zero is ignored. Events may arrive out of accounting order. After inserting each received event, order all events by accounting sequence and recompute the balances from the earliest affected position. Return one ledger snapshot after every received event. A snapshot lists all current entries in ascending accounting-sequence order as sequence:principalBalance:feeBalance, joined with |. Function processLoanEvents(initialPrincipal: long, eventTypes: String[], amounts: long[], sequences: int[]) → String[] Examples Example 1 initialPrincipal = 100000 eventTypes = ["PAYMENT","PAYMENT","FEE"] amounts = [1000,500,100] sequences = [1,3,2] return = ["1:99000:0","1:99000:0|3:98500:0","1:99000:0|2:99000:100|3:98600:0"] When sequence 2 arrives, only the affected suffix is recomputed, and the later payment clears its fee before principal. Example 2 initialPrincipal = 1000 eventTypes = ["FEE","PAYMENT"] amounts = [75,100] sequences = [10,20] return = ["10:1000:75","10:1000:75|20:975:0"] The payment clears 75 of fees and then reduces principal by 25. Example 3 initialPrincipal = 50 eventTypes = ["PAYMENT"] amounts = [80] sequences = [1] return = ["1:0:0"] Balances do not become negative. Constraints 0 <= initialPrincipal <= 10^9. eventTypes.length == amounts.length == sequences.length <= 100000. Every type is FEE or PAYMENT. 0 <= amounts[i] <= 10^9. Accounting sequences are unique signed 32-bit integers. All running balances fit in a signed 64-bit integer.
Reported by candidates. Source: FastPrep
Pattern and pitfall
The core is keeping events sorted by sequence as they arrive, then replaying balances. Payment logic is simple: subtract from fees first, then principal, clamp at zero, ignore leftovers. The trick is that an insert at position k only changes balances from k onward, so you start from the balance stored just before k and recompute the suffix. Prefix entries stay untouched. The common pitfall is rebuilding everything from the initial principal each time, or using a plain array insert and forgetting that the output snapshot itself is O(n) per event anyway. Think about what the output size forces you to accept before chasing a fancier structure. Also watch the 64-bit types, and remember that sequences are signed and unique, so negatives sort correctly. If the suffix logic won't come together live, StealthCoder is the hedge on the real assessment. It reads the problem and hands you a working structure.
StealthCoder is the hedge for the one pattern you didn't drill. It runs invisibly during the screen share.
You can drill Out-of-Order Loan Ledger cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. If you're reading this with an OA window open, you're who this was built for.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass Valon's OA.
Valon reuses patterns across OAs. If you're reading this with an OA window open, you're who this was built for. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Out-of-Order Loan Ledger FAQ
What's the trick in the Valon Out-of-Order Loan Ledger problem?+
Keep events sorted by accounting sequence and only recompute balances from the insertion point onward. Store the principal and fee balance after each entry, so the suffix replay starts from the previous entry's state. Payments clear fees first, then principal, never going below zero.
How hard is this OA really?+
Medium. The rules are easy to read, but the combination of ordered insertion, suffix recompute, and building string snapshots trips people up. Most failures come from rebuilding the entire ledger each time or mishandling the payment overflow case where the amount exceeds both balances.
Do I need a balanced tree or can I use a sorted array?+
Output size is the limit. Every snapshot lists all entries, so each step costs at least O(n) in string building. A sorted list with binary search insertion and suffix recompute is fine. Don't over-engineer the data structure before you've checked what the output forces.
What edge cases should I test?+
Payment larger than fee plus principal, giving zero balances. Zero-amount events. Negative sequence numbers. An event that arrives with the lowest sequence, forcing a full recompute. An insert at the end, which only touches one entry. Initial principal of zero.
How do I prepare in 48 hours for this kind of question?+
Write the three examples as tests first. Then implement sorted insertion with binary search and a suffix replay loop. Practice formatting the sequence:principal:fee output joined by pipes. Check your types handle 64-bit values. That covers nearly everything this problem asks.