import math
H = 1.0078250319
B = 11.00930536
C = 12.
N = 14.0030740074
O = 15.9949146223
F = 18.99840316
P = 30.973762
S = 31.97207073
Cl = 34.96885271
Br = 78.9183376
I = 126.9044719

elements = [H, C, N, O, F, S, Cl, Br, I]
elt_str = ["H", "C", "N", "O", "F", "S", "Cl", "Br", "I"]
valences = [1, 4, 3, 2, 1, 6, 1, 1, 1]

def get_str(vec):
    s = ""
    for i in range(len(vec)):
        if vec[i] > 0:
            s += elt_str[i]
            if vec[i] > 1:
                s += str(vec[i])
    return s

def get_mass(vec, elements):
    return sum([vec[i]*elements[i] for i in range(len(vec))])

def get_DBE(fragment, valence):
    free_bond = float(2.0)
    for i in range(len(fragment)):
        free_bond += fragment[i] * (valence[i] - 2)
    free_bond /= float(2.0)
    return free_bond

def unbounded_knapsack_rec(m0, m1, elements):
    vec_frag = [0 for i in range(len(elements))]
    list_results = []
    unbounded_knapsack_rec_aux(m0, m1, vec_frag, len(elements)-1, elements, list_results)
    return list_results
        
def unbounded_knapsack_rec_aux(mass_min, mass_max, vec_fragment, idx, elements, list_results):
    if idx < 0 or mass_max < 0 or (mass_min > 0 and mass_max < elements[0]):
        return
    mass_i = elements[idx]
    if idx == 0:
        max_ai = math.floor(mass_max/mass_i)
        min_ai = max(0, math.ceil(mass_min/mass_i))
        for a_i in range(max_ai, min_ai-1, -1):
            vec_fragment[idx] = a_i
            if float(a_i)*mass_i <= mass_max and float(a_i)*mass_i >= mass_min:
                vec = [ai for ai in vec_fragment]
                list_results.append(vec)
        return
    max_ai = math.floor(mass_max/mass_i)
    for a_i in range(max_ai, -1, -1):
        vec_fragment[idx] = a_i
        unbounded_knapsack_rec_aux(mass_min-float(a_i)*mass_i, mass_max-float(a_i)*mass_i, vec_fragment, idx-1, elements, list_results)
    return

intervals = [
    ( 34.96751071,  34.97006625),
    ( 35.97413780,  35.97778836),
    ( 36.96406557,  36.96750599),
    ( 46.96648952,  46.97028744),
    ( 48.96255817,  48.96840119),
    ( 59.96022019,  59.97131577),
    ( 81.93308641,  81.93953315),
    ( 82.93831759,  82.95111397),
    ( 83.93024931,  83.93724265),
    ( 84.92634272,  84.97112964),
    ( 85.92419323,  85.93924313),
    ( 97.92364853,  97.93896563),
    ( 99.90729357,  99.94127719),
    (116.90200574, 116.90847942),
    (117.89455759, 117.92205637),
    (118.89897942, 118.90567754),
    (119.89648859, 119.91785117),
    (120.89523104, 120.90302932),
    (122.88755350, 122.90537266)]

for interval in intervals:
    m0 = interval[0]
    m1 = interval[1]
    print("{:12s}  {:12s}".format(str(m0), str(m1)))
    list_results = unbounded_knapsack_rec(m0, m1, elements)
    for vec in list_results:
        print("{:8s} {:12s} {}".format(get_str(vec), str(get_mass(vec, elements)), get_DBE(vec, valences)))
    print()


"""
 34.96751071   34.97006625
Cl        34.96885271 0.5

  35.9741378   35.97778836
HCl      35.9766777419 0.0

 36.96406557   36.96750599

 46.96648952   46.97028744
CCl       46.96885271 1.5

 48.96255817   48.96840119

 59.96022019   59.97131577
COS      59.9669853523 4.0

 81.93308641   81.93953315
CCl2      81.93770542 1.0

 82.93831759   82.95111397
H4Br     82.9496377276 -1.5
HCCl2    82.9455304519 0.5
FS2      82.94254461999999 4.5

 83.93024931   83.93724265

 84.92634272   84.97112964
H6Br     84.9652877914 -2.5
HNCl2    84.9486044593 0.0
H3CCl2   84.9611805157 -0.5
H2OSCl   84.9514881261 1.5
CF2Cl     84.96565903 0.5
H2O3Cl   84.96924664069999 -0.5
H2FS2    84.9581946838 3.5

 85.92419323   85.93924313
OCl2     85.9326200423 0.0

 97.92364853   97.93896563
H3OBr    97.936727318 -1.0
COCl2    97.9326200423 1.0
H2S3     97.93186225379999 6.0

 99.90729357   99.94127719
H2FBr    99.9323908238 -1.0
NOCl2    99.9356940497 0.5
HS2Cl    99.9208192019 4.0
HO2SCl   99.93857771649999 2.0

116.90200574  116.90847942
CCl3     116.90655813000001 0.5
H116     116.90770370039999 -57.0

117.89455759  117.92205637
H4ClBr   117.9184904376 -2.0
HCCl3    117.9143831619 0.0
OSCl2    117.9046907723 2.0
FS2Cl    117.91139733 4.0
H117     117.91552873229999 -57.5

118.89897942  118.90567754

119.89648859  119.91785117
HNCl3    119.91745716930001 -0.5
C2S3     119.91621219 9.0

120.89523104  120.90302932
OCl3     120.90147275230001 -0.5

 122.8875535  122.90537266
CSBr     122.89040833 3.5

"""
