```json
{
  "sym_variables": [
    ("x0", "scissors"),
    ("x1", "smoke detectors"),
    ("x2", "hole punches"),
    ("x3", "mechanical pencils")
  ],
  "objective_function": "5.78 * x0 + 4.79 * x1 + 1.44 * x2 + 8.87 * x3",
  "constraints": [
    "3 * x0 + 26 * x1 + 11 * x2 + 6 * x3 <= 373",
    "22 * x0 + 21 * x1 + 28 * x2 + 9 * x3 <= 294",
    "26 * x1 + 11 * x2 >= 75",
    "26 * x1 + 6 * x3 >= 77",
    "3 * x0 + 26 * x1 + 6 * x3 >= 93",
    "21 * x1 + 28 * x2 <= 105",
    "28 * x2 + 9 * x3 <= 122",
    "22 * x0 + 9 * x3 <= 144",
    "22 * x0 + 28 * x2 <= 140",
    "22 * x0 + 28 * x2 + 9 * x3 <= 93",
    "22 * x0 + 21 * x1 + 28 * x2 + 9 * x3 <= 93",
    "3 * x0 + 26 * x1 <= 327",
    "3 * x0 + 6 * x3 <= 157",
    "3 * x0 + 11 * x2 <= 251",
    "11 * x2 + 6 * x3 <= 175",
    "3 * x0 + 26 * x1 + 6 * x3 <= 184",
    "3 * x0 + 26 * x1 + 11 * x2 + 6 * x3 <= 184"
  ]
}
```

```python
import gurobipy as gp

# Create a new model
m = gp.Model("optimization_problem")

# Create variables
scissors = m.addVar(vtype=gp.GRB.INTEGER, name="scissors")
smoke_detectors = m.addVar(vtype=gp.GRB.INTEGER, name="smoke_detectors")
hole_punches = m.addVar(vtype=gp.GRB.INTEGER, name="hole_punches")
mechanical_pencils = m.addVar(vtype=gp.GRB.INTEGER, name="mechanical_pencils")

# Set objective function
m.setObjective(5.78 * scissors + 4.79 * smoke_detectors + 1.44 * hole_punches + 8.87 * mechanical_pencils, gp.GRB.MAXIMIZE)

# Add constraints
m.addConstr(3 * scissors + 26 * smoke_detectors + 11 * hole_punches + 6 * mechanical_pencils <= 373, "c0")
m.addConstr(22 * scissors + 21 * smoke_detectors + 28 * hole_punches + 9 * mechanical_pencils <= 294, "c1")
m.addConstr(26 * smoke_detectors + 11 * hole_punches >= 75, "c2")
m.addConstr(26 * smoke_detectors + 6 * mechanical_pencils >= 77, "c3")
m.addConstr(3 * scissors + 26 * smoke_detectors + 6 * mechanical_pencils >= 93, "c4")
m.addConstr(21 * smoke_detectors + 28 * hole_punches <= 105, "c5")
m.addConstr(28 * hole_punches + 9 * mechanical_pencils <= 122, "c6")
m.addConstr(22 * scissors + 9 * mechanical_pencils <= 144, "c7")
m.addConstr(22 * scissors + 28 * hole_punches <= 140, "c8")
m.addConstr(22 * scissors + 28 * hole_punches + 9 * mechanical_pencils <= 93, "c9")
m.addConstr(22 * scissors + 21 * smoke_detectors + 28 * hole_punches + 9 * mechanical_pencils <= 93, "c10")
m.addConstr(3 * scissors + 26 * smoke_detectors <= 327, "c11")
m.addConstr(3 * scissors + 6 * mechanical_pencils <= 157, "c12")
m.addConstr(3 * scissors + 11 * hole_punches <= 251, "c13")
m.addConstr(11 * hole_punches + 6 * mechanical_pencils <= 175, "c14")
m.addConstr(3 * scissors + 26 * smoke_detectors + 6 * mechanical_pencils <= 184, "c15")
m.addConstr(3 * scissors + 26 * smoke_detectors + 11 * hole_punches + 6 * mechanical_pencils <= 184, "c16")


# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print('Obj: %g' % m.objVal)
    for v in m.getVars():
        print('%s %g' % (v.varName, v.x))
elif m.status == gp.GRB.INFEASIBLE:
    print("The model is infeasible.")
else:
    print("Optimization ended with status:", m.status)

```