```json
{
  "sym_variables": [
    ("x0", "ham sandwiches"),
    ("x1", "peanutbutter sandwiches"),
    ("x2", "fruit salads"),
    ("x3", "bowls of cereal")
  ],
  "objective_function": "3*x0 + 4*x1 + 9*x2 + 3*x3",
  "constraints": [
    "6*x0 + 5*x2 >= 18",
    "6*x0 + 6*x3 >= 31",
    "1*x1 + 3*x2 >= 24",
    "1*x1 + 3*x2 + 1*x3 >= 23",
    "3*x0 + 1*x1 + 3*x2 >= 23",
    "1*x1 + 3*x2 + 1*x3 >= 13",
    "3*x0 + 1*x1 + 3*x2 >= 13",
    "4*x0 + 7*x2 >= 8",
    "6*x0 + 6*x3 <= 78",
    "6*x0 + 8*x1 + 5*x2 <= 66",
    "6*x0 + 8*x1 + 6*x3 <= 118",
    "6*x0 + 8*x1 + 5*x2 + 6*x3 <= 118",
    "8*x0 + 6*x2 <= 47",
    "8*x0 + 1*x1 + 6*x2 + 4*x3 <= 47",
    "3*x0 + 1*x1 <= 61",
    "1*x1 + 1*x3 <= 42",
    "3*x0 + 3*x2 <= 34",
    "3*x0 + 3*x2 + 1*x3 <= 93",
    "3*x0 + 1*x1 + 1*x3 <= 39",
    "3*x0 + 1*x1 + 3*x2 <= 72",
    "1*x1 + 3*x2 + 1*x3 <= 75",
    "3*x0 + 1*x1 + 3*x2 + 1*x3 <= 75",
    "4*x0 + 8*x3 <= 50",
    "4*x0 + 7*x2 <= 32",
    "4*x0 + 8*x1 <= 52",
    "8*x1 + 8*x3 <= 23",
    "4*x0 + 8*x1 + 8*x3 <= 53",
    "8*x1 + 7*x2 + 8*x3 <= 35",
    "4*x0 + 8*x1 + 7*x2 + 8*x3 <= 35",
    "6*x0 + 8*x1 + 5*x2 + 6*x3 <= 124",  // iron
    "8*x0 + 1*x1 + 6*x2 + 4*x3 <= 131",  // cost
    "3*x0 + 1*x1 + 3*x2 + 1*x3 <= 102",  // fiber
    "4*x0 + 8*x1 + 7*x2 + 8*x3 <= 61",  // tastiness
    "x0 >= 0",
    "x1 >= 0",
    "x2 >= 0",
    "x3 >= 0"
  ]
}
```

```python
import gurobipy as gp

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

# Create variables
ham_sandwiches = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="ham_sandwiches")
peanutbutter_sandwiches = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="peanutbutter_sandwiches")
fruit_salads = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="fruit_salads")
bowls_of_cereal = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="bowls_of_cereal")


# Set objective function
m.setObjective(3 * ham_sandwiches + 4 * peanutbutter_sandwiches + 9 * fruit_salads + 3 * bowls_of_cereal, gp.GRB.MAXIMIZE)

# Add constraints
m.addConstr(6 * ham_sandwiches + 5 * fruit_salads >= 18)
m.addConstr(6 * ham_sandwiches + 6 * bowls_of_cereal >= 31)
m.addConstr(peanutbutter_sandwiches + 3 * fruit_salads >= 24)
m.addConstr(peanutbutter_sandwiches + 3 * fruit_salads + bowls_of_cereal >= 23)
m.addConstr(3 * ham_sandwiches + peanutbutter_sandwiches + 3 * fruit_salads >= 23)
m.addConstr(peanutbutter_sandwiches + 3 * fruit_salads + bowls_of_cereal >= 13)
m.addConstr(3 * ham_sandwiches + peanutbutter_sandwiches + 3 * fruit_salads >= 13)
m.addConstr(4 * ham_sandwiches + 7 * fruit_salads >= 8)
m.addConstr(6 * ham_sandwiches + 6 * bowls_of_cereal <= 78)
m.addConstr(6 * ham_sandwiches + 8 * peanutbutter_sandwiches + 5 * fruit_salads <= 66)
m.addConstr(6 * ham_sandwiches + 8 * peanutbutter_sandwiches + 6 * bowls_of_cereal <= 118)
m.addConstr(6 * ham_sandwiches + 8 * peanutbutter_sandwiches + 5 * fruit_salads + 6 * bowls_of_cereal <= 118)
m.addConstr(8 * ham_sandwiches + 6 * fruit_salads <= 47)
m.addConstr(8 * ham_sandwiches + peanutbutter_sandwiches + 6 * fruit_salads + 4 * bowls_of_cereal <= 47)
m.addConstr(3 * ham_sandwiches + peanutbutter_sandwiches <= 61)
m.addConstr(peanutbutter_sandwiches + bowls_of_cereal <= 42)
m.addConstr(3 * ham_sandwiches + 3 * fruit_salads <= 34)
m.addConstr(3 * ham_sandwiches + 3 * fruit_salads + bowls_of_cereal <= 93)
m.addConstr(3 * ham_sandwiches + peanutbutter_sandwiches + bowls_of_cereal <= 39)
m.addConstr(3 * ham_sandwiches + peanutbutter_sandwiches + 3 * fruit_salads <= 72)
m.addConstr(peanutbutter_sandwiches + 3 * fruit_salads + bowls_of_cereal <= 75)
m.addConstr(3 * ham_sandwiches + peanutbutter_sandwiches + 3 * fruit_salads + bowls_of_cereal <= 75)
m.addConstr(4 * ham_sandwiches + 8 * bowls_of_cereal <= 50)
m.addConstr(4 * ham_sandwiches + 7 * fruit_salads <= 32)
m.addConstr(4 * ham_sandwiches + 8 * peanutbutter_sandwiches <= 52)
m.addConstr(8 * peanutbutter_sandwiches + 8 * bowls_of_cereal <= 23)
m.addConstr(4 * ham_sandwiches + 8 * peanutbutter_sandwiches + 8 * bowls_of_cereal <= 53)
m.addConstr(8 * peanutbutter_sandwiches + 7 * fruit_salads + 8 * bowls_of_cereal <= 35)
m.addConstr(4 * ham_sandwiches + 8 * peanutbutter_sandwiches + 7 * fruit_salads + 8 * bowls_of_cereal <= 35)


# Resource Constraints
m.addConstr(6 * ham_sandwiches + 8 * peanutbutter_sandwiches + 5 * fruit_salads + 6 * bowls_of_cereal <= 124) # iron
m.addConstr(8 * ham_sandwiches + peanutbutter_sandwiches + 6 * fruit_salads + 4 * bowls_of_cereal <= 131) # cost
m.addConstr(3 * ham_sandwiches + peanutbutter_sandwiches + 3 * fruit_salads + bowls_of_cereal <= 102) # fiber
m.addConstr(4 * ham_sandwiches + 8 * peanutbutter_sandwiches + 7 * fruit_salads + 8 * bowls_of_cereal <= 61) # tastiness


# 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 problem is infeasible.")
else:
    print("The problem could not be solved to optimality.")

```