{"id":"code-work-pm-python-nps-from-survey","audience":"product-managers","category":"coding","track":"coding","technique":"constraints","title":"Compute NPS from a survey export with plain Python","free":false,"task":"Write a Python script using only the standard library that reads survey.csv and prints one line exactly like NPS: 32 (n=118). Promoters score 9-10 and detractors 0-6. Rows with a blank score are skipped and don't count toward n. NPS is percent promoters minus percent detractors, rounded to a whole number. One code block, at most 20 lines, then under 25 words outside the code.","materialLabel":"Survey export, first rows (attached to your prompt automatically)","material":"survey.csv - in-app survey, October (exported from Pollen)\n\nresponse_id,user_id,score,comment,platform\n5001,77,10,Love the new board view,web\n5002,81,,,ios\n5003,12,6,Too many notifications,android\n5004,90,8,,web\n5005,33,9,Fast and simple,ios\n5006,41,0,Lost my data after update,web\n5007,52,,Skipped,ios\n\nNotes:\n- About 1 in 6 people close the survey without picking a score.\n- Scores are whole numbers from 0 to 10.\n- The comment column can contain commas inside quotes.\n- Last quarter's NPS was 28 according to the old dashboard.\n- Pollen's export always has this header row.\n- The product team reads the number in Monday's standup, so it needs to be one line they can paste into the team channel.\n- Comments are reviewed separately by the research team every Friday afternoon.","rules":[{"type":"codeBlocks","count":1},{"type":"maxCodeLines","max":20},{"type":"maxProseWords","max":25}],"mistakes":[{"title":"Not saying what to do with blanks","why":"The AI counts blank scores as zeros or as responses, which drags NPS down.","fix":"Add: \"Skip blank scores; they don't count in n.\"","checks":["r0"]},{"title":"Trusting the AI's definition","why":"The AI may count 7 or 8 somewhere or forget to round.","fix":"Add: \"Promoters 9-10, detractors 0-6, round to a whole number.\"","checks":["r1"]},{"title":"Not showing the output","why":"The AI prints a report with percentages and labels you don't need.","fix":"Add: \"Print one line exactly like NPS: 32 (n=118).\"","checks":["r2"]},{"title":"Getting a menu of options","why":"The AI likes to offer two or three versions of the script, so you're left to pick and test them yourself.","fix":"Add: \"Give one script only, in one code block, no alternatives.\"","checks":["codeBlocks","maxCodeLines"]},{"title":"Getting a tutorial","why":"By default the AI explains every part of the code at length, which you then have to scroll past.","fix":"Add: \"After the code, one line under 12 words. Nothing else.\"","checks":["maxProseWords"]}],"promptHints":[{"label":"Handles blank scores","patterns":["blank","empty","missing","skip"]},{"label":"Defines the groups","patterns":["9-10","0-6","promoter","detractor"]},{"label":"Shows the output line","patterns":["nps: \\d+","\\(n=","one line"]},{"label":"Rules out pandas","patterns":["standard library","no pandas","csv module"]},{"label":"Caps the code length","patterns":["\\d+\\s*lines","at most","under \\d+","short"]}],"hint":"Look at the empty scores in the export. Tell the AI what to do with them and show the exact line you want printed.","rubricLabels":["Uses only the standard library (csv module, no pandas) and skips rows with a blank score, so they aren't counted in n","Counts promoters as 9-10 and detractors as 0-6 (7 and 8 are neither) and computes 100 * (promoters - detractors) / n, rounded to a whole number","Prints exactly one line in the form NPS: 32 (n=118), with nothing else printed"]}