Periodic table
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Display the row and column in the periodic table of the given atomic number.
- The periodic table
Let us consider the following periodic table representation.
__________________________________________________________________________ | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | | | |1 H He | | | |2 Li Be B C N O F Ne | | | |3 Na Mg Al Si P S Cl Ar | | | |4 K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr | | | |5 Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Xe | | | |6 Cs Ba * Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn | | | |7 Fr Ra ° Rf Db Sg Bh Hs Mt Ds Rg Cn Nh Fl Mc Lv Ts Og | |__________________________________________________________________________| | | | | |8 Lantanoidi* La Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu | | | |9 Aktinoidi° Ak Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr | |__________________________________________________________________________|
- Example test cases;
-
1
->1 1
-
2
->1 18
-
29
->4 11
-
42
->5 6
-
57
->8 4
-
58
->8 5
-
72
->6 4
-
89
->9 4
Note that atomic values corresponding to Lantanoidi (57 to 71) and Aktinoidi (89 to 103) are to be mapped in their own rows.
- See also
- the periodic table
- This task was an idea from CompSciFact
- The periodic table in ascii that was used as template
ALGOL 68
<lang algol68>BEGIN # display the period and group number of an element, #
# given its atomic number # INT max atomic number = 118; # highest known element # # the positions are stored as: # # ( group number * group multiplier ) + period # INT group multiplier = 100; [ 1 : max atomic number ]INT position; STRING periodic table = "- =" + "-- -----=" + "-- -----=" + "-----------------=" + "-----------------=" + "--8--------------=" + "--9--------------=" ; # construct the positions of the elements in the table # # from the outline # BEGIN INT period := 1; INT group := 1; INT element := 1; FOR t FROM LWB periodic table TO UPB periodic table DO CHAR p = periodic table[ t ]; IF p = " " THEN # no element at this position # SKIP ELIF p = "8" OR p = "9" THEN # lantanoids or actinoids # INT series period = IF p = "8" THEN 8 ELSE 9 FI; INT series group := 4; FOR e TO 15 DO position[ element ] := ( group multiplier * series group ) + series period; element +:= 1; series group +:= 1 OD ELSE # there is a single element here # position[ element ] := ( group multiplier * group ) + period; element +:= 1; IF p = "=" THEN # final element of the period # period +:= 1; group := 0 FI FI; group +:= 1 OD END; # display the period and group numbers of test elements # []INT test = ( 1, 2, 29, 42, 57, 58, 72, 89, 113 ); FOR t FROM LWB test TO UPB test DO INT e = test[ t ]; IF e < LWB position OR e > UPB position THEN print( ( "Invalid element: ", whole( e, 0 ), newline ) ) ELSE INT period = position[ e ] MOD group multiplier; INT group = position[ e ] OVER group multiplier; print( ( "Element ", whole( e, -3 ) , " -> ", whole( period, 0 ), ", ", whole( group, -2 ) , newline ) ) FI OD
END</lang>
- Output:
Element 1 -> 1, 1 Element 2 -> 1, 18 Element 29 -> 4, 11 Element 42 -> 5, 6 Element 57 -> 8, 4 Element 58 -> 8, 5 Element 72 -> 6, 4 Element 89 -> 9, 4 Element 113 -> 7, 13
Python
A solution trying hard not to encode too much data about the table.
<lang 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 ))
</lang>