30 days of prices, a sparkline and a buy-or-wait verdict.
/build/project-price-drop-alert with the starter and the rubric already in it.Analyse a month of a product's prices: the lowest day, how often it fell, a one-line chart, the days it hit your target and whether to buy today.
Every list problem you will meet (min, index, comparing neighbours, filtering) shows up here, on data you actually care about before a sale.
You can analyse a list of numbers with loops and comprehensions and turn it into a decision.
Each step is one function in price_alert.py. In the workspace, press Check next to a step: it runs your file and tells you exactly what is still wrong. Step 1 is free; the rest are part of Pro or your 7-day free trial.
Build against this exact list — it is the spec your published project is judged on.
Copy this into a new file — or open it in a workspace as price_alert.py. The TODO parts are yours to fill.
"""
Price-drop alert.
Reads 30 days of a phone's price, draws a sparkline, finds the best day
and says whether to buy today. Fill in one function per step, press Run,
then press "Check" on that step.
"""
TARGET = 21500 # buy when the price is at or below this (₹)
# One price per day for the last 30 days (sample data)
PRICES = [24999, 24999, 24499, 24999, 23999, 23999, 24499, 22999, 22999, 23499,
23999, 23999, 22499, 22999, 23499, 21999, 21999, 22999, 23499, 23999,
22999, 21499, 21999, 22499, 22999, 20999, 21499, 21999, 22499, 21999]
def lowest(prices: list[int]) -> tuple[int, int]:
# TODO: return (lowest price, the day it happened). Days count from 1,
# so the first price is day 1. Hint: min() and list.index().
raise NotImplementedError("step 1, lowest(): the lowest price and its day")
def drop_days(prices: list[int]) -> list[int]:
# TODO: the days (counting from 1) when the price was lower than the
# day before. Day 1 has no day before it, so it is never a drop.
raise NotImplementedError("step 2, drop_days(): days the price fell")
def sparkline(prices: list[int]) -> str:
# TODO: one character per price from "▁▂▃▄▅▆▇█": the lowest price gets
# ▁, the highest █, the rest in between.
# level = round((price - low) / (high - low) * 7)
raise NotImplementedError("step 3, sparkline(): a chart in one line of text")
def days_at_or_below(prices: list[int], target: int) -> list[int]:
# TODO: the days (from 1) when the price was at or below target.
raise NotImplementedError("step 4, days_at_or_below(): days you could have bought")
def verdict(prices: list[int], target: int) -> str:
# TODO: look at today's price (the last one).
# At or below target: "BUY: ₹21,999 is at or below your ₹22,000"
# Otherwise: "WAIT: ₹499 above your ₹21,500"
raise NotImplementedError("step 5, verdict(): buy today or wait")
def main() -> None:
low, day = lowest(PRICES)
print(f"Lowest ₹{low:,} on day {day}")
print(f"Fell on {len(drop_days(PRICES))} of 30 days")
print(f"30 days {sparkline(PRICES)}")
hits = days_at_or_below(PRICES, TARGET)
print(f"At or below ₹{TARGET:,} on days {hits}")
result = verdict(PRICES, TARGET)
# TODO: print result as the last line.
raise NotImplementedError("step 6, main(): print the verdict")
if __name__ == "__main__":
try:
main()
except NotImplementedError as todo:
# A fresh starter is SUPPOSED to stop here. Say which step is next
# instead of printing a traceback that looks like a bug.
print(f"Not built yet: {todo}")
print("Write that function, then press Run again. Each step you finish moves this message forward.")
price_alert.py and a README.md holding all 5 rubric items as a checklist.pyrun.in/u/<handle>/w/project-price-drop-alert.pyrun.in/u/<handle> portfolio page.Your workspace saves to this browser only. Sign in to keep it across devices and to publish it.
Flip the workspace to Public and paste its URL below, or push the file to a GitHub gist or repo.
A published PyRun workspace URL (pyrun.in/u/<handle>/w/project-price-drop-alert) works as the public URL too.