# 6.11. Idiom Reduce

• Reduce sequence using function

• Built-in

>>> 1 + 2
3

>>> 1 + 2 + 3 + 4
10


## 6.11.2. Problem

>>> def add(x, y):
...     return x + y
>>>
>>>
>>> DATA = [1, 2, 3, 4]
>>> result = 0
>>>
>>> for element in DATA:
>>>
>>> print(result)
10


## 6.11.3. Solution

>>> from functools import reduce
>>>
>>>
...     return x + y
>>>
>>>
>>> DATA = [1, 2, 3, 4]
>>>
10


## 6.11.4. Rationale

>>> from functools import reduce
>>> from operator import mul
>>>
>>>
>>> DATA = [1, 2, 3, 4]
>>>
>>> reduce(mul, DATA)
24

>>> from functools import reduce
>>>
>>>
>>> DATA = [1, 2, 3, 4]
>>>
>>> reduce(min, DATA)
1
>>> reduce(max, DATA)
4


## 6.11.6. Assignments

"""
* Assignment: Idiom Reduce Evaluate
* Type: class assignment
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min

English:
1. Define result: int with sum of DATA
2. Note, that all the time you are working on a data stream
3. Use reduce()
4. Run doctests - all must succeed

Polish:
1. Zdefiniuj result: int ze sumą z DATA
2. Zwróć uwagę, że cały czas pracujesz na strumieniu danych
3. Użyj reduce()
4. Uruchom doctesty - wszystkie muszą się powieść

Hints:
* from functools import reduce

Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from inspect import isfunction

>>> assert isfunction(odd), \
'Object odd must be a function'
>>> assert isfunction(cube), \
'Object cube must be a function'
>>> assert result is not Ellipsis, \
'Assign result to variable: result'
>>> assert type(result) is int, \
'Variable result has invalid type, should be int'

>>> result
1225
"""

def odd(x):
return x % 2

def cube(x):
return x ** 3

DATA = range(0, 10)
DATA = filter(odd, DATA)
DATA = map(cube, DATA)

# Calculate sum of DATA
# Use reduce()
# type: int
result = ...


"""
* Assignment: Idiom Reduce Chain
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min

English:
1. Define result with numbers from range():
a. from 0 (inclusive)
b. to 10 (exclusive)
2. Use filter() to get odd numbers from result
(and assign to result)
3. Use map() to cube all numbers in result
4. Create result: float with arithmetic mean of result
5. Do not use lambda expressions
6. Note, that all the time you are working on one data stream
7. Run doctests - all must succeed

Polish:
1. Zdefiniu result z liczbami z range():
a. od 0 (włącznie)
b. do 10 (rozłącznie)
2. Użyj filter() aby otrzymać liczby nieparzyste z result
(i przypisz je do result)
3. Użyj map() aby podnieść wszystkie liczby w result do sześcianu
4. Stwórz result: float ze średnią arytmetyczną z result
5. Nie używaj wyrażeń lambda
6. Zwróć uwagę, że cały czas pracujesz na jednym strumieniu danych
7. Uruchom doctesty - wszystkie muszą się powieść

Hints:
* type cast to list() to expand generator before calculating mean
* mean = sum(...) / len(...)
* TypeError: object of type 'map' has no len()
* ZeroDivisionError: division by zero

Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from inspect import isfunction

>>> isfunction(odd)
True
>>> isfunction(cube)
True
>>> type(result) is float
True
>>> result
245.0
"""

def odd(x):
return x % 2

def cube(x):
return x ** 3

data = range(0, 10)
data = filter(odd, data)
data = map(cube, data)

# Calculate mean
# type: float
result = ...


"""
* Assignment: Idiom Reduce Impl
* Complexity: medium
* Lines of code: 4 lines
* Time: 13 min

English:
1. Write own implementation of a built-in reduce() function
2. Define function myreduce with parameters:
a. parameter function: Callable
b. parameter iterable: list | tuple
3. Don't validate arguments and assume, that user will:
a. always pass valid type of arguments
b. iterable length will always be greater than 0
4. Do not use: map, filter, zip, enumerate, all, any, reduce
5. Run doctests - all must succeed

Polish:
1. Zaimplementuj własne rozwiązanie wbudowanej funkcji reduce()
2. Zdefiniuj funkcję myreduce z parametrami:
a. parameter function: Callable
b. parameter iterable: list | tuple
3. Nie waliduj argumentów i przyjmij, że użytkownik:
a. zawsze poda argumenty poprawnych typów
b. długość iterable będzie większa od 0
4. Nie używaj: map, filter, zip, enumerate, all, any, reduce
5. Uruchom doctesty - wszystkie muszą się powieść

Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from inspect import isfunction
>>> from operator import add, mul
>>> assert isfunction(myreduce)

>>> myreduce(add, [1, 2, 3, 4, 5])
15

>>> myreduce(mul, [1, 2, 3, 4, 5])
120
"""

# Write own implementation of a built-in reduce() function
# Define function myrange with parameters: function, iterable
# type: Callable[[Callable, Iterable], Any]
def myreduce(function, iterable):
...