Newspaper Seller Case Study

Presented by: Ahmed Abbas, Rokiya Abdelsattar, Ahmed Ibrahim

Presented for: Dr. Noha Ali

Problem Definition

The newspaper seller wants to determine how many newspapers he should buy each day in order to maximize his profits. His present method of determining the quantity of newspapers is based upon his best guess or estimate of the daily demand for the day news.

Assumptions and Parameters

Probability Distributions

Day Type Probability Distribution

Type of Newsday Probability Cumulative Random Number Range
Good 0.35 0.35 0 ≤ R < 0.35
Fair 0.45 0.80 0.35 ≤ R < 0.80
Poor 0.20 1.00 0.80 ≤ R ≤ 1

Demand Probability Distribution

Demand Probability Distribution Cumulative Random-Digit Assignment
Good Fair Poor Good Fair Poor Good Fair Poor
Lower Upper Lower Upper Lower Upper
40 0.03 0.10 0.44 0.03 0.10 0.44 0.00 0.02 0.00 0.09 0.00 0.43
50 0.05 0.18 0.22 0.08 0.28 0.66 0.03 0.07 0.10 0.27 0.44 0.65
60 0.15 0.40 0.16 0.23 0.68 0.82 0.08 0.22 0.28 0.67 0.66 0.81
70 0.20 0.20 0.12 0.43 0.88 0.94 0.23 0.42 0.68 0.87 0.82 0.93
80 0.35 0.08 0.06 0.78 0.96 1.00 0.43 0.77 0.88 0.95 0.94 1.00
90 0.15 0.04 0.00 0.93 1.00 0.78 0.92 0.96 1.00
100 0.07 0.00 0.00 1.00 0.93 1.00

Model Formulation

The key equations used in the model are as follows (corrected for clarity):

  1. Revenue from sales = min(d, X) × P
  2. Cost of newspapers = X × C
  3. Number of unsold newspapers = max(X - d, 0)
  4. Salvage from scrap = Number of unsold newspapers × S
  5. Lost profit from unmet demand = (d > X) ? (d - X) × (P - C) : 0
  6. Daily profit (Z) = Revenue from sales - Cost of newspapers + Salvage from scrap - Lost profit from unmet demand

Objective: Use simulation (e.g., random number generation for day type and demand) to estimate the optimal number of newspapers to purchase daily (X) that maximizes the average profit Z(X, d).

Implementation

Excel Sheet Simulation Example

Day R.D Type Type R.D.Demand Demand Revenue Sales Excess Demand Lost Profit Num of Scrap Salvage from Scrap Daily Profit
1 1 Good 1 40 2000 0 0 30 150 -160
2 2 Good 26 70 3500 0 0 0 0 1190
3 32 Good 75 80 3500 10 170 0 0 1020

Note: The above table shows a sample simulation for X = 70 newspapers. Full simulation data is available in the original report.

Project Resources

C++ Code

constexpr int days = 30;
constexpr int quantity = 70;
constexpr int paper_cost = 33;
constexpr int iteration = 10;
constexpr float scrap_sale = 5;
constexpr float paper_sell = 50;

// Types of News day
constexpr float GOOD = 0.35;
constexpr float FAIR = 0.45;
constexpr float POOR = 0.20;

float cumulative_prob[3] = {GOOD, GOOD + FAIR, GOOD + FAIR + POOR};

struct RD {
    float lower, upper;
} RandDist[3] = {
    {0.0, GOOD - 0.01},
    {GOOD, GOOD + FAIR - 0.01},
    {GOOD + FAIR, GOOD + FAIR + POOR}
};

struct DayData {
    int day;
    double R1;
    string type;
    double R2;
    int demand;
    int revenue_sales;
    int excess_demand;
    int lost_profit;
    int num_scrap;
    int salvage_scrap;
    int daily_profit;
};

int getDemand(const string& dayType, const double R) {
    if (dayType == "Good") {
        if (R < 0.03) return 40;
        if (R < 0.08) return 50;
        if (R < 0.23) return 60;
        if (R < 0.43) return 70;
        if (R < 0.78) return 80;
        if (R < 0.93) return 90;
        return 100;
    }
    if (dayType == "Fair") {
        if (R < 0.10) return 40;
        if (R < 0.28) return 50;
        if (R < 0.68) return 60;
        if (R < 0.88) return 70;
        if (R < 0.96) return 80;
        return 90;
    }
    if (dayType == "Poor") {
        if (R < 0.44) return 40;
        if (R < 0.66) return 50;
        if (R < 0.82) return 60;
        if (R < 0.94) return 70;
        return 80;
    }
    return 40; // Default fallback
}

vector simulate(int X, int N) {
    vector results;
    random_device rd;
    mt19937 gen(rd());
    uniform_real_distribution<> dis(0.0, 1.0);
    for (int day = 1; day <= N; ++day) {
        DayData data;
        data.day = day;
        data.R1 = dis(gen);
        if (data.R1 < GOOD) data.type = "Good";
        else if (data.R1 < GOOD + FAIR) data.type = "Fair";
        else data.type = "Poor";
        data.R2 = dis(gen);
        data.demand = getDemand(data.type, data.R2);
        data.revenue_sales = min(data.demand, X) * paper_sell;
        data.excess_demand = max(data.demand - X, 0);
        data.lost_profit = (data.demand > X) ? (data.demand - X) * (paper_sell - paper_cost) : 0;
        data.num_scrap = max(X - data.demand, 0);
        data.salvage_scrap = data.num_scrap * scrap_sale;
        data.daily_profit = data.revenue_sales - (X * paper_cost) + data.salvage_scrap - data.lost_profit;
        results.push_back(data);
    }
    return results;
}

void writeTable(const vector& results) {
    ofstream outfile("simulation_results.txt");
    outfile << "Day\t|\tR1\t|\tType\t|\tR2\t|\tDemand\t|\tRevenue Sales\t|\tExcess Demand\t|\tLost Profit\t|\tNum Scrap\t|\tSalvage Scrap\t|\tDaily Profit\n";
    for (const auto& data : results) {
        outfile << data.day << "\t|\t"
                << fixed << setprecision(2) << data.R1 << "\t|\t"
                << data.type << "\t|\t"
                << data.R2 << "\t|\t"
                << data.demand << "\t|\t"
                << data.revenue_sales << "\t|\t"
                << data.excess_demand << "\t|\t"
                << data.lost_profit << "\t|\t"
                << data.num_scrap << "\t|\t"
                << data.salvage_scrap << "\t|\t"
                << data.daily_profit << "\n";
    }
    outfile.close();
}

int main() {
    int N_large = 1000;
    vector X_values = {40, 50, 60, 70, 80, 90, 100};
    double best_avg_profit = -numeric_limits::max();
    int best_x = -1;
    cout << "Let's simulate...\n";
    for (int X : X_values) {
        auto results = simulate(X, N_large);
        double total_profit = 0;
        for (const auto& data : results) total_profit += data.daily_profit;
        double avg_profit = total_profit / N_large;
        cout << "Quantity X = " << X << ", Average Profit = " << fixed << setprecision(2)
             << avg_profit << " cents\n";
        if (avg_profit > best_avg_profit) {
            best_avg_profit = avg_profit;
            best_x = X;
        }
    }
    cout << "\nOptimal quantity to buy: " << best_x << " newspapers\n";
    cout << "Expected avg profit: " << fixed << setprecision(2) << best_avg_profit << " cents per day\n";
    auto table_results = simulate(best_x, days);
    writeTable(table_results);
    return 0;
}
            

Results and Conclusion

The simulation results indicate that the optimal number of newspapers to purchase daily is determined by running the C++ simulation over various quantities (X = 40, 50, 60, 70, 80, 90, 100). The code calculates the average profit for each quantity over 1000 days and identifies the quantity that maximizes profit. Detailed results, including a table of Quantity vs. Average Profit and interpretations of how demand patterns and day types influence profitability, are available in the full simulation output.