Use only in-memory state. Identifiers are nonempty strings supplied by the caller. Amounts and limits are integers within the declared C++ numeric type. There are no timestamps, threads, persistence, or external services.

Prototype: implement BalanceAccount() with initial balance zero. balance() returns the integer balance. deposit(amount) requires amount > 0, adds it, and returns the new balance. withdraw(amount) requires amount > 0; return false without mutation if funds are insufficient, otherwise debit and return true. Invalid amounts raise std::invalid_argument without mutation.

Final: implement Bank():

  • create_account(): create a zero-balance account and zero outgoing total; return false on a duplicate without resetting it.
  • balance(): return the balance, or nullopt for an unknown account.
  • deposit(): reject nonpositive amounts with std::invalid_argument first; return nullopt for an unknown account, otherwise return its new balance.
  • transfer(): reject a nonpositive amount with std::invalid_argument first. A previously successful request with exactly the same (source, target, amount) returns its original (source_balance, target_balance). Reusing that identifier with different arguments raises std::invalid_argument. Otherwise return nullopt without mutation for missing accounts, identical accounts, or insufficient funds. On success move the amount, add it only to the source's outgoing total, record the successful request, and return the two resulting balances. Failures do not consume request identifiers.
  • top_spenders(): return at most limit accounts ordered by outgoing total descending, then identifier ascending. Include zero-spending accounts. Zero returns []; negative limits raise std::invalid_argument. The list is a fresh snapshot.

All raised errors and rejected requests preserve state. Separate instances are independent.

The public C++ API below is authoritative for field types and return values. erase is used where another language might use a method named delete, because delete is a C++ keyword. Returned records are value snapshots with the documented named fields; mutating a record or its nested vectors cannot affect the service.

cpp

class BalanceAccount { public:
 BalanceAccount();
 Int balance() const;
 Int deposit(Int amount);
 bool withdraw(Int amount);
};
class Bank { public:
 Bank();
 bool create_account(const std::string& id);
 Opt<Int> balance(const std::string& id) const;
 Opt<Int> deposit(const std::string& id,Int amount);
 Opt<Pair> transfer(const std::string& request,const std::string& source,const std::string& target,Int amount);
 Vec<std::pair<std::string,Int>> top_spenders(Int limit) const;
};

Compile and run from this directory:

Shell
c++ -std=c++20 -O2 -Wall -Wextra -pedantic -pthread main.cpp -o practice
./practice --stage prototype
./practice --stage final

Edit exercise.hpp. Both stages start unfinished and must report failures until implemented. Keep main.cpp as the executable contract. The runner returns nonzero for a failed check, an unexpected exception, an invalid stage, or an empty suite. C++20 and only the standard library are required.

Drag or use the arrow keys to resize. Home collapses the question; End collapses the editor. Enter or double-click resets the split.
Loading editor…
No results yet.

Complete the starter code, then run the checks.
Results and errors will appear here.

C++ runtime powered by Wasmer.