""" Authors: Peter Mawhorter Consulted: Date: 2024-11-19 Purpose: SOLUTIONS for extra fruitful recursion practice exercises. NOTE: This file does NOT contain optimism tests, nor is there a separate testing file. YOU are responsible for testing these functions, and you should fill in the docstrings with examples BEFORE you start to write the code for each. If you use 'doctest' style examples, the code at the end of the file will check them for you (see the comment down there). """ def sumOfEvens(n): """ Returns the sum of all even numbers up to and including n (assuming n is even, or up to n - 1 if n is odd). For example: >>> sumOfEvens(4) # 2 + 4 = 6 6 >>> sumOfEvens(3) 2 >>> sumOfEvens(8) 20 >>> sumOfEvens(9) 20 >>> sumOfEvens(10) 30 """ if n <= 0: return 0 elif n % 2 == 0: # Even so include it + sum rest return n + sumOfEvens(n - 2) else: # Must be odd so ignore it and sum from even below return sumOfEvens(n - 1) def isPalindrome(word): """ Returns True if the word is a palindrome and False if not. Counts the empty string as a palindrome. For example: >>> isPalindrome('racecar') True >>> isPalindrome('thought') False >>> isPalindrome('a') True >>> isPalindrome('') True """ if len(word) <= 1: # Empty string & single-letter words count return True else: # Length is at least 2: get first & last letters first = word[0] last = word[-1] # If they match, check whether the inside part is a palindrome if first == last: inside = word[1:-1] # get version without first & last letters return isPalindrome(inside) # this is a palindrome if that is else: return False # this is not a palindrome: outers don't match. def onlyLarger(numbers, threshold): """ Returns a new list of numbers that includes only the numbers in the given list which are strictly greater than the given threshold. >>> onlyLarger([1, 2, 3, 4, 5], 3) [4, 5] >>> onlyLarger([47, 2, 6, 18, 4, -4, -5], 5) [47, 6, 18] >>> onlyLarger([], 0) [] """ if len(numbers) == 0: return [] else: # Split into first number & rest list first = numbers[0] rest = numbers[1:] # Use recursion to filter rest of list restAbove = onlyLarger(rest, threshold) # Now add or don't add the first one if first > threshold: # Put it in a list + then add to combine lists return [first] + restAbove else: return restAbove def logarithm(n, base): """ Returns the (integer) logarithm of n in the given base, which is the number of times that n can be divided by the base before the result is less than 1 (we won't worry about negative values and will just return 0 for any numbers that are already less than 1). For example, if n is 10 and the base is 2, then the result will be 3, because: 1. 10 / 2 is 5 2. 5 / 2 is 2.5, and 3. 2.5 / 2 is 1.25 ...but 1.25 / 2 is less than 1. We'll assume that the base is a positive integer greater than 1. More examples: >>> logarithm(10, 3) 2 >>> logarithm(100, 10) 2 >>> logarithm(32, 2) 5 >>> logarithm(4.9, 5) # can't divide even once and remain > 1 0 >>> logarithm(0.5, 5) # number less than 1 results in a 0 0 """ if n < base: return 0 else: dividedOnce = n / base return 1 + logarithm(dividedOnce, base) def countSentences(text): """ Returns the number of sentence-ending punctuation marks ('.', '!', or '?') within the given piece of text. Doesn't always work perfectly. Hint: you do NOT have to break the text up into words. For example: >>> countSentences('One sentence.') 1 >>> countSentences('one phrase') 0 >>> countSentences('Ellipsis...') 3 >>> countSentences('Lazy dog. Sphynx vow. Boxing wizards.') 3 >>> countSentences('Really? Wow!') 2 """ if len(text) == 0: return 0 else: first = text[0] restCount = countSentences(text[1:]) if first == '!' or first == '.' or first == '?': return 1 + restCount else: return restCount # These lines will test any 'doctest' examples you include in docstrings # above. A 'doctest' example starts with '>>>' and some code, and then # shows the result for that code on the next line down. For example: # >>> sumOfEvens(3) # 2 # This would be a valid doctest for sumOfEvens (although it needs to # appear in a function's docstring, not in a comment). # If any of your doctests are incorrect, these lines of code will print # out a report on which tests failed and why. If your doctests all pass, # this will print 'All tests passed.' import doctest fails, tests = doctest.testmod() if tests == 0: print("No doctest examples provided.") elif fails == 0: print("All tests passed.") else: print(fails, "tests failed.")