# Orbit of {BC, DE} _ orbit of {BE, CD}_ orbit of {BD, CE}
# under the cyclic permutation A -> B -> C -> D -> E -> A.

basis = {
    0b_11000_00101_11101,
    0b_01100_10010_11110,
    0b_00110_01001_01111,
    0b_00011_10100_10111,
    0b_11111_00000_11111, # Omit this and following for the Hadamard code.
    0b_00000_11111_11111, # Omit this one for the Petersen code.
    0b_00000_00000_11111, # Omit this one for the even-weight code.
}

code = {0b_00000_00000_00000}
for b in basis:
    code = code.union(x ^ b for x in code)

print("Codewords")
by_weight = {i: set() for i in range(16)}
for word in code:
    by_weight[word.bit_count()].add(word)
for (weight, words) in by_weight.items():
    print(weight, len(words))

print("Symptoms")
by_errors = {i: set() for i in range(16)}
for message in range(1 << 15):
    symptom = min((message ^ word for word in code), key = int.bit_count)
    by_errors[symptom.bit_count()].add(symptom)
for (weight, symptoms) in by_errors.items():
    print(weight, len(symptoms))

for num_errors in [3, 4]:
    print(f"Ambiguities in {num_errors}-bit errors")
    by_ambiguity = {i: set() for i in range(16)}
    for symptom in by_errors[num_errors]:
        decodings = [
            word
            for word in code
            if (word ^ symptom).bit_count() == num_errors
        ]
        by_ambiguity[len(decodings)].add(symptom)
    for (ambiguity, symptoms) in by_ambiguity.items():
        print(ambiguity, len(symptoms))
