aboutsummaryrefslogtreecommitdiff
path: root/mendeleev.py
blob: 21bc6006241fc8a8946ef842c6ea571d048422d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import sys


# fmt: off
ELEMENTS = [
  "Ac", "Ag", "Al", "Am", "Ar", "As", "At", "Au", "B", "Ba", "Be", "Bh",
  "Bi", "Bk", "Br", "C", "Ca", "Cd", "Ce", "Cf", "Cl", "Cm", "Cn", "Co",
  "Cr", "Cs", "Cu", "Db", "Ds", "Dy", "Er", "Es", "Eu", "F", "Fe", "Fl",
  "Fm", "Fr", "Ga", "Gd", "Ge", "H", "He", "Hf", "Hg", "Ho", "Hs", "I",
  "In", "Ir", "K", "Kr", "La", "Li", "Lr", "Lu", "Lv", "Mc", "Md", "Mg",
  "Mn", "Mo", "Mt", "N", "Na", "Nb", "Nd", "Ne", "Nh", "Ni", "No", "Np",
  "O", "Og", "Os", "P", "Pa", "Pb", "Pd", "Pm", "Po", "Pr", "Pt", "Pu",
  "Ra", "Rb", "Re", "Rf", "Rg", "Rh", "Rn", "Ru", "S", "Sb", "Sc", "Se",
  "Sg", "Si", "Sm", "Sn", "Sr", "Ta", "Tb", "Tc", "Te", "Th", "Ti", "Tl",
  "Tm", "Ts", "U", "V", "W", "Xe", "Y", "Yb", "Zn", "Zr"
]
# fmt: on

elements = [el.lower().encode() for el in ELEMENTS]


def search(start, length, shift, char):
    upper = start + length
    lower = start
    while lower < upper:
        mid = int((lower + upper) / 2)
        if elements[mid][shift] < char:
            lower = mid + 1
        else:
            upper = mid

    if lower == start + length:
        return (0, 0)

    if elements[lower][shift] != char:
        return (0, 0)

    upper = start + length
    start = lower
    while lower < upper:
        mid = int((lower + upper) / 2)
        if char < elements[mid][shift]:
            upper = mid
        else:
            lower = mid + 1

    length = upper - start

    return (start, length)


def divide(tail):
    result = []

    start = 0
    length = len(ELEMENTS)
    shift = 0

    while shift < len(tail):
        start, length = search(start, length, shift, tail[shift])
        if length == 0:
            break

        shift += 1
        if len(elements[start]) == shift:
            result.append((ELEMENTS[start], tail[shift:]))
            start += 1
            length -= 1

    return result or [("?", tail[1:])]


def advance(els, tail):
    return [(els + [e], t) for (e, t) in divide(tail)]


def explode(word):
    result = [([], word.lower().encode())]
    while result[0][1]:
        new = []
        for res in result:
            if res[1]:
                adv = advance(*res)
                new.extend(adv)
            else:
                new.append(res)

        result = new

    return [els for els, _ in result]


for w in sys.argv[1:]:
    print(w + ":")
    for f in filter(None, explode(w)):
        print(" " + " ".join(f))