# William M. Farmer
# super_sum.py
# 19 March 2013


# sum implements the big sigma notation.
#
# m,n are integers.
# f is a function from integers to integers.
#
# sum returns f(m) + f(m + 1) + ... + f(n) if m <= n and 
# returns 0 if m > n.

def sum(m,n,f):
  accum = 0
  for i in range(m,n + 1):
    accum = accum + f(i)
  return accum

# product implements the big pi notation.
#
# m,n are integers.
# f is a function from integers to integers.
#
# product returns f(m) * f(m + 1) * ... * f(n) if m <= n and 
# returns 1 if m > n.

def product(m,n,f):
  accum = 1
  for i in range(m,n + 1):
    accum = accum * f(i)
  return accum

# superSum is a generalization of sum and product.
#
# add is function that acts like addition on a some set S of values.
# zero is in S and is the additive identity with respect to add.
# m,n are integers.
# f is a function from integers to S.
#
# superSum returns f(m) add f(m + 1) add ... add f(n) if m <= n and 
# returns zero if m > n.
#
# Technical note: (S,add,zero) must be a monoid.

def superSum(add,zero,m,n,f):
  accum = zero
  for i in range(m,n + 1):
    accum = add(accum,f(i))
  return accum

# Examples

def id(x):
  return x

def plus(x,y):
  return x + y

def times(x,y):
  return x * y

def numberToAscii(x):
  return chr(x)

def sum2(m,n,f):
  return superSum(plus,0,m,n,f)

def product2(m,n,f):
  return superSum(times,1,m,n,f) 

def factorial(n):
    return superSum(times,1,1,n,id)

def asciiString():
  return superSum(plus,"",0,127,numberToAscii)