text: """
  This module lets you practice two forms of the ACCUMULATOR pattern:
    -- SUMMING
    -- COUNTING
  where the accumulation is done via ITERATING (i.e., looping)
  through a SEQUENCE.
  
  It also demonstrates using an ORACLE and/or PROBABILITY THEORY
  in testing and BOUNDARY (EDGE) TESTING.
  
  Authors: David Mutchler, Vibha Alangar, Matt Boutell, Dave Fisher,
           Mark Hays, Amanda Stouder, Aaron Wilkin, their colleagues,
           and Jonah Egertson.
  """  # DONE: 1. PUT YOUR NAME IN THE ABOVE LINE.
  
  import random
  import builtins  # Never necessary, but here to make a point about SUM
  import math
  
  
  def main():
      """ Calls the   TEST   functions in this module. """
      run_test_sum_sequence()
      run_test_count_items_bigger_than()
      run_test_count_positive_sines()
      run_test_sum_first_n()
  
  
  def run_test_sum_sequence():
      """ Tests the   sum_sequence   function. """
      print()
      print('--------------------------------------------------')
      print('Testing the   sum_sequence   function:')
      print('--------------------------------------------------')
  
      # -------------------------------------------------------------------------
      # DONE: 2. READ the COMMENTS and CODE in this function,
      #  asking questions as needed.
      #
      #   When you believe that you understand:
      #     -- What an ORACLE is
      #     -- How one can generate and use RANDOM test cases
      #     -- How one can test using PROBABILITY THEORY
      #   then:
      #      change the above TO DO to DONE.
      # -------------------------------------------------------------------------
  
      # -------------------------------------------------------------------------
      # Here (below) are examples of using an ORACLE for testing,
      # that is, using a separate way of gaining the correct tests as if
      # by "magic". The oracle here is the built-in    sum    function.
      # We provided two tests that use that oracle.
      #
      # BTW, google for  "Oracle of Delphi" if you are curious about
      # why we call such tests "oracles".
      # -------------------------------------------------------------------------
  
      # -------------------------------------------------------------------------
      # Test 1 (using an ORACLE to computer the expected answer):
      # -------------------------------------------------------------------------
      sequence1 = [48, -10, 100, 9939309808, 433443080, -45634930]
  
      oracle_answer = builtins.sum(sequence1)
      actual_answer = sum_sequence(sequence1)
  
      print()
      print('Test 1: Using the sequence:')
      print('   ', sequence1)
      print('  Expected (oracle) result: ', oracle_answer)
      print('  Actual result:            ', actual_answer)
  
      # -------------------------------------------------------------------------
      # Test 2 (using an ORACLE to computer the expected answer):
      # -------------------------------------------------------------------------
      sequence2 = [48, 180, -475, 205, 88]
  
      oracle_answer = builtins.sum(sequence2)
      actual_answer = sum_sequence(sequence2)
  
      print()
      print('Test 2: Using the sequence:')
      print('   ', sequence2)
      print('  Expected (oracle) result: ', oracle_answer)
      print('  Actual result:            ', actual_answer)
  
      # -------------------------------------------------------------------------
      # Test 3 (using an ORACLE to compute the expected answer):
      #
      #   This test uses a RANDOMLY generated sequence,
      #   so every time you run the program it does a DIFFERENT test!
      #   So this code snippet can be used to do MANY tests!
      # -------------------------------------------------------------------------
  
      # The next few lines make a sequence of 10,000 RANDOM numbers:
      sequence3 = []
      for _ in range(10000):
          sequence3.append(random.randrange(-10, 11))
  
      oracle_answer = builtins.sum(sequence3)
      actual_answer = sum_sequence(sequence3)
  
      print()
      print('Test 3: Using the following RANDOMLY generated sequence:')
      print('   ', sequence3)
      print('  Expected (oracle) result: ', oracle_answer)
      print('  Actual result:            ', actual_answer)
  
      # -------------------------------------------------------------------------
      # Tests 4 and 5:  using a KNOWN answer
      #   (here, ones easily computed by hand).]
      #
      #   Test 5 is an example of BOUNDARY (aka EDGE) testing, which is:
      #
      #       Where test cases are generated using the EXTREMES of the
      #       input domain, e.g. maximum, minimum, just inside/outside
      #       boundaries, error values. It focuses] on "corner cases".
      #
      #   The above quotation is a slight paraphrase from the Wikipedia
      #   article at https://en.wikipedia.org/wiki/Boundary_testing.
      #
      # -------------------------------------------------------------------------
  
      # Test 4:
      sequence4 = [48, -10]
  
      known_answer = 38
      actual_answer = sum_sequence(sequence4)
  
      print()
      print('Test 4: Using the sequence:')
      print('   ', sequence4)
      print('  Expected (known) result: ', known_answer)
      print('  Actual result:           ', actual_answer)
  
      # Test 5:
      sequence5 = []
  
      known_answer = 0
      actual_answer = sum_sequence(sequence5)
  
      print()
      print('Test 5: Using the sequence:')
      print('   ', sequence5)
      print('  Expected (known) result: ', known_answer)
      print('  Actual result:           ', actual_answer)
  
      # -------------------------------------------------------------------------
      # Test 6:  (Don't worry if you don't follow this example fully.)
      #
      #   Like Test 3, this test uses a RANDOMLY generated sequence.
      #
      #   But unlike Test 3 (which used an ORACLE),
      #   THIS example uses PROBABILITY THEORY to predict (approximately)
      #   the expected value.
      #
      #   It relies on what is called the
      #      Law of Large Numbers
      #   which, as applied here says:
      #      If you compute the average of a lot of numbers with each
      #      number drawn RANDOMLY from -10 to 10 (inclusive),
      #      the result should be close to the average of the numbers
      #      from -10 to 10 (inclusive) [which is 0].
      #
      #   See https://en.wikipedia.org/wiki/Law_of_large_numbers
      #   for a not-too-clear explanation of the Law of Large Numbers.
      # -------------------------------------------------------------------------
  
      # Skips this test if  sum_sequence  has not yet been implemented:
      if sum_sequence([1, 2, 3]) == None:
          return
  
      sequence6 = []  # Next lines make a sequence of 10000 RANDOM numbers
      for _ in range(10000):
          sequence6.append(random.randrange(-10, 11))
  
      expected_sum_from_probability_theory = 0
      expected_average_from_probability_theory = 0
      actual_sum = sum_sequence(sequence6)
      actual_average = sum_sequence(sequence6) / 10000
  
      print()
      print('Test 6: Using the following RANDOMLY generated sequence:')
      print('   ', sequence6)
  
      print('  Expected results (from PROBABILITY THEORY):')
      print('    Sum:     ', expected_sum_from_probability_theory)
      print('    Average: ', expected_average_from_probability_theory)
      print('  ACTUAL results (should be CLOSE to the above)')
      print('    Sum:     ', actual_sum)
      print('    Average: ', actual_average)
      print('  where "close" for the sum means absolute value < about 600')
  
  
  def sum_sequence(sequence):
      """
      What comes in:  A sequence of integers.
      What goes out: Returns the sum of the numbers in the given sequence.
      Side effects: None.
      Examples:
        sum_sequence([8, 13, 7, -5])  returns  23
        sum_sequence([48, -10])       returns  38
        sum_sequence([])              returns  0
      Type hints:
        :type sequence: list or tuple (of integers)
      """
      # -------------------------------------------------------------------------
      # DONE: 3. Implement and test this function.
      #          Tests have been written for you (above).
      #
      # RESTRICTION:
      #    You may NOT use the built-in  sum   function
      #    in IMPLEMENTING this function.
      #      -- The TESTING code above does use   built_ins.sum
      #         as an ORACLE in TESTING this function, however.
      # -------------------------------------------------------------------------
      sum = 0
      for k in range(len(sequence)):
          sum = sum + sequence[k]
      return sum
  
  
  def run_test_count_items_bigger_than():
      """ Tests the   count_items_bigger_than   function. """
      # -------------------------------------------------------------------------
      # DONE: 4. Implement this TEST function.
      #   It TESTS the  count_items_bigger_than  function defined below.
      #   Include at least ** 2 ** ADDITIONAL tests.
      #
      #   As usual, include both EXPECTED and ACTUAL results in your test
      #   and compute the latter BY HAND (not by running your program).
      # -------------------------------------------------------------------------
      print()
      print('--------------------------------------------------')
      print('Testing the   count_items_bigger_than   function:')
      print('--------------------------------------------------')
  
      # Test 1:
      sequence = [45, 84, 32, 70, -10, 40]
      threshold = 45
      expected = 2
      actual = count_items_bigger_than(sequence, threshold)
      print()
      print('Test 1 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 2:
      sequence = [45, 84, 32, 70, -10, 40]
      threshold = 0
      expected = 5
      actual = count_items_bigger_than(sequence, threshold)
      print()
      print('Test 2 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 3:
      sequence = [45, 84, 32, 70, -10, 40]
      threshold = -10
      expected = 5
      actual = count_items_bigger_than(sequence, threshold)
      print()
      print('Test 3 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 4:
      sequence = [45, 84, 32, 70, -10, 40]
      threshold = -10.000000001
      expected = 6
      actual = count_items_bigger_than(sequence, threshold)
      print()
      print('Test 4 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 5:
      sequence = []
      threshold = -99999999999999999999999999999
      expected = 0
      actual = count_items_bigger_than(sequence, threshold)
      print()
      print('Test 5 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 6:  This test uses a RANDOMLY generated sequence
      #          but a KNOWN answer (NONE in the sequence are > threshold)
  
      # Next lines make a sequence of 100,000 RANDOM numbers,
      # with each chosen from -100 to 99 (inclusive):
      sequence = []
      for _ in range(100000):
          sequence.append(random.randrange(-100, 100))
  
      threshold = 99.000000001
      expected = 0
      actual = count_items_bigger_than(sequence, threshold)
      print()
      print('Test 6 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 7:  This test uses a RANDOMLY generated sequence
      #          but a KNOWN answer (ALL in the sequence are > threshold).
  
      # Next lines make a sequence of 100,000 RANDOM numbers,
      # with each chosen from -100 to 99 (inclusive):
      sequence = []
      for _ in range(100000):
          sequence.append(random.randrange(-100, 100))
  
      threshold = -100.00000001
      expected = 100000
      actual = count_items_bigger_than(sequence, threshold)
      print()
      print('Test 7 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 8:  This test uses a RANDOMLY generated sequence
      #          and an APPROXIMATE answer that is PROBABLY about right,
      #          based on PROBABILITY THEORY (the Law of Large Numbers).
  
      # Next lines make a sequence of 100,000 RANDOM numbers,
      # with each chosen from -100 to 99 (inclusive):
      sequence = []
      n = 100000
      for _ in range(n):
          sequence.append(random.randrange(-100, 100))
  
      threshold = 98
      expected = n * (1 / 200)
      actual = count_items_bigger_than(sequence, threshold)
      standard_deviation = math.sqrt(n * (1 / 200) * (199 / 200))
  
      print()
      print('Test 8 uses PROBABILITY THEORY')
      print('  to compute the expected result.')
      print('  See the note that follows to see')
      print('  how to evaluate the results of this test.')
      print('       expected:', expected)
      print('       actual:  ', actual)
  
      print()
      print('  Note on how to evaluate the results of')
      print('  Test 8 (above): According to Probability Theory,')
      message = '  the above "actual" should be within {:.0f}'
      print(message.format(2 * standard_deviation))
      print('  of the above "expected" about 95 percent of the time.')
      print()
      print('  You might try running this program multiple times')
      print('  to see whether or not that seems to be true')
      print('  for your code (and Python\'s pseudo-random numbers).')
  
      # DONE 4 (continued):  Add your 2 ADDITIONAL tests here:
  
      sequence = [-62,-200,40,8]
      threshold = -65
      expected = 3
      actual = count_items_bigger_than(sequence, threshold)
      print()
      print('Test 9 expected:', expected)
      print('       actual:  ', actual)
  
      sequence = [45, 23, 90, 10, -15]
      threshold = 20
      expected = 3
      actual = count_items_bigger_than(sequence, threshold)
      print()
      print('Test 10 expected:', expected)
      print('       actual:  ', actual)
  
  
  def count_items_bigger_than(numbers, threshold):
      """
      What comes in:
        -- An sequence of numbers.
        -- A number that is a 'threshold'.
      What goes out:
        Returns the number of items in the given sequence of numbers
        that are strictly bigger than the given 'threshold' number.
      Side effects: None.
      Examples:
        If  numbers   is  [45, 84, 32, 70, -10, 40]
        and threshold is 45,
        then this function returns 2 (since 84 and 70 are bigger than 45).
  
        If  numbers   is  [45, 84, 32, 70, -10, 40]
        and threshold is 0,
        then this function returns 5
        (since all of the 6 numbers except -10 are bigger than 0).
  
        If  numbers   is  [45, 84, 32, 70, -10, 40]
        and threshold is -10,
        then this function still returns 5
        (since all of the 6 numbers except -10 are bigger than -10;
        note that -10 is NOT bigger than itself).
  
        If  numbers   is  [45, 84, 32, 70, -10, 40]
        and threshold is -10.00000001,
        then this function returns 6.
  
      Type hints:
        :type numbers:   list or tuple (of numbers)
        :type threshold: float
      """
      # -------------------------------------------------------------------------
      # DONE: 5. Implement and test this function.
      #   Note that you should write its TEST function first (above).
      # -------------------------------------------------------------------------
      count = 0
      for k in range(len(numbers)):
          if numbers[k] > threshold:
              count = count+1
      return count
  
  
  def run_test_count_positive_sines():
      """ Tests the   count_positive_sines   function. """
      # -------------------------------------------------------------------------
      # DONE: 6. Implement this TEST function.
      #   It TESTS the  count_positive_sines  function defined below.
      #   Include at least ** 1 ** ADDITIONAL test beyond what we supplied.
      #
      #   As usual, include both EXPECTED and ACTUAL results in your test
      #   and compute the latter BY HAND (not by running your program).
      #
      # NOTE: Some numbers that you might expect to be zero,
      #   for example math.sin(math.pi), are in fact slightly positive.
      #   That is because   math.pi   is not exact (nor is math.sin).
      #   Simply stay away from such test cases in this problem.
      # -------------------------------------------------------------------------
      print()
      print('--------------------------------------------------')
      print('Testing the   count_positive_sines   function:')
      print('--------------------------------------------------')
  
      # Test 1:
      expected = 4
      actual = count_positive_sines([3, 4, 5, 6, 7, 8, 9])
      print()
      print('Test 1 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 2:
      expected = 2
      actual = count_positive_sines([3, 6, 8])
      print()
      print('Test 2 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 3:
      expected = 3
      actual = count_positive_sines([7, 7, 7])
      print()
      print('Test 3 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 4:
      expected = 0
      actual = count_positive_sines([6, 6, 6, 6, 6, 6, 6, 6, 6])
      print()
      print('Test 4 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 5:
      expected = 1
      actual = count_positive_sines([3])
      print()
      print('Test 5 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 6:
      expected = 0
      actual = count_positive_sines([6])
      print()
      print('Test 6 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 7:
      expected = 0
      actual = count_positive_sines([5, 4, 6])
      print()
      print('Test 7 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 8 (using the list [0, 1, 2, ... 1063]
      sequence = []
      for k in range(1064):
          sequence.append(k)
  
      expected = 532  # Trust me!
      actual = count_positive_sines(sequence)
      print()
      print('Test 8 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 9 (using the list [0, 1, 2, ... 1064]
      sequence.append(1064)
  
      expected = 533  # Trust me!
      actual = count_positive_sines(sequence)
      print()
      print('Test 9 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 10 (using the list [0, 1, 2, ... 1065]
      sequence.append(1065)
  
      expected = 533  # Trust me!
      actual = count_positive_sines(sequence)
      print()
      print('Test 10 expected:', expected)
      print('        actual:  ', actual)
  
      # TO DO 6 (continued):  Add your 1 ADDITIONAL test here:
  
      expected = 1
      actual = count_positive_sines([5, 6, 9])
      print()
      print('Test 11 expected:', expected)
      print('       actual:  ', actual)
  
  
  def count_positive_sines(numbers):
      """
      What comes in:  An sequence of numbers.
      What goes out: Returns the number of items in the given sequence
        whose sine is positive.
      Side effects: None.
  
      Examples:  Since:
         sine(3) is about 0.14
         sine(4) is about -0.76
         sine(5) is about -0.96
         sine(6) is about -0.28
         sine(7) is about 0.66
         sine(8) is about 0.99
         sine(9) is about 0.41
  
        -- count_positive_sines([3, 4, 5, 6, 7, 8, 9])  returns 4
        -- count_positive_sines([3, 6, 8])              returns 2
        -- count_positive_sines([7, 7, 7])              returns 3
  
      Type hints:
        :type sequence: list or tuple (of numbers)
      """
      # -------------------------------------------------------------------------
      # DONE: 7. Implement and test this function.
      #   Note that you should write its TEST function first (above).
      # -------------------------------------------------------------------------
      count = 0
      for k in range(len(numbers)):
          if math.sin(numbers[k]) > 0:
              count = count + 1
      return count
  
  
  def run_test_sum_first_n():
      """ Tests the   sum_first_n   function. """
      # -------------------------------------------------------------------------
      # DONE: 8. Implement this TEST function.
      #   It TESTS the  sum_first_n  function defined below.
      #   Include at least ** 2 ** ADDITIONAL tests.
      #
      #   As usual, include both EXPECTED and ACTUAL results in your test
      #   and compute the latter BY HAND (not by running your program).
      # -------------------------------------------------------------------------
      print()
      print('--------------------------------------------------')
      print('Testing the   sum_first_n   function:')
      print('--------------------------------------------------')
  
      # Test 1:
      expected = 0
      actual = sum_first_n([48, -10, 50, 5], 0)
      print()
      print('Test 1 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 2:
      expected = 48
      actual = sum_first_n([48, -10, 50, 5], 1)
      print()
      print('Test 2 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 3:
      expected = 38
      actual = sum_first_n([48, -10, 50, 5], 2)
      print()
      print('Test 3 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 4:
      expected = 88
      actual = sum_first_n([48, -10, 50, 5], 3)
      print()
      print('Test 4 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 5:
      expected = 93
      actual = sum_first_n([48, -10, 50, 5], 4)
      print()
      print('Test 5 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 6:  This test uses a RANDOMLY generated sequence
      #          and an ORACLE to determine the expected (correct) result.
      sequence = []
      for _ in range(10000):
          sequence.append(random.randrange(-100, 100))
      expected = builtins.sum(sequence[:-1])
      actual = sum_first_n(sequence, 9999)
      print()
      print('Test 6 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 7:  This test uses a RANDOMLY generated sequence
      #          and an ORACLE to determine the expected (correct) result.
      sequence = []
      for _ in range(10000):
          sequence.append(random.randrange(-100, 100))
      expected = builtins.sum(sequence[:-4000])
      actual = sum_first_n(sequence, 6000)
      print()
      print('Test 7 expected:', expected)
      print('       actual:  ', actual)
  
      # TO DO 8 (continued):  Add your 2 ADDITIONAL tests here:
  
      # Test 8:
      expected = 56
      actual = sum_first_n([56, -1, 56, 5], 1)
      print()
      print('Test 8 expected:', expected)
      print('       actual:  ', actual)
  
      # Test 9:
      expected = 105
      actual = sum_first_n([48, -10, 67, 35], 3)
      print()
      print('Test 9 expected:', expected)
      print('       actual:  ', actual)
  
  
  def sum_first_n(numbers, n):
      """
      What comes in:
        -- An sequence of numbers.
        -- A nonnegative integer   n   that is less than or equal to
             the length of the given sequence.
      What goes out:
        Returns the sum of the first   n   numbers in the given sequence,
        where   n   is the second argument.
      Side effects: None.
      Examples:
        If numbers is   [48, -10, 50, 5], then:
        - sum_first_n(numbers, 0) returns 0  (the sum of NO numbers is 0)
        - sum_first_n(numbers, 1) returns 48
        - sum_first_n(numbers, 2) returns 38
        - sum_first_n(numbers, 3) returns 88
        - sum_first_n(numbers, 4) returns 93
      Type hints:
        :type numbers:   list of tuple (of numbers)
        :type n: int
      """
      # -------------------------------------------------------------------------
      # DONE: 9. Implement and test this function.
      #          Tests have been written for you (above).
      #
      # RESTRICTION:
      #    You may NOT use the built-in  sum   function
      #    in IMPLEMENTING this function.
      #      -- The TESTING code above does use   built_ins.sum
      #         as an ORACLE in TESTING this function, however.
      # -------------------------------------------------------------------------
      sum = 0
      for k in range(n):
          sum = sum + numbers[k]
      return sum
  
  
  # -----------------------------------------------------------------------------
  # Calls  main  to start the ball rolling.
  # -----------------------------------------------------------------------------
  main()
  