{"id":"simple-loops-debugging","slug":"debugging-loops","title":"Debugging loops with print","text":"In a loop the same lines run many times, with different values each time, so a bug can hide in any one of the iterations. Debugging prints are especially useful here: a `print` inside the loop shows what happens on every iteration.\n\nThis program should print the average of the numbers typed, but for 4 and 8 it prints 4.0 instead of 6.0:\n\n```python\ntotal = 0\ncount = 0\nwhile True:\n    number = int(input(\"Number (0 to finish): \"))\n    count += 1\n    if number == 0:\n        break\n    total += number\nprint(f\"Average: {total / count}\")\n```\n\n```input\n4\n8\n0\n```\n\n```output\nNumber (0 to finish): 4\nNumber (0 to finish): 8\nNumber (0 to finish): 0\nAverage: 4.0\n```\n\nAdd a debugging print at the end of the loop's block, and another one right after the loop. Give each value a label, so you can tell them apart:\n\n```python\ntotal = 0\ncount = 0\nwhile True:\n    number = int(input(\"Number (0 to finish): \"))\n    count += 1\n    if number == 0:\n        break\n    total += number\n    print(\"number:\", number, \"count:\", count, \"total:\", total)\nprint(\"after the loop, count:\", count, \"total:\", total)\nprint(f\"Average: {total / count}\")\n```\n\n```input\n4\n8\n0\n```\n\n```output\nNumber (0 to finish): 4\nnumber: 4 count: 1 total: 4\nNumber (0 to finish): 8\nnumber: 8 count: 2 total: 12\nNumber (0 to finish): 0\nafter the loop, count: 3 total: 12\nAverage: 4.0\n```\n\nThe values are right during the loop, but after it `count` is 3: the 0 that ends the input was counted too, because `count += 1` comes before the check. Moving that line below the `if` fixes the program. Then the debugging prints can go.\n\n### What a break skips\n\nA `break` ends the loop right where it stands, so on the last iteration the lines below it never run. Often that's just what you want: in the fixed program above, the 0 that ends the input must not be counted. But a check that comes too early makes the loop lose its last value. Suppose a loop should stop after the fifth score, but its `if count == 5:` with the `break` comes before the line that adds the score to the total. Then the fifth score is read and counted, but never added. A debugging print after the loop shows that the total is one value short, and following the last iteration line by line shows which line it never reached.\n\nWhen you debug a loop, keep the number of iterations small at first: two or three are usually enough to see the problem, and the printed lines are still easy to read.\n","task":"A hike has at most 4 stages. This program reads the length of each stage until the user types 0 or all 4 stages are in, and then prints the number of stages and the distance. With four stages, the distance comes out too short. Find the bug (debugging prints help) and fix it:\n\n```\nStage length in km (0 to stop): 3\nStage length in km (0 to stop): 5\nStage length in km (0 to stop): 2\nStage length in km (0 to stop): 4\nStages: 4, distance: 14 km\n```\n","kind":"code","seed":"stages = 0\ntotal = 0\nwhile True:\n    km = int(input(\"Stage length in km (0 to stop): \"))\n    if km == 0:\n        break\n    stages += 1\n    if stages == 4:\n        break\n    total += km\nprint(f\"Stages: {stages}, distance: {total} km\")\n","solution":"stages = 0\ntotal = 0\nwhile True:\n    km = int(input(\"Stage length in km (0 to stop): \"))\n    if km == 0:\n        break\n    stages += 1\n    total += km\n    if stages == 4:\n        break\nprint(f\"Stages: {stages}, distance: {total} km\")\n","hints":["Add `print(\"stages:\", stages, \"total:\", total)` as the last line of the loop's block and run the example. Which stage never shows up in the total?","On the fourth stage, `if stages == 4:` ends the loop before `total += km` runs, so that stage is counted but never added.","Every stage must be added before the loop can end. Move the line that adds it above the check."],"tests":[{"name":"Test 1","stdin":"3\n5\n2\n4\n","expect":"Stage length in km (0 to stop): 3\nStage length in km (0 to stop): 5\nStage length in km (0 to stop): 2\nStage length in km (0 to stop): 4\nStages: 4, distance: 14 km","hidden":false},{"name":"Test 2","stdin":"7\n0\n","expect":"Stage length in km (0 to stop): 7\nStage length in km (0 to stop): 0\nStages: 1, distance: 7 km","hidden":true},{"name":"Test 3","stdin":"0\n","expect":"Stage length in km (0 to stop): 0\nStages: 0, distance: 0 km","hidden":true},{"name":"Test 4","stdin":"1\n1\n1\n1\n","expect":"Stage length in km (0 to stop): 1\nStage length in km (0 to stop): 1\nStage length in km (0 to stop): 1\nStage length in km (0 to stop): 1\nStages: 4, distance: 4 km","hidden":true},{"name":"Test 5","stdin":"10\n20\n0\n","expect":"Stage length in km (0 to stop): 10\nStage length in km (0 to stop): 20\nStage length in km (0 to stop): 0\nStages: 2, distance: 30 km","hidden":true},{"name":"Test 6","stdin":"2\n2\n2\n2\n9\n","expect":"Stage length in km (0 to stop): 2\nStage length in km (0 to stop): 2\nStage length in km (0 to stop): 2\nStage length in km (0 to stop): 2\nStages: 4, distance: 8 km","hidden":true}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"x = 1\ntotal = 0\nwhile True:\n    total += x\n    print(\"x:\", x, \"total:\", total)\n    if total > 10:\n        break\n    x += 2\n","solution":"x = 1\ntotal = 0\nwhile True:\n    total += x\n    print(\"x:\", x, \"total:\", total)\n    if total > 10:\n        break\n    x += 2\n","hints":["Follow the two variables one iteration at a time: first `total` grows by `x`, then the line is printed.","`x` grows by 2 after the check: it is 1, then 3, then 5 and so on.","The loop stops after the first line where the total is over 10."],"tests":[{"name":"Output","stdin":"","expect":"x: 1 total: 1\nx: 3 total: 4\nx: 5 total: 9\nx: 7 total: 16","hidden":false}],"require":[],"forbid":[],"lines":["x: 1 total: 1","x: 3 total: 4","x: 5 total: 9","x: 7 total: 16"]},{"task":"This program should tell how long the longest word was, but it always says 0. Find the bug and fix it, so it prints:\n\n```\nWord (end to finish): sun\nWord (end to finish): banana\nWord (end to finish): kiwi\nWord (end to finish): end\nThe longest word has 6 characters.\n```\n","kind":"code","seed":"while True:\n    longest = 0\n    word = input(\"Word (end to finish): \")\n    if word == \"end\":\n        break\n    if len(word) > longest:\n        longest = len(word)\nprint(f\"The longest word has {longest} characters.\")\n","solution":"longest = 0\nwhile True:\n    word = input(\"Word (end to finish): \")\n    if word == \"end\":\n        break\n    if len(word) > longest:\n        longest = len(word)\nprint(f\"The longest word has {longest} characters.\")\n","hints":["Print `longest` at the start of each iteration. What is it every time?","The helper variable is set back to 0 on every iteration, the last one too.","Move `longest = 0` above the loop, so it's set only once."],"tests":[{"name":"Test 1","stdin":"sun\nbanana\nkiwi\nend\n","expect":"Word (end to finish): sun\nWord (end to finish): banana\nWord (end to finish): kiwi\nWord (end to finish): end\nThe longest word has 6 characters.","hidden":false},{"name":"Test 2","stdin":"strawberry\nfig\nend\n","expect":"Word (end to finish): strawberry\nWord (end to finish): fig\nWord (end to finish): end\nThe longest word has 10 characters.","hidden":true},{"name":"Test 3","stdin":"a\nbb\nccc\nend\n","expect":"Word (end to finish): a\nWord (end to finish): bb\nWord (end to finish): ccc\nWord (end to finish): end\nThe longest word has 3 characters.","hidden":true}],"require":[],"forbid":[]}]}