C++: Tracking orders

Move orders through a series of states.

What to build

A small state machine using a map and an enum class.

Requirements

  • The states are New, Paid and Shipped.
  • add ID creates an order as New, or prints exists.
  • pay ID moves it from New to Paid. ship ID moves it from Paid to Shipped.
  • A command on a missing order prints missing. A move not allowed from the current state prints not allowed.
  • report prints each order in increasing ID order, as ID state, with the state in lower case.

Input

The first line has n. Each of the next n lines is a command.

Output

Only what the commands above print.

Constraints

n is from 1 to 200.

Example

Input:

4
add 2
add 1
pay 2
report

Output:

1 new
2 paid

Why it works

Naming every state makes the rules read like the description, and the map keeps the orders sorted for the report.

Examples

Example 1 · Input
4
add 2
add 1
pay 2
report
Expected output
1 new
2 paid
Example 2 · Input
2
pay 9
add 1
Expected output
missing

Hints

Hint 1

Use map<int, Status>, with an enum class for the status.

Hint 2

Use count to check whether an order exists.

Hint 3

Only a New order can be paid, and only a Paid order can be shipped.

Solution

Show one correct solution (try it yourself first)
#include <iostream>
#include <map>
#include <string>
using namespace std;

enum class Status { New, Paid, Shipped };

string text_of(Status s) {
    if (s == Status::New) return "new";
    if (s == Status::Paid) return "paid";
    return "shipped";
}

int main() {
    int n;
    cin >> n;
    map<int, Status> orders;
    for (int i = 0; i < n; i++) {
        string command;
        cin >> command;
        if (command == "report") {
            for (const auto& order : orders) {
                cout << order.first << " " << text_of(order.second) << endl;
            }
            continue;
        }
        int id;
        cin >> id;
        if (command == "add") {
            if (orders.count(id)) {
                cout << "exists" << endl;
            } else {
                orders[id] = Status::New;
            }
        } else if (!orders.count(id)) {
            cout << "missing" << endl;
        } else if (command == "pay" && orders[id] == Status::New) {
            orders[id] = Status::Paid;
        } else if (command == "ship" && orders[id] == Status::Paid) {
            orders[id] = Status::Shipped;
        } else {
            cout << "not allowed" << endl;
        }
    }
    return 0;
}

Lesson: Modern C++ →