John and his wife Ann have decided to go to Codewars. 

On first day Ann will do one kata and John - he wants to know how it is working - 0 kata.

Let us call `a(n)` - and `j(n)` - the number of katas done by Ann - and John - at day `n`. We have `a(0) = 1` and in the same manner `j(0) = 0`.

They have chosen the following rules:

- On day `n` the number of katas done by Ann should be `n` minus the number of katas done by John at day `t`, `t` being equal to the number of katas done
by Ann herself at day `n - 1`.

- On day `n` the number of katas done by John should be `n` minus the number of katas done by Ann at day `t`, `t` being equal to the number of katas done
by John himself at day `n - 1`.

Whoops! I think they need to lay out a little clearer exactly what there're getting themselves into!

# Could you write:
- 1) two functions `ann` and `john (parameter n)` giving the list of the numbers of katas Ann and John should take on the first n days (see first examples below)? 
- 2) The total number of katas taken by ann `function sum_ann(n)` and john `function sum_john(n)` - on the first n days? 
 

The functions in 1) are not tested in Fortran and not tested in Shell.

# Examples:
```
john(11) -->  [0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6]
ann(6) -->  [1, 1, 2, 2, 3, 3]

sum_john(75) -->  1720
sum_ann(150) -->  6930
```

# Shell Note:
sumJohnAndAnn has two parameters:

first one : n (number of days, $1)

second one : which($2) ->

- 1 for getting John's sum

- 2 for getting Ann's sum.

See "Sample Tests".

# Note: 

Keep an eye on performance.

Difficulty: introductory

Starter code:

def j(n):
	

Solutions:
def j_n(n):
    j = [0]
    a = [1]
    for i in range(1, n):
        j.append((i - a[j[i-1]]))
        a.append((i-j[a[i-1]]))
    return j, a


def john(n):
    return j_n(n)[0]
    
def ann(n):
    return j_n(n)[1]
    
        
def sum_john(n):
    return sum(john(n))
    
def sum_ann(n):
     return sum(ann(n))

from functools import lru_cache

@lru_cache(maxsize = None)
def john_value(n):
    if n == 0:
        return 0
    return n - ann_value(john_value(n - 1))
    
@lru_cache(maxsize = None)
def ann_value(n):
    if n == 0:
        return 1
    return n - john_value(ann_value(n - 1))

def ann(n):
    return [ann_value(x) for x in range(n)]

def john(n):
    return [john_value(x) for x in range(n)]

def sum_john(n):
    return sum(john(n))
    
def sum_ann(n):
    return sum(ann(n))

def get_arrays(n, name):
    a = [1]
    j = [0]
    for i in xrange(1, n):
        next_j = i - a[j[i-1]]
        j.append(next_j)
        next_a = i - j[a[i-1]]
        a.append(next_a)
    ret = {
        'john': j,
        'ann' : a
    }
    return ret[name]

def john(n):
    return get_arrays(n, 'john')
    
def ann(n):
    return get_arrays(n, 'ann')
    
def sum_john(n):
    return sum(john(n))
    
def sum_ann(n):
    return sum(ann(n))

an, jh = [1], [0]
for i in range(1,int(1e5*5)):
    jh.append(i-an[jh[-1]])
    an.append(i-jh[an[-1]])
john=lambda n:jh[:n]
ann=lambda n:an[:n]
sum_john=lambda n:sum(jh[:n])
sum_ann=lambda n:sum(an[:n])

from functools import lru_cache


@lru_cache(maxsize=None)
def j(n):
    return n - a(j(n-1)) if n else 0


@lru_cache(maxsize=None)
def a(n):
    return n - j(a(n-1)) if n else 1


def john(n): return [j(i) for i in range(n)]
def ann(n): return [a(i) for i in range(n)]
def sum_john(n): return sum(john(n))
def sum_ann(n): return sum(ann(n))

def generate_solved_katas(n):
    """ 生成ann和john在第n天时的解题数量表"""
    john_katas = [0]
    ann_katas = [1]
    for i in range(1, n):
        john_katas.append(i - ann_katas[john_katas[i-1]])
        ann_katas.append(i - john_katas[ann_katas[i-1]])
    return john_katas, ann_katas


def john(n):
    return generate_solved_katas(n)[0]


def ann(n):
    return generate_solved_katas(n)[1]


def sum_john(n):
    return sum(john(n))


def sum_ann(n):
    return sum(ann(n))

def john_and_ann(n):
    john = [0]
    ann = [1]
    for i in range(1, n):
        t1, t2 = ann[i-1],  john[i-1]
        john.append(i - ann[t2])
        ann.append(i - john[t1])
    return john, ann

def ann(n):
    john, ann = john_and_ann(n)
    return ann

def john(n):
    john, ann = john_and_ann(n)
    return john

def sum_ann(n):
    Ann = ann(n)
    return sum(Ann)

def sum_john(n):
    John = john(n)
    return sum(John)

jm, am = {0:0}, {0:1}
def j(n):
    if n in jm.keys(): return jm[n]
    jm[n] = n - a(j(n-1))
    return jm[n]

def a(n):
    if n in am.keys(): return am[n]
    am[n] = n - j(a(n-1))
    return am[n]

def john(n):
    return [j(i) for i in range(n)]
    
def ann(n):
    return [a(i) for i in range(n)]
    
def sum_john(n):
    return sum(john(n))
    
def sum_ann(n):
    return sum(ann(n))

#Dictionaries to cache results
john_dict = {}
ann_dict = {}

#Helper functions using caches to find each value.  
#I couldn't find a way to simplify this without making it more complex.
def john_val(n):
    if n == 0:
        return 0
    if not n in john_dict:
        john_dict[n] =  n - ann_val(john_val(n-1))
    return john_dict[n]

def ann_val(n):
    if n == 0:
        return 1
    if not n in ann_dict:
        ann_dict[n] =  n - john_val(ann_val(n-1))
    return ann_dict[n]

#Once the helpers are done it's easy
def john(n):
    return [john_val(i) for i in range(n)]

def ann(n):
    return [ann_val(i) for i in range(n)]

def sum_john(n):
    return sum(john(n))

def sum_ann(n):
    return sum(ann(n))


def johnann(n, jnota):
    j, a = [0], [1]
    for i in range(1,n):
        j.append(i-a[j[-1]])
        a.append(i-j[a[-1]])
    return j if jnota else a

john = lambda n: johnann(n, True)
ann = lambda n: johnann(n, False)
sum_john = lambda n: sum(john(n))
sum_ann = lambda n: sum(ann(n))