def parse_value_bitmask(bitstring):
    """Parse a ternary string specifying a bitmask.
    The bitmask is given as a string of 36 bits, written with the most significant bit on the left
    and the least significant bit on the right. A 0 or 1 overwrites the corresponding bit in the value, 
    while an X leaves the bit in the value unchanged.

    Since there are three possible modes for each position in the bitmask, we require more than one
    binary operation, which we separate into a zero_mask and a one_mask for overwriting with 0 and 1,
    respectively. Then to mask the value, we calculate `(value & zero_mask) | one_mask`.

    Truth table: Input I, Mask M, zero_mask Z, one_mask W, Result R; M = (Z,W), R = (I & Z) | W
    I | M | Z | W | R
    0 | 0 | 0 | 0 | 0
    1 | 0 | 0 | 0 | 0
    0 | 1 | 1 | 1 | 1
    1 | 1 | 1 | 1 | 1
    0 | X | 1 | 0 | 0
    1 | X | 1 | 0 | 1
    """
    zero_mask = int("".join(map(lambda c: '1' if c == 'X' else c, bitstring)), base=2)
    one_mask = int("".join(map(lambda c: '0' if c == 'X' else c, bitstring)), base=2)
    return zero_mask, one_mask