
def SANC(a,b):
    """
    >>> SANC('0','0')
    ('0', '0')
    """
    assert isinstance(a,str)
    assert isinstance(b,str)
    assert a.isdigit()
    assert b.isdigit()
    table = {
        '0':{
            '0':('0','0'),
            '1':('0','1'),
            '2':('0','2'),
            '3':('0','3'),
            '4':('0','4'),
            '5':('0','5'),
            '6':('0','6'),
            '7':('0','7'),
            '8':('0','8'),
            '9':('0','9')
        },
        '1':{
            '0':('0','1'),
            '1':('0','2'),
            '2':('0','3'),
            '3':('0','4'),
            '4':('0','5'),
            '5':('0','6'),
            '6':('0','7'),
            '7':('0','8'),
            '8':('0','9'),
            '9':('1','0')
        },
        '3':{},
        '4':{},
        '5':{},
        '6':{},
        '7':{},
        '8':{},
        '9':{}
    }
    tmp = int(a) + int(b)
    tmp = str(tmp)
    if len(tmp) == 1:
        tmp = '0' + tmp
    tmp = reversed(tmp)
    tmp = tuple(tmp)
    print("SANC%s => %s"%((a,b),tmp))
    return tmp

def R(accum,(num,carry)):
    """
    >>> R([],('1','0'))
    ['1', '0']
    >>> R(['1','0'],('1','0'))
    ['1', '1', '0']
    >>> R(['0','1'],('1','0'))
    ['0', '0', '1']
    >>> R(['0','0'],('1','0'))
    ['0', '1', '0']
    """
    assert isinstance(accum,list)
    assert not [True for num in accum if not isinstance(num,str)]
    assert not [True for num in accum if not num.isdigit()]
    assert isinstance(num,str)
    assert num.isdigit()
    assert isinstance(carry,str)
    assert carry.isdigit()
    if not accum:
        ret = [num,carry]
    else:
        ret = accum[:-1]
        last = accum[-1]
        nunum, nucarry = SANC(last,num)
        nucarry, _ = SANC(carry,nucarry)
        ret = ret + [nunum] + [nucarry]
    print("R(%s,%s) => %s"%(accum,(num,carry),ret))
    return ret


def _add(a,b):
    """
    >>> _add("12345","54321")
    "66666"
    >>> _add("999","11122")
    "12121"
    """
    assert isinstance(a,str)
    assert isinstance(b,str)
    assert b.isdigit()
    assert a.isdigit()
    #make the number the same length
    while len(a) < len(b):
        a = '0' + a
    while len(b) < len(a):
        b = '0' + b
    #then make em a reversed list of number
    _aa = reversed(a)
    _bb = reversed(b)
    #group all number from both side as pair
    both = zip(_aa,_bb)
    #addition
    print(both)
    numCarryPair = map(lambda (a,b):SANC(a,b),both)
    print(numCarryPair)
    arrayNum = reduce(R,numCarryPair,[])
    print(arrayNum)
    ret = reversed(arrayNum)
    ret = ''.join(ret)
    print("_add%s => %s"%((a,b),ret))
    return ret

if __name__ == '__main__':
    import doctest
    doctest.testmod()
