docs: def number_of_partitions(max_range, max_sum):
      '''
      Returns an array arr of the same shape as max_range, where
      arr[j] = number of admissible partitions for 
               j summands bounded by max_range[j:] and with sum <= max_sum
      '''
      M = max_sum + 1
      N = len(max_range) 
      arr = np.zeros(shape=(M,N), dtype = int)    
      arr[:,-1] = np.where(np.arange(M) <= min(max_range[-1], max_sum), 1, 0)
      for i in range(N-2,-1,-1):
          for j in range(max_range[i]+1):
              arr[j:,i] += arr[:M-j,i+1] 
      return arr.sum(axis = 0)