47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
def perta(atomic) -> (int, int):
|
|
|
|
NOBLES = 2, 10, 18, 36, 54, 86, 118
|
|
INTERTWINED = 0, 0, 0, 0, 0, 57, 89
|
|
INTERTWINING_SIZE = 14
|
|
LINE_WIDTH = 18
|
|
|
|
prev_noble = 0
|
|
for row, noble in enumerate(NOBLES):
|
|
if atomic <= noble: # we are at the good row. We now need to determine the column
|
|
nb_elem = noble - prev_noble # number of elements on that row
|
|
rank = atomic - prev_noble # rank of the input element among elements
|
|
if INTERTWINED[row] and INTERTWINED[row] <= atomic <= INTERTWINED[row] + INTERTWINING_SIZE: # lantanides or actinides
|
|
row += 2
|
|
col = rank + 1
|
|
else: # not a lantanide nor actinide
|
|
# handle empty spaces between 1-2, 4-5 and 12-13.
|
|
nb_empty = LINE_WIDTH - nb_elem # spaces count as columns
|
|
inside_left_element_rank = 2 if noble > 2 else 1
|
|
col = rank + (nb_empty if rank > inside_left_element_rank else 0)
|
|
break
|
|
prev_noble = noble
|
|
return row+1, col
|
|
|
|
|
|
|
|
# small test suite
|
|
|
|
TESTS = {
|
|
1: (1, 1),
|
|
2: (1, 18),
|
|
29: (4,11),
|
|
42: (5, 6),
|
|
58: (8, 5),
|
|
59: (8, 6),
|
|
57: (8, 4),
|
|
71: (8, 18),
|
|
72: (6, 4),
|
|
89: (9, 4),
|
|
90: (9, 5),
|
|
103: (9, 18),
|
|
}
|
|
|
|
for input, out in TESTS.items():
|
|
found = perta(input)
|
|
print('TEST:{:3d} -> '.format(input) + str(found) + (f' ; ERROR: expected {out}' if found != out else ''))
|