{"id":"loop-conditions-building-strings","slug":"building-strings","title":"Strings that grow round by round","text":"In the last module you built strings in a loop: start with the empty string `\"\"`, and add a piece in every round with `+=`. That works just as well in a loop with a condition. The pieces can be f-strings, which saves you the `str()` that a number would otherwise need:\n\n```python\ncountdown = \"\"\nnumber = 5\nwhile number > 0:\n    countdown += f\"{number}... \"\n    number -= 1\ncountdown += \"Go!\"\nprint(countdown)\n```\n\n```output\n5... 4... 3... 2... 1... Go!\n```\n\nWhy not print each piece right away? Because every `print` starts a new line, and here the whole countdown should be on one line. A string you've built can also wait: after the loop, the program can add more to it, as with `Go!` here, print it twice, or check it first.\n\n### Choosing the piece\n\nEach round can decide what to add. This loop draws a ruler, with a `|` at every fifth position and a dot everywhere else:\n\n```python\nruler = \"\"\nposition = 0\nwhile position <= 20:\n    if position % 5 == 0:\n        ruler += \"|\"\n    else:\n        ruler += \".\"\n    position += 1\nprint(ruler)\n```\n\n```output\n|....|....|....|....|\n```\n\nThe loop runs 21 rounds, for the positions 0 to 20, and in each round the `if` picks the piece. `%` gives the remainder of a division, so `position % 5 == 0` is true for 0, 5, 10, 15 and 20.\n\n### Separators: the first piece first\n\nIn the last module, an `if` kept a separator from being left over at the end: it added the separator only when the string wasn't empty any more. When you know the first piece before the loop starts, there's a simpler way. Put that piece in the string before the loop, and add every later piece with the separator in front of it:\n\n```python\nevens = \"2\"\nnumber = 4\nwhile number <= 10:\n    evens += f\", {number}\"\n    number += 2\nprint(f\"Even numbers: {evens}\")\n```\n\n```output\nEven numbers: 2, 4, 6, 8, 10\n```\n\nEvery comma sits between two numbers, and the loop needs no `if`. Note how the start value of `number` is 4, not 2: the 2 is already in the string.\n","task":"The program draws a progress bar of 10 places: a `#` for every task done and a `-` for every task still to do. Fill in the line that adds a `#` to the bar.\n\n```\nTasks done (out of 10): 4\n[####------]\n```\n","kind":"fill","seed":"done = int(input(\"Tasks done (out of 10): \"))\nbar = \"\"\nplace = 1\nwhile place <= 10:\n    if place <= done:\n        [[bar += \"#\"‖bar = bar + \"#\"]]\n    else:\n        bar += \"-\"\n    place += 1\nprint(f\"[{bar}]\")\n","solution":"done = int(input(\"Tasks done (out of 10): \"))\nbar = \"\"\nplace = 1\nwhile place <= 10:\n    if place <= done:\n        bar += \"#\"\n    else:\n        bar += \"-\"\n    place += 1\nprint(f\"[{bar}]\")\n","hints":["Look at the `else` branch: it adds a `-` to the end of `bar`. The blank does the same with a `#`.","Adding to the end of a string is `+=`, with the text to add in quotes."],"tests":[{"name":"Test 1","stdin":"4\n","expect":"Tasks done (out of 10): 4\n[####------]","hidden":false},{"name":"Test 2","stdin":"0\n","expect":"Tasks done (out of 10): 0\n[----------]","hidden":true},{"name":"Test 3","stdin":"10\n","expect":"Tasks done (out of 10): 10\n[##########]","hidden":true},{"name":"Test 4","stdin":"7\n","expect":"Tasks done (out of 10): 7\n[#######---]","hidden":true}],"require":[],"forbid":[],"more":[{"task":"Write a program that asks for a number and prints its first five multiples on one line, separated by a comma and a space, as below. Build the line in a loop.\n\n```\nNumber: 7\nMultiples of 7: 7, 14, 21, 28, 35\n```\n","kind":"code","seed":"number = int(input(\"Number: \"))\n","solution":"number = int(input(\"Number: \"))\nmultiples = f\"{number}\"\ntimes = 2\nwhile times <= 5:\n    multiples += f\", {number * times}\"\n    times += 1\nprint(f\"Multiples of {number}: {multiples}\")\n","hints":["The first multiple is the number itself. Put it in the string before the loop: `multiples = f\"{number}\"`.","Loop with a helper variable that goes from 2 to 5, and add `\", \"` and the next multiple to the string in every round.","The whole line is printed once, after the loop."],"tests":[{"name":"Test 1","stdin":"7\n","expect":"Number: 7\nMultiples of 7: 7, 14, 21, 28, 35","hidden":false},{"name":"Test 2","stdin":"3\n","expect":"Number: 3\nMultiples of 3: 3, 6, 9, 12, 15","hidden":true},{"name":"Test 3","stdin":"10\n","expect":"Number: 10\nMultiples of 10: 10, 20, 30, 40, 50","hidden":true},{"name":"Test 4","stdin":"1\n","expect":"Number: 1\nMultiples of 1: 1, 2, 3, 4, 5","hidden":true}],"require":[{"pattern":"\\bwhile\\b","message":"Build the line in a `while` loop instead of writing out the five multiples one by one."}],"forbid":[]},{"task":"Write a program that asks for prices with the prompt `Price: ` until the user types 0. Then it prints all the prices as one sum, with the total at the end, as below. You can assume the first price isn't 0.\n\n```\nPrice: 4\nPrice: 10\nPrice: 3\nPrice: 0\n4 + 10 + 3 = 17\n```\n","kind":"code","seed":"# Write your program here.\n","solution":"# Write your program here.\ntotal = 0\ncalculation = \"\"\nwhile True:\n    price = int(input(\"Price: \"))\n    if price == 0:\n        break\n    if calculation == \"\":\n        calculation = f\"{price}\"\n    else:\n        calculation += f\" + {price}\"\n    total += price\nprint(f\"{calculation} = {total}\")\n","hints":["You need two helper variables: the total, starting at 0, and the calculation as a string, starting empty.","Read the prices in a `while True` loop and `break` when the price is 0. Add every other price to the total.","For the string: if it's still empty, the price becomes its first piece. Otherwise add `\" + \"` and the price.","After the loop, print the string, `\" = \"` and the total."],"tests":[{"name":"Test 1","stdin":"4\n10\n3\n0\n","expect":"Price: 4\nPrice: 10\nPrice: 3\nPrice: 0\n4 + 10 + 3 = 17","hidden":false},{"name":"Test 2","stdin":"8\n0\n","expect":"Price: 8\nPrice: 0\n8 = 8","hidden":true},{"name":"Test 3","stdin":"1\n2\n3\n4\n5\n0\n","expect":"Price: 1\nPrice: 2\nPrice: 3\nPrice: 4\nPrice: 5\nPrice: 0\n1 + 2 + 3 + 4 + 5 = 15","hidden":true}],"require":[],"forbid":[]}]}