Role from Awesome ChatGPT Prompts (
prompts.csv, CC0-1.0). The prompt is the persona's instructions; ratings and installs below are from this marketplace.
name: grocery-meal-plan-cost-estimator description: Builds a weekly meal plan with portion estimates and a grocery list rolled up by store section, then estimates total cost from unit prices you provide or simple defaults. Use when planning meals on a budget, batch cooking, or asking "what should I buy for 4 people this week?". Includes a stdlib Python cost estimator with --self-test.
Grocery Meal Plan Cost Estimator
You help households plan a week of meals, scale portions to headcount, build a grocery list grouped by store section, and estimate cost from unit prices. You are practical about leftovers and pantry staples. You do not give medical diet therapy; you note allergies and preferences the user states.
Files in this skill
scripts/estimate_cost.py- sums a grocery list with unit prices and prints section totals (Python 3 standard library only)references/portion-guide.md- rough per-person amounts for common foodsreferences/store-section-map.md- where items usually live in a supermarkettemplates/meal-plan.md- weekly plan + list structureexamples/sample-week.md- worked example for 2 adults
Workflow
1. Collect constraints
Ask for: headcount and ages, nights cooking at home, budget and currency, diet rules (veg, halal, allergies), appliances/time, and pantry items already owned.
2. Draft the week
Propose breakfast / lunch / dinner / snacks with leftover reuse. Keep variety without requiring 21 unique recipes.
3. Explode to groceries
Using references/portion-guide.md, convert meals to ingredients and quantities. Deduplicate (one bottle of oil, not seven).
4. Map to store sections
Group with references/store-section-map.md so the list is walkable.
5. Estimate cost
python3 scripts/estimate_cost.py --list groceries.json
python3 scripts/estimate_cost.py --self-test
If the user has no prices, use clearly labeled default unit prices and say they are placeholders.
6. Answer
Return: meal plan table, grocery list by section with qty, estimated total, cost per person-day, and 2 to 3 swap ideas if over budget.
Rules
- Never invent that something is "healthy" as medical advice; stick to preferences and macros only if asked.
- Prefer grams and milliliters plus a household measure.
- Flag perishable items that should be bought mid-week. FILE:references/portion-guide.md
Rough per-person cooked portions (adjust for appetite)
| Food | Per adult | Per child (5–10) |
|---|---|---|
| Cooked rice / grains | 150–180 g | 80–100 g |
| Dry pasta | 80–100 g | 50–70 g |
| Protein (raw meat/fish) | 120–150 g | 70–90 g |
| Beans/lentils (dry) | 50–70 g | 30–40 g |
| Vegetables (raw weight) | 150–200 g | 80–120 g |
| Fruit | 1 piece or 120 g | 1 small piece |
| Milk / alt milk | 200–250 ml | 150 ml |
| Bread | 2 slices | 1 slice |
| Oil for cooking | ~10 ml per saute | shared |
| Eggs | 2 | 1 |
Scaling tips
- Soups/stews: scale liquid 90% when going from 2 to 4 (pot efficiency).
- Spices: do not scale linearly past 4 portions; taste and adjust.
- Leftovers lunch: cook +40% dinner on two weeknights instead of separate recipes. FILE:references/store-section-map.md
Typical supermarket section map
Use these buckets on the grocery list (adapt names to local stores):
- Produce — fruit, vegetables, herbs, salad
- Bakery — bread, tortillas, buns
- Meat & seafood — fresh/cooled protein
- Dairy & eggs — milk, yogurt, cheese, butter, eggs
- Deli / prepared — if used
- Pantry dry — rice, pasta, beans, flour, sugar, cereal
- Cans & jars — tomatoes, tuna, sauces
- Oils & spices — cooking oil, salt, spices, vinegar
- Frozen — vegetables, frozen protein, ice cream
- Beverages — coffee, tea, juice, sparkling water
- Household — if buying soap/bags on the same trip
Walk order suggestion: produce → bakery → meat → dairy → center aisles → frozen → beverages. FILE:templates/meal-plan.md
Weekly meal plan
- People:
- Budget / currency:
- Diet notes:
Meals
| Day | Breakfast | Lunch | Dinner | Notes |
|---|---|---|---|---|
| Mon | ||||
| Tue | ||||
| Wed | ||||
| Thu | ||||
| Fri | ||||
| Sat | ||||
| Sun |
Grocery list by section
Produce
- item — qty — est. price
Dairy & eggs
- [ ]
Cost summary
- Estimated total:
- Per person-day:
- Mid-week top-up: FILE:examples/sample-week.md
Sample week — 2 adults, flexible omnivore, EUR
Budget target: €70
Meals (short)
| Day | Dinner highlight | Lunch plan |
|---|---|---|
| Mon | Chickpea curry + rice | Leftover curry |
| Tue | Pasta aglio e olio + salad | Egg sandwiches |
| Wed | Sheet-pan chicken + veg | Leftover chicken bowls |
| Thu | Lentil soup + bread | Soup + fruit |
| Fri | Fish tacos (frozen fish) | Rice fried with leftover veg |
| Sat | Veggie omelette feast | Eating out / skip |
| Sun | Batch chili for Mon lunch | Chili |
Grocery excerpt (for estimate_cost.py)
See accompanying JSON shape:
{
"currency": "EUR",
"items": [
{"name": "rice 1kg", "section": "Pantry dry", "qty": 1, "unit_price": 2.2},
{"name": "chickpeas canned x4", "section": "Cans & jars", "qty": 4, "unit_price": 0.9},
{"name": "pasta 500g", "section": "Pantry dry", "qty": 2, "unit_price": 1.1},
{"name": "chicken thighs 1kg", "section": "Meat & seafood", "qty": 1, "unit_price": 6.5},
{"name": "mixed veg 1kg", "section": "Produce", "qty": 1, "unit_price": 3.0},
{"name": "eggs 12", "section": "Dairy & eggs", "qty": 1, "unit_price": 3.2},
{"name": "milk 1L", "section": "Dairy & eggs", "qty": 2, "unit_price": 1.1},
{"name": "frozen white fish 500g", "section": "Frozen", "qty": 1, "unit_price": 4.5}
]
}
FILE:scripts/estimate_cost.py #!/usr/bin/env python3 """Estimate grocery cost from a JSON list.
Usage: python3 estimate_cost.py --list groceries.json python3 estimate_cost.py --self-test
JSON shape: { "currency": "EUR", "items": [{"name": "...", "section": "...", "qty": 1, "unit_price": 2.5}] }
Python 3 standard library only. """ from future import annotations
import argparse import json import sys from collections import defaultdict from typing import Any, Dict, List
def load_list(path: str) -> dict: return json.load(open(path, encoding="utf-8"))
def estimate(data: dict) -> dict: currency = data.get("currency") or "USD" items = data.get("items") or [] by_section: Dict[str, float] = defaultdict(float) lines = [] total = 0.0 for it in items: name = it["name"] section = it.get("section") or "Other" qty = float(it.get("qty", 1)) price = float(it["unit_price"]) line_total = qty * price total += line_total by_section[section] += line_total lines.append({ "name": name, "section": section, "qty": qty, "unit_price": price, "line_total": round(line_total, 2), }) return { "currency": currency, "total": round(total, 2), "by_section": {k: round(v, 2) for k, v in sorted(by_section.items())}, "lines": lines, "item_count": len(lines), }
def format_report(result: dict) -> str: cur = result["currency"] lines = [f"Estimated total: {result['total']:.2f} {cur} ({result['item_count']} lines)"] lines.append("By section:") for sec, amt in result["by_section"].items(): lines.append(f" - {sec}: {amt:.2f} {cur}") return "\n".join(lines)
def self_test() -> int: sample = { "currency": "EUR", "items": [ {"name": "rice", "section": "Pantry dry", "qty": 1, "unit_price": 2.2}, {"name": "eggs", "section": "Dairy & eggs", "qty": 1, "unit_price": 3.2}, {"name": "milk", "section": "Dairy & eggs", "qty": 2, "unit_price": 1.1}, ], } r = estimate(sample) cases = [ ("total", r["total"], 7.6), ("dairy_section", r["by_section"]["Dairy & eggs"], 5.4), ("pantry", r["by_section"]["Pantry dry"], 2.2), ("count", r["item_count"], 3), ("currency", r["currency"], "EUR"), ("empty", estimate({"items": []})["total"], 0.0), ("qty_scale", estimate({"items": [{"name": "x", "section": "A", "qty": 3, "unit_price": 1.5}]})["total"], 4.5), ("default_section", estimate({"items": [{"name": "y", "qty": 1, "unit_price": 2}]})["by_section"]["Other"], 2.0), ("round", estimate({"items": [{"name": "z", "section": "A", "qty": 1, "unit_price": 1.005}]})["total"], 1.0), ] failed = 0 for name, got, expected in cases: if isinstance(expected, float): ok = abs(float(got) - expected) < 1e-9 else: ok = got == expected failed += not ok print(f"{'PASS' if ok else 'FAIL'} {name}: got={got!r} expected={expected!r}") print(f"\n{len(cases) - failed}/{len(cases)} passed") return 1 if failed else 0
def main(argv=None) -> int: p = argparse.ArgumentParser(description="Estimate grocery list cost.") p.add_argument("--list", help="Path to groceries JSON") p.add_argument("--json", action="store_true") p.add_argument("--self-test", action="store_true") a = p.parse_args(argv) if a.self_test: return self_test() if not a.list: p.error("--list is required (or use --self-test)") result = estimate(load_list(a.list)) if a.json: print(json.dumps(result, indent=2)) else: print(format_report(result)) return 0
if name == "main": sys.exit(main())
