def get_target(domain):
        target = RowVector()
        w = [RowVector() for i in range(9)]
        for (nu, mu) in domain:
            nu1, mu1 = Partition.trim(nu[1:]), Partition.trim(mu[1:])
            nu2, mu2 = Partition.trim(nu[2:]), Partition.trim(mu[2:])
            nu3, mu3 = Partition.decrement_one(nu), mu

            m = sum(nu) - sum(mu) + 2
            v = lvector(nu, mu, m)
            target |= v

            w[0] |= lvector(nu1, mu1, m)
            w[1] |= lvector(nu1, mu1, m) >> 1
            w[2] |= lvector(nu1, mu1, m) >> 2

            w[3] |= lvector(nu2, mu2, m)
            w[4] |= lvector(nu2, mu2, m) >> 1
            w[5] |= lvector(nu2, mu2, m) >> 2

            w[6] |= lvector(nu3, mu3, m)
            w[7] |= lvector(nu3, mu3, m) >> 1
            w[8] |= lvector(nu3, mu3, m) >> 2

            assert lvector(nu, mu, m) == rvector(nu, mu, m)
        return target, w
def deep_dive(nu=(6, 5, 3, 2, 1), mu=(4, 3, 2, 1)):
    split_nu, split_mu, diagonal = split(nu, mu)
    print()
    print('TYPE:')
    print()
    print(split_nu, split_mu, diagonal)
    print()
    print(Partition.printable(split_nu, split_mu, shifted=False))
    print()

    print('nu =', nu, 'mu =', mu)
    print()
    print(Partition.printable(nu, mu, shifted=True))
    print()

    m = sum(nu) - sum(mu) + 2
    target = lvector(nu, mu, m)

    nu1, mu1 = Partition.decrement_one(nu), mu
    nu2, mu2 = Partition.decrement_one(Partition.decrement_one(nu)), mu
    nu3, mu3 = Partition.decrement_one(
        Partition.decrement_one(
            Partition.decrement_one(nu))), Partition.decrement_one(mu)
    nu4, mu4 = Partition.trim(nu[1:]), Partition.trim(mu[1:])
    nu5, mu5 = Partition.trim(nu[2:]), Partition.trim(mu[2:])
    nu6, mu6 = tuple(i - 1 for i in nu), tuple(i - 1 for i in mu)

    print(Partition.printable(nu1, mu1, shifted=True), '\n')
    print(Partition.printable(nu2, mu2, shifted=True), '\n')
    print(Partition.printable(nu3, mu3, shifted=True), '\n')
    print(Partition.printable(nu4, mu4, shifted=True), '\n')
    print(Partition.printable(nu5, mu5, shifted=True), '\n')

    m = sum(nu) - sum(mu) + 2

    print('nu =', nu, '; mu =', mu)
    print()
    print(Partition.printable(nu, mu, shifted=True))
    print()

    v = [
        lvector(nu1, mu1, m),
        lvector(nu1, mu1, m) >> 1,
        lvector(nu2, mu2, m),
        lvector(nu2, mu2, m) >> 1,
        lvector(nu3, mu3, m),
        lvector(nu3, mu3, m) >> 1,
        lvector(nu4, mu4, m),
        lvector(nu4, mu4, m) >> 1,
        lvector(nu5, mu5, m),
        lvector(nu5, mu5, m) >> 1,
        lvector(nu5, mu5, m) >> 2,
    ]
    print('target =')
    print(target)
    print()
    RowVector.print_matrix(v)
    print()
    print('partial solutions =', RowVector.solve(v, target, integral=False))
    print()
def test_all(n=6):
    def inspect(w, target, good, unique=None):
        ans = []
        sort = sorted(good, key=lambda x: -unique[x]) if unique else good
        for g in sort:
            a = w[0] * g[0]
            for i in range(1, len(g)):
                a += w[i] * g[i]
            if target == a:
                ans.append(g)
        return ans

    types = get_types(n)
    success = [0, 0]
    unique = {}
    refined_unique = defaultdict(list)
    good = set()

    for (split_nu, split_mu, diagonal) in types:
        # if (split_nu, split_mu) != ((3, 1, 1, 1), ()):
        #    continue
        target = RowVector()
        w = [RowVector() for i in range(9)]

        # print(10 * '\n')
        domain = types[(split_nu, split_mu, diagonal)]

        # if len(domain) <= 2:
        #     continue

        for (nu, mu) in domain:
            nu1, mu1 = Partition.decrement_one(nu), mu
            # nu2, mu2 = Partition.decrement_one(Partition.decrement_one(nu)), mu
            # nu3, mu3 = Partition.decrement_one(Partition.decrement_one(nu)), Partition.decrement_one(mu)
            nu4, mu4 = Partition.trim(nu[1:]), Partition.trim(mu[1:])
            nu5, mu5 = Partition.trim(nu[2:]), Partition.trim(mu[2:])
            nu6, mu6 = Partition.trim(nu[3:]), Partition.trim(mu[3:])

            m = sum(nu) - sum(mu) + 2

            v = lvector(nu, mu, m)
            target |= v

            w[0] |= lvector(nu4, mu4, m)
            w[1] |= lvector(nu4, mu4, m) >> 1
            w[2] |= lvector(nu4, mu4, m) >> 2

            w[3] |= lvector(nu5, mu5, m)
            w[4] |= lvector(nu5, mu5, m) >> 1
            w[5] |= lvector(nu5, mu5, m) >> 2

            w[6] |= lvector(nu1, mu1, m)
            w[7] |= lvector(nu1, mu1, m) >> 1
            w[8] |= lvector(nu1, mu1, m) >> 2

            # v = RowVector.elementary(1, len(v))
            # w[9] |= v

            # w[9] |= lvector(nu6, mu6, m)
            # w[10] |= lvector(nu6, mu6, m) >> 1
            # w[11] |= lvector(nu6, mu6, m) >> 2

            # w[8] |= lvector(nu2, mu2, m)
            # w[9] |= lvector(nu2, mu2, m) >> 1

            # w[10] |= lvector(nu3, mu3, m)
            # w[11] |= lvector(nu3, mu3, m) >> 1

            # w[12] |= lvector(nu6, mu6, m)
            # w[13] |= lvector(nu6, mu6, m) >> 1

            try:
                assert lvector(nu, mu, m) == rvector(nu, mu, m)
            except:
                print(Partition.printable(nu, mu, shifted=True), '\n')
                print(lvector(nu, mu, m), '==', rvector(nu, mu, m))
                input('')

        k = 1
        solved = inspect(w, k * target, good, unique)
        if not solved:
            solved = [k * x for x in RowVector.solve(w, target)]
            if solved:
                integral = [RowVector([int(a) for a in solved[0]])]
                if inspect(w, k * target, integral):
                    solved = integral

        if solved:  # and all(type(t) == int for t in solved[0]):
            solved = solved[0]
            success[0] += 1
            unique[solved] = unique.get(solved, 0) + 1
            for (nu, mu) in domain:
                x = sum(nu) - sum(mu)
            refined_unique[solved].append(
                (split_nu, split_mu, diagonal, domain, w, target))
            # if len(domain) > 1:
            #    print(len(domain), ':', solved, diagonal)
            if all(type(i) == int for i in solved):
                good.add(solved)
            if solved[-1] == 0:
                continue
        else:
            success[1] += 1
            for (nu, mu) in domain:
                # if mu == ():
                #    continue

                nu1, mu1 = Partition.decrement_one(nu), mu
                # nu2, mu2 = Partition.decrement_one(Partition.decrement_one(nu)), mu
                # nu3, mu3 = Partition.decrement_one(Partition.decrement_one(nu)), Partition.decrement_one(mu)
                nu4, mu4 = Partition.trim(nu[1:]), Partition.trim(mu[1:])
                nu5, mu5 = Partition.trim(nu[2:]), Partition.trim(mu[2:])
                # nu6, mu6 = Partition.decrement_one(Partition.decrement_one(nu)), mu

                m = sum(nu) - sum(mu) + 2

                print('nu =', nu, '; mu =', mu)
                print()
                print(Partition.printable(nu, mu, shifted=True))
                print()

                # print(Partition.printable(nu1, mu1, shifted=True), '\n')
                # print(Partition.printable(nu2, mu2, shifted=True), '\n')
                # print(Partition.printable(nu3, mu3, shifted=True), '\n')
                # print(Partition.printable(nu4, mu4, shifted=True), '\n')
                # print(Partition.printable(nu5, mu5, shifted=True), '\n')
                # print(Partition.printable(nu6, mu6, shifted=True), '\n')

                v = [
                    lvector(nu4, mu4, m),
                    lvector(nu4, mu4, m) >> 1,
                    lvector(nu4, mu4, m) >> 2,
                    lvector(nu5, mu5, m),
                    lvector(nu5, mu5, m) >> 1,
                    lvector(nu5, mu5, m) >> 2,
                    lvector(nu1, mu1, m),
                    lvector(nu1, mu1, m) >> 1,
                    lvector(nu1, mu1, m) >> 2,
                    # lvector(nu2, mu2, m),
                    # lvector(nu2, mu2, m) >> 1,
                    # lvector(nu3, mu3, m),
                    # lvector(nu3, mu3, m) >> 1,
                    # lvector(nu6, mu6, m),
                    # lvector(nu6, mu6, m) >> 1,
                ]
                print('target =')
                print(lvector(nu, mu, m))
                print()
                RowVector.print_matrix(v)
                print()
                print('partial solutions =',
                      RowVector.solve(v, lvector(nu, mu, m), integral=False))
                print()
                # print('solutions so far:')
                # for u in unique:
                #     print('*', u)

        RowVector.print_matrix(w)
        RowVector.print_matrix([target])

        print(Partition.printable(nu, mu, shifted=True), '\n')
        print(Partition.printable(nu1, mu1, shifted=True), '\n')

        print()
        print('TYPE:')
        print()
        print(split_nu, split_mu, diagonal)
        print()
        print(Partition.printable(split_nu, split_mu, shifted=False))
        print()
        print()
        print(solved)
        print()
        # input('')
        print(10 * '\n')
    print()

    for u in sorted(unique, key=lambda x: -unique[x]):
        print(u, ':', unique[u])
        for (split_nu, split_mu, diagonal, domain, w,
             target) in refined_unique[u][:10]:
            RowVector.print_matrix(w)
            RowVector.print_matrix([target])
            print()
            print('type:', split_nu, split_mu, diagonal)
            print()
            print(Partition.printable(split_nu, split_mu, shifted=False))
            print()
            # i = 1
            # for nu, mu in domain:
            #     print(i, 'of', len(domain), '\n')
            #     print(Partition.printable(nu, mu, shifted=True))
            #     print()
            #     i += 1

    print()
    print('{')
    for u in sorted(unique, key=lambda x: unique[x]):
        print(u, ':', unique[u], ',')  # , unique[u], set(refined_unique[u]))
    print('}')
    print()
    print('unique:', len(unique))
    print()
    print(success)