Given a list of sample IDs generate unique n-base barcodes for each.
    Note that only 4^n unique barcodes are possible.

def generate_barcodes(nIds, codeLen=12):
    """
    Given a list of sample IDs generate unique n-base barcodes for each.
    Note that only 4^n unique barcodes are possible.
    """
    def next_code(b, c, i):
        return c[:i] + b + (c[i+1:] if i < -1 else '')

    def rand_base():
        return random.choice(['A', 'T', 'C', 'G'])

    def rand_seq(n):
        return ''.join([rand_base() for _ in range(n)])

    # homopolymer filter regex: match if 4 identical bases in a row
    hpf = re.compile('aaaa|cccc|gggg|tttt', re.IGNORECASE)

    while True:
        codes = [rand_seq(codeLen)]
        if (hpf.search(codes[0]) is None):
            break
    idx = 0

    while len(codes) < nIds:
        idx -= 1
        if idx < -codeLen:
            idx = -1
            codes.append(rand_seq(codeLen))
        else:
            nc = next_code(rand_base(), codes[-1], idx)
            if hpf.search(nc) is None:
                codes.append(nc)
        codes = list(set(codes))

    return codes