'''Explore matrices that respect rank

identity_matrices = RankMatrices(identity_rule)

>>> identity_matrices.print_product_stats(10)
2 1 [(1, 2)]
3 1 [(0, 3), (1, 3)]
4 1 [(0, 10), (1, 5)]
4 2 [(0, 14), (1, 6)]
5 1 [(0, 32), (1, 8)]
5 2 [(0, 39), (1, 9)]
6 1 [(0, 91), (1, 13)]
6 2 [(0, 115), (1, 15)]
6 3 [(0, 101), (1, 15), (2, 1)]
7 1 [(0, 252), (1, 21)]
7 2 [(0, 312), (1, 24)]
7 3 [(0, 288), (1, 26), (2, 1)]
8 1 [(0, 680), (1, 34)]
8 2 [(0, 845), (1, 39)]
8 3 [(0, 769), (1, 45), (2, 2)]
8 4 [(0, 803), (1, 44), (2, 3)]
9 1 [(0, 1815), (1, 55)]
9 2 [(0, 2247), (1, 63)]
9 3 [(0, 2066), (1, 76), (2, 2), (3, 1)]
9 4 [(0, 2116), (1, 80), (2, 4)]
10 1 [(0, 4806), (1, 89)]
10 2 [(0, 5950), (1, 102)]
10 3 [(0, 5472), (1, 129), (2, 5), (3, 1)]
10 4 [(0, 5639), (1, 139), (2, 6), (3, 1)]
10 5 [(0, 5542), (1, 144), (2, 10)]

>>> identity_matrices.print_C_stats(10)
0 [(1, 1)]
1 [(0, 1), (1, 1)]
2 [(0, 3), (1, 3)]
3 [(-1, 1), (0, 10), (1, 4)]
4 [(-1, 2), (0, 31), (1, 7)]
5 [(-1, 4), (0, 89), (1, 11)]
6 [(-1, 7), (0, 248), (1, 18)]
7 [(-1, 12), (0, 673), (1, 29)]
8 [(-1, 20), (0, 1803), (1, 47)]
9 [(-1, 33), (0, 4786), (1, 76)]
10 [(-1, 54), (0, 12639), (1, 123)]

>>> identity_matrices.print_D_stats(10)
0 [(0, 1), (1, 1)]
1 [(0, 2), (1, 1)]
2 [(0, 8), (1, 2)]
3 [(0, 21), (1, 3)]
4 [(0, 60), (1, 5)]
5 [(0, 160), (1, 8)]
6 [(0, 429), (1, 13)]
7 [(0, 1134), (1, 21)]
8 [(0, 2992), (1, 34)]
9 [(0, 7865), (1, 55)]
10 [(0, 20648), (1, 89)]


>>> for d in range(1, 7):
...    print(' '.join(map(CD_from_word, FIB_WORDS[d])))
C
CC D
CCC CD DC
CCCC CCD CDC DCC DD
CCCCC CCCD CCDC CDCC CDD DCCC DCD DDC
CCCCCC CCCCD CCCDC CCDCC CCDD CDCCC CDCD CDDC DCCCC DCCD DCDC DDCC DDD

>>> for d in range(1, 7):
...    for word in FIB_WORDS[d]:
...        if word != word_from_CD(CD_from_word(word)):
...            print(word, CD_from_word(word))


>>> for n in range(10):
...    for word in FIB_WORDS[n]:
...        index = index_from_word(word)
...        word2 = word_from_index(index)
...        if word != word2:
...            print(word, word2)


>>> EXPAND_D[0] == (b'',)
True
>>> EXPAND_D[1] == (b'\x02', b'\x01\x01')
True
>>> EXPAND_D[2] == (b'\x02\x02', b'\x02\x01\x01', b'\x01' * 4)
True
>>> EXPAND_D[3] == (b'\x02\x02\x02', b'\x02\x02\x01\x01',
... b'\x02' + b'\x01' * 4,  b'\x01' * 6)
True

>>> list(expand_d((0,))) == [(b'',)]
True

>>> str_expand_d(expand_d((0,)))
''

>>> str_expand_d(expand_d((1,)))
'2'

>>> str_expand_d(expand_d((2,)))
'22'

>>> str_expand_d(expand_d((0, 1, 2)))
',2,22 ,2,211 ,2,1111 ,11,22 ,11,211 ,11,1111'

>>> str_expand_d(expand_d((0, 2, 1)))
',22,2 ,22,11 ,211,2 ,211,11 ,1111,2 ,1111,11'

>>> str_expand_d(expand_d((1, 2, 1)))
'2,22,2 2,22,11 2,211,2 2,211,11 2,1111,2 2,1111,11'

>>> str_expand_d(expand_d((2, 2, 1)))
'22,22,2 22,22,11 22,211,2 22,211,11 22,1111,2 22,1111,11'

>>> expand_c((1, 0, 0))
((0, 0, 1), (0, 1, 0), (1, 0, 0))

>>> expand_c((0, 0, 1))
((0, 0, 1),)

>>> expand_c((2, 0, 0))
((0, 0, 2), (0, 1, 1), (0, 2, 0), (1, 0, 1), (1, 1, 0), (2, 0, 0))

>>> expand_c((1, 1, 0))
((0, 0, 2), (0, 1, 1), (0, 2, 0), (1, 0, 1), (1, 1, 0))


>>> slide_d(((0,), (0,)))
(((0,), (0,)),)
>>> slide_d(((0,), (1,)))
(((0,), (1,)),)
>>> slide_d(((1,), (0,)))
(((1,), (0,)),)
>>> slide_d(((1,), (1,)))
(((1,), (1,)),)


>>> slide_d(((0, 0), (0, 0)))
(((0, 0), (0, 0)),)
>>> slide_d(((0, 0), (1, 0)))
(((0, 0), (1, 0)), ((1, 1), (0, 0)))
>>> slide_d(((0, 0), (2, 0)))
(((0, 0), (2, 0)), ((1, 1), (1, 0)), ((2, 2), (0, 0)))

>>> slide_d(((1, 0), (1, 0)))
(((1, 0), (1, 0)), ((2, 1), (0, 0)))
>>> slide_d(((1, 0), (2, 0)))
(((1, 0), (2, 0)), ((2, 1), (1, 0)), ((3, 2), (0, 0)))

>>> cm_1.print_C_stats(10)
0 [(1, 1)]
1 [(0, 1), (1, 1)]
2 [(0, 3), (1, 3)]
3 [(0, 11), (1, 4)]
4 [(0, 32), (1, 8)]
5 [(0, 90), (1, 14)]
6 [(0, 250), (1, 23)]
7 [(-1, 2), (0, 674), (1, 38)]
8 [(-1, 3), (0, 1801), (1, 66)]
9 [(-1, 14), (0, 4776), (1, 105)]
10 [(-1, 19), (0, 12616), (1, 181)]

>>> cm_1.print_D_stats(10)
0 [(0, 1), (1, 1)]
1 [(0, 2), (1, 1)]
2 [(0, 8), (1, 2)]
3 [(0, 19), (1, 5)]
4 [(0, 57), (1, 8)]
5 [(0, 154), (1, 14)]
6 [(0, 416), (1, 26)]
7 [(-1, 3), (0, 1110), (1, 42)]
8 [(-1, 1), (0, 2949), (1, 76)]
9 [(-1, 10), (0, 7784), (1, 126)]
10 [(-1, 11), (0, 20510), (1, 216)]

>>> cm_1.print_product_stats(10)