def stream_operator(input_stream, f):
    # List function: list -> list
    def list_operator(input_list):
        return f(input_list)
    return stream_func(
        list_func=list_operator,
        inputs=input_stream,
        num_outputs=1,
        state=None,
        call_streams=None)
def stream_from_list(x_list, trigger_stream):
    # List function: state -> list, state
    def get_next_element(index):
        return ([x_list[index]], index+1)
    
    return stream_func(
        list_func=get_next_element,
        inputs=None,
        num_outputs=1,
        state=0, # initial state
        call_streams=[trigger_stream])
def outliers_and_inrange_streams(x_and_y_streams, a, b, delta):
    # List function: list of lists -> list of lists
    def outliers_and_inrange_lists(x_and_y_lists):
        z_list = zip(*x_and_y_lists)
        outliers_list = list(v for v in z_list if abs(a * v[0] + b - v[1]) > delta)
        inrange_list = list(v for v in z_list if abs(a * v[0] + b - v[1]) <= delta)
        return [inrange_list, outliers_list]

    return stream_func(
        list_func=outliers_and_inrange_lists, inputs=x_and_y_streams, num_outputs=2, state=None, call_streams=None
    )
def print_stream(input_stream):
    # List function: list -> ()
    def print_list(lst):
        for v in lst:
            print '{0} = {1}'.format(input_stream.name, v)

    return stream_func(
        list_func=print_list,
        inputs=input_stream,
        num_outputs=0,
        state=None,
        call_streams=None)
def single_random_stream(trigger_stream):
    # List function: () -> list
    import random
    def list_of_single_random_number():
        return [random.random()]

    return stream_func(
        list_func=list_of_single_random_number,
        inputs=None,
        num_outputs=1,
        state=None,
        call_streams=[trigger_stream])
def print_is_multiple_streams(multiples_and_divisors_streams):
    # List function: list of lists -> ()
    def print_is_multiple_lists(multiples_and_divisors_lists):
        multiples_list, divisors_list = multiples_and_divisors_lists
        for i in range(min(len(multiples_list), len(divisors_list))):
            print 'is {0} a multiple of {1} ? {2} '.format(
                multiples_list[i], divisors_list[i],
                multiples_list[i] % divisors_list[i] == 0)

    return stream_func(
        list_func=print_is_multiple_lists,
        inputs=multiples_and_divisors_streams,
        num_outputs=0,
        state=None,
        call_streams=None)
def averages_stream(input_stream):
    # List function: list, state -> list, state
    def averages_list(input_list, state):
        number_of_values, sum_of_values = state
        output_list = [0.0] * len(input_list)
        for i,v in enumerate(input_list):
            sum_of_values += v
            number_of_values += 1
            output_list[i] = sum_of_values/float(number_of_values)
        state = number_of_values, sum_of_values
        return (output_list, state)

    return stream_func(
        list_func=averages_list,
        inputs=input_stream,
        num_outputs=1,
        state=(0, 0.0),
        call_streams=None)
def mean_and_sigma_streams(trigger_stream):
    # List function: state -> [list of lists, state]
    def mean_and_sigma_lists(state):
        number_of_values, sum_of_values, sum_of_squared_values = state
        next_value = random.random()
        number_of_values += 1
        sum_of_values += next_value
        sum_of_squared_values += next_value*next_value
        mean = sum_of_values/float(number_of_values)
        second_moment = sum_of_squared_values/float(number_of_values)
        variance = second_moment - mean*mean
        sigma = math.sqrt(variance)
        state = (number_of_values, sum_of_values, sum_of_squared_values)
        return ([[mean], [sigma]], state)
    
    return stream_func(
        list_func=mean_and_sigma_lists,
        inputs=None,
        num_outputs=2,
        state=(0, 0.0, 0.0),
        call_streams=[trigger_stream])
def print_next_and_mean_stream(input_stream):
    # List function: list, state -> state
    def print_next_and_mean_list(lst, state):
        number_of_values, sum_of_values = state
        for v in lst:
            number_of_values += 1
            sum_of_values += v
            print '{0}[{1}], value = {2}'.format(
                input_stream.name, number_of_values, v)
            print '{0}, number received = {1}, mean = {2:8.2f}'.format(
                input_stream.name, number_of_values,
                sum_of_values/float(number_of_values))
        state = (number_of_values, sum_of_values)
        return state

    return stream_func(
        list_func=print_next_and_mean_list,
        inputs=input_stream,
        num_outputs=0,
        state=(0, 0.0),
        call_streams=None)
def print_is_multiple_with_scores_streams(multiples_and_divisors_streams):
    # List function: list of lists, state -> state
    def print_is_multiple_with_scores_lists(multiples_and_divisors_lists, state):
        multiples_list, divisors_list = multiples_and_divisors_lists
        num_true_values, num_false_values = state
        for i in range(min(len(multiples_list), len(divisors_list))):
            is_multiple = (multiples_list[i] % divisors_list[i] == 0)
            num_true_values += is_multiple
            num_false_values += (not is_multiple)
            print 'is {0} a multiple of {1} ? {2}. '.format(
                multiples_list[i], divisors_list[i],
                is_multiple)
            print 'Total number of true values = {0}, false values = {1}'.format(
                num_true_values, num_false_values)
        state = (num_true_values, num_false_values)
        return state

    return stream_func(
        list_func=print_is_multiple_with_scores_lists,
        inputs=multiples_and_divisors_streams,
        num_outputs=0,
        state=(0,0),
        call_streams=None)
def average_by_sensor_type_stream(input_stream):
    # List function: list, state -> list of lists, state
    def average_by_sensor_type_list(input_list, state):
        number_type_0, number_type_1, sum_type_0, sum_type_1 = state
        averages_list_type_0 = list()
        averages_list_type_1 = list()
        for (type, value) in input_list:
            if type == 1:
                number_type_1 += 1
                sum_type_1 += value
                averages_list_type_1.append(sum_type_1/float(number_type_1))
            else:
                number_type_0 += 1
                sum_type_0 += value
                averages_list_type_0.append(sum_type_0/float(number_type_0))
        state = number_type_0, number_type_1, sum_type_0, sum_type_1
        return ([averages_list_type_0, averages_list_type_1], state)
                
    return stream_func(
        list_func=average_by_sensor_type_list,
        inputs=input_stream,
        num_outputs=2,
        state=(0, 0, 0.0, 0.0),
        call_streams=None)