{"id":"recursion-smaller-pieces","slug":"smaller-pieces","title":"Fibonacci, strings and lists","text":"In the **Fibonacci sequence**, each number is the sum of the two numbers before it: 1, 1, 2, 3, 5, 8, 13 and so on. The definition has two base cases, the first two numbers, and its recursive case calls the function twice:\n\n```python\ndef fibonacci(n):\n    if n <= 2:\n        return 1\n    return fibonacci(n - 1) + fibonacci(n - 2)\n\n\nprint([fibonacci(n) for n in range(1, 11)])\n```\n\n```output\n[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]\n```\n\nYou can check it one number at a time: `fibonacci(3)` is `fibonacci(2) + fibonacci(1)`, which is 1 + 1 = 2. Then `fibonacci(4)` is `fibonacci(3) + fibonacci(2)`, which is 2 + 1 = 3, and so on.\n\nTwo calls in every call add up fast, though. `fibonacci(30)` makes more than a million calls, because it works out the same smaller numbers again and again. A loop that remembers the two latest numbers is much faster. Recursion is often the clearest way to write something down, not always the fastest way to run it.\n\n### Smaller strings and lists\n\nRecursion works whenever a problem has a smaller problem of the same kind inside it. A string without its first character is a shorter string, and a list without its first item is a shorter list. Slices give you those smaller pieces: `text[1:]` and `numbers[1:]`. The base case is often the empty string or the empty list.\n\nThe sum of a list is its first number plus the sum of the rest:\n\n```python\ndef list_sum(numbers):\n    if len(numbers) == 0:\n        return 0\n    return numbers[0] + list_sum(numbers[1:])\n\n\nprint(list_sum([4, 8, 15, 16]))\n```\n\n```output\n43\n```\n\nA string reversed is the rest of it reversed, with the first character at the end:\n\n```python\ndef reverse(text):\n    if text == \"\":\n        return \"\"\n    return reverse(text[1:]) + text[0]\n\n\nprint(reverse(\"stressed\"))\n```\n\n```output\ndesserts\n```\n\nA **palindrome** reads the same backwards, like \"racecar\". A string is a palindrome if its first and last characters are the same and the part between them, `text[1:-1]`, is a palindrome too. A string of 0 or 1 characters is always one:\n\n```python\ndef is_palindrome(text):\n    if len(text) <= 1:\n        return True\n    if text[0] != text[-1]:\n        return False\n    return is_palindrome(text[1:-1])\n\n\nprint(is_palindrome(\"racecar\"))\nprint(is_palindrome(\"rocket\"))\n```\n\n```output\nTrue\nFalse\n```\n\nThis one has two base cases: a short string gives `True`, and a mismatch gives `False` straight away, without looking at the rest.\n\nWhen you write a recursive function, ask yourself two questions. What is the simplest case, and what's its answer? And how does the answer for a slightly smaller problem help with the whole one?\n","task":"The function counts how many times a character appears in a text. Fill in the blank so the recursive call gets the rest of the text. The program should print:\n\n```\n3\n0\n```\n","kind":"fill","seed":"def count_char(text, char):\n    if text == \"\":\n        return 0\n    if text[0] == char:\n        return 1 + count_char([[text[1:]]], char)\n    return count_char(text[1:], char)\n\n\nprint(count_char(\"banana\", \"a\"))\nprint(count_char(\"kiwi\", \"x\"))\n","solution":"def count_char(text, char):\n    if text == \"\":\n        return 0\n    if text[0] == char:\n        return 1 + count_char(text[1:], char)\n    return count_char(text[1:], char)\n\n\nprint(count_char(\"banana\", \"a\"))\nprint(count_char(\"kiwi\", \"x\"))\n","hints":["The first character has been checked, so the recursive call should look at the rest of the text.","The text without its first character is the slice `text[1:]`."],"tests":[{"name":"Output","stdin":"","expect":"3\n0","hidden":false}],"require":[],"forbid":[],"more":[{"task":"Write a recursive function `largest(numbers)` that returns the greatest number in a list that has at least one number. Don't use `max` or a loop: the greatest number is either the first one or the greatest of the rest.\n\nFor example, this call:\n\n```python\nprint(largest([3, 9, 4]))\n```\n\nprints:\n\n```\n9\n```\n","kind":"code","seed":"def largest(numbers):\n    pass\n\n\nif __name__ == \"__main__\":\n    print(largest([3, 9, 4]))\n","solution":"def largest(numbers):\n    if len(numbers) == 1:\n        return numbers[0]\n    rest = largest(numbers[1:])\n    if numbers[0] > rest:\n        return numbers[0]\n    return rest\n\n\nif __name__ == \"__main__\":\n    print(largest([3, 9, 4]))\n","hints":["The base case is a list of one number: that number is the greatest.","Otherwise, find the greatest of the rest with `largest(numbers[1:])` and store it in a variable.","Then return whichever is greater, the first number or the greatest of the rest."],"tests":[{"name":"print(largest([3, 9, 4]))","stdin":"","call":"print(largest([3, 9, 4]))\n","expect":"9","hidden":false},{"name":"largest([-5, -2, -9])","stdin":"","call":"largest([-5, -2, -9])\n","expect":"-2","hidden":true,"returns":true},{"name":"largest([7])","stdin":"","call":"largest([7])\n","expect":"7","hidden":true,"returns":true},{"name":"largest([1, 2, 3, 10])","stdin":"","call":"largest([1, 2, 3, 10])\n","expect":"10","hidden":true,"returns":true}],"require":[{"pattern":"def largest\\b[^\\n]*\\n(?:[ \\t]*\\n|[ \\t]+[^\\n]*\\n)*?[ \\t]+[^\\n]*\\blargest\\s*\\(","message":"Make `largest` call itself inside its own body."}],"forbid":[{"pattern":"\\bmax\\s*\\(","message":"Find the greatest number with recursion, without `max`."},{"pattern":"\\b(?:while|for)\\b","message":"Use recursion instead of a loop."}]},{"task":"You climb a staircase taking either one or two steps at a time. A staircase of 3 steps can be climbed in 3 different ways: 1 + 1 + 1, 1 + 2 and 2 + 1. Write a recursive function `ways(steps)` that returns the number of different ways to climb a staircase of `steps` steps (at least 1).\n\nYour first move is either one step or two. After one step, `steps - 1` steps are left, and after two, `steps - 2`. So the number of ways is the ways for `steps - 1` plus the ways for `steps - 2`. A staircase of 1 step can be climbed in 1 way, and one of 2 steps in 2 ways.\n\nFor example, this call:\n\n```python\nprint(ways(3))\n```\n\nprints:\n\n```\n3\n```\n","kind":"code","seed":"def ways(steps):\n    pass\n\n\nif __name__ == \"__main__\":\n    print(ways(3))\n","solution":"def ways(steps):\n    if steps <= 2:\n        return steps\n    return ways(steps - 1) + ways(steps - 2)\n\n\nif __name__ == \"__main__\":\n    print(ways(3))\n","hints":["There are two base cases: 1 step gives 1 way and 2 steps give 2 ways.","For a longer staircase, add up two recursive calls: `ways(steps - 1) + ways(steps - 2)`.","Since the answer for 1 is 1 and for 2 is 2, both base cases can be `if steps <= 2: return steps`."],"tests":[{"name":"print(ways(3))","stdin":"","call":"print(ways(3))\n","expect":"3","hidden":false},{"name":"ways(4)","stdin":"","call":"ways(4)\n","expect":"5","hidden":true,"returns":true},{"name":"ways(1)","stdin":"","call":"ways(1)\n","expect":"1","hidden":true,"returns":true},{"name":"ways(10)","stdin":"","call":"ways(10)\n","expect":"89","hidden":true,"returns":true}],"require":[{"pattern":"def ways\\b[^\\n]*\\n(?:[ \\t]*\\n|[ \\t]+[^\\n]*\\n)*?[ \\t]+[^\\n]*\\bways\\s*\\(","message":"Make `ways` call itself inside its own body."}],"forbid":[]}]}