I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

Periodic table

From Rosetta Code
Task
Periodic table
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
Details;

The representation of the periodic table may be represented in various way. The one presented in this challenge does have the following property : Lantanides and Aktinoides are all in a dedicated row, hence there is no element that is placed at 6, 3 nor 7, 3.

You may take a look at the atomic number repartitions here.

The atomic number is at least 1, at most 118.


See also



6502 Assembly[edit]

A lookup table is the simplest solution, for the following reasons:

  • The input value is guaranteed to be between 0 and 255
  • The data doesn't fit a pattern that the CPU can easily take advantage of.

Since the 6502 can't index an array larger than 256 bytes, we'll store all the "low bytes" in one table and all the "high bytes" in another. Both tables share the same index, so this lets us store up to 255 possible elements while taking the same amount of memory as a single table of 16-bit values. Right now, we can do this either way, but since we're close to 128 elements, may as well future-proof the code, right?

Lookup:      ;INPUT: X = atomic number of the element of interest.
LDA PeriodicTable_Column,x
STA $20  ;store column number in memory (I chose $20 arbitrarily, you can store it anywhere)
LDA PeriodicTable_Row,x
STA $21  ;store row number in memory
RTS
 
PeriodicTable_Column:
db $ff,$01,$18,$01,$02,$13,$14,$15,$16,$17,$18,...  ;I don't need to write them all out, the concept is self-explanatory enough.
PeriodicTable_Row:
db $ff,$01,$01,$02,$02,$02,$02,$02,$02,$02,$02,...

68000 Assembly[edit]

A lookup table is the simplest solution, as the data of interest doesn't have a pattern that a computer can take advantage of easily. It's quicker than using a formula, but takes up more memory as a result.

The table consists of 118 16-bit values. The high byte is the row number, the low byte is the column number. Both are stored as binary-coded decimal (i.e. hex values that look like base 10 numbers.)

Lookup:
;input: D0.W = the atomic number of interest.
LEA PeriodicTable,A0
ADD.W D0,D0 ;we're indexing a table of words, so double the index.
MOVE.W (A0,D0),D0 ;D0.W contains row number in the high byte and column number in the low byte.
RTS
 
PeriodicTable:
DC.W $FFFF ;padding since arrays start at zero in assembly.
DC.W $0101 ;HYDROGEN
DC.W $0118 ;HELIUM
DC.W $0201 ;LITHIUM
DC.W $0202 ;BERYLLIUM
DC.W $0213 ;BORON
DC.W $0214 ;CARBON
DC.W $0215 ;NITROGEN
DC.W $0216 ;OXYGEN
DC.W $0217 ;FLUORINE
DC.W $0218 ;NEON
;etc.

ALGOL 68[edit]

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;
# construct the positions of the elements in the table #
BEGIN
STRING periodic table = "- ="
+ "-- -----="
+ "-- -----="
+ "-----------------="
+ "-----------------="
+ "--8--------------="
+ "--9--------------="
;
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 = "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
ELIF p /= " " THEN
# 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, 59, 71, 72, 89, 90, 103, 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
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  59 -> 8,  6
Element  71 -> 8, 18
Element  72 -> 6,  4
Element  89 -> 9,  4
Element  90 -> 9,  5
Element 103 -> 9, 18
Element 113 -> 7, 13

Applesoft BASIC[edit]

This program borrows from the Python solution but only PRINTs the results of the tests shown in the task. Each row and column from the tests are PLOTted in a COLORful table.

0 GR:HOME:COLOR=11:FORR=1TO7:FORC=1TO2:GOSUB7:NEXTC,R:COLOR=7:FORR=4TO7:FORC=3+(R>5)TO12:GOSUB7:NEXTC,R:COLOR=13:FORR=2TO7:FORC=13TO18:GOSUB7:NEXTC,R
1 forr=2to7:forc=13to18:GOSUB7:NEXTC,R:COLOR=14:R=8:FORC=4TO18:GOSUB7:NEXTC:COLOR=12:R=9:FORC=4TO18:GOSUB7:NEXTC:R=9:FORC=4TO18:GOSUB7:NEXTC:Z=2:R=7:C=3:GOSUB7:COLOR=14:R=6:C=3:GOSUB7:COLOR=15
2 S=14:W=18:FORI=1TO7:READN(I),I(I):NEXT:DATA2,0,10,0,18,0,36,0,54,0,86,57,118,89,1,1,1,2,1,18,29,4,11,42,5,6,57,8,4,58,8,5,72,6,4,89,9,4,59,8,6,71,8,18,90,9,5,103,9,18
3 FORT=1TO8:READA,Y,X:GOSUB4:PRINTRIGHT$(" "+STR$(A),3)"->"R" "LEFT$(STR$(C)+" ",3);:GOSUB7:NEXTT:VTAB23:END
4 N=0:FORR=1TO7:P=N:N=N(R):IFA>NTHEN:NEXTR
5 E=N-P:K=A-P:IFI(R)AND(I(R)<=AANDA<=I(R)+S)THENR=R+2:C=K+1:RETURN
6 E=W-E:L=1+(N>2):C=K+E*(K>L):RETURN
7 K=C+(R=1ANDC=2)*16:VLINR*4+Z,R*4+2ATK*2+1:RETURN


BASIC[edit]

QBasic[edit]

Works with: QBasic version 1.1
Works with: QuickBasic version 4.5
Translation of: FreeBASIC
SUB MostarPos (N)
DIM a(7)
RESTORE a:
FOR x = 0 TO 7: READ a(x): NEXT x
DIM b(7)
RESTORE b:
FOR x = 0 TO 7: READ b(x): NEXT x
 
I = 7
WHILE a(I) > N
I = I - 1
WEND
M = N + b(I)
R = (M \ 18) + 1
C = (M MOD 18) + 1
PRINT USING "Atomic number ### -> #_, ##"; N; R; C
END SUB
 
DIM Element(0 TO 12)
RESTORE elements
elements:
DATA 1, 2, 29, 42, 57, 58, 59, 71, 72, 89, 90, 103, 113
FOR x = 0 TO 12: READ Element(x): NEXT x
 
FOR I = 0 TO UBOUND(Element)
MostarPos (Element(I))
NEXT I
 
a:
DATA 1, 2, 5, 13, 57, 72, 89, 104
b:
DATA -1, 15, 25, 35, 72, 21, 58, 7
Output:
Same as FreeBASIC entry.

BASIC256[edit]

Translation of: FreeBASIC
subroutine MostarPos(N)
dim A = { 1, 2, 5, 13, 57, 72, 89, 104}
dim B = {-1, 15, 25, 35, 72, 21, 58, 7}
I = 7
while A[I] > N
I -= 1
end while
M = N + B[I]
R = (M \ 18) +1
C = (M % 18) +1
print "Atomic number "; rjust(N,3); "-> "; R ; ", "; C
end subroutine
 
dim Element = {1, 2, 29, 42, 57, 58, 59, 71, 72, 89, 90, 103, 113}
for I = 0 to Element[?]-1
call MostarPos(Element[I])
next I
Output:
Same as FreeBASIC entry.

Gambas[edit]

Sub MostarPos(N As Integer)       'Mostrar fila y columna para el elemento
Dim M, I, R, C As Integer
Dim A As Integer[] = [1, 2, 5, 13, 57, 72, 89, 104] 'magic numbers
Dim B As Integer[] = [-1, 15, 25, 35, 72, 21, 58, 7]
I = 7
While A[I] > N
Dec I
Wend
M = N + B[I]
R = (M \ 18) + 1
C = (M Mod 18) + 1
Print "Atomic number "; Format(N, "###"); " -> "; R; ", "; C
End
 
Public Sub Main()
 
Dim Element As Integer[] = [1, 2, 29, 42, 57, 58, 59, 71, 72, 89, 90, 103, 113]
For e As Integer = 0 To 12
MostarPos(Element[e])
Next
 
End
Output:
Same as FreeBASIC entry.

Run BASIC[edit]

Works with: Just BASIC
Works with: Liberty BASIC
Translation of: FreeBASIC
dim Element(12)
Element(0) = 1
Element(1) = 2
Element(2) = 29
Element(3) = 42
Element(4) = 57
Element(5) = 58
Element(6) = 59
Element(7) = 71
Element(8) = 72
Element(9) = 89
Element(10) = 90
Element(11) = 103
Element(12) = 113
for e = 0 to 12
call MostarPos Element(e)
next e
 
sub MostarPos N
dim A(7)
A(0) = 1
A(1) = 2
A(2) = 5
A(3) = 13
A(4) = 57
A(5) = 72
A(6) = 89
A(7) = 104
dim B(7)
B(0) = -1
B(1) = 15
B(2) = 25
B(3) = 35
B(4) = 72
B(5) = 21
B(6) = 58
B(7) = 7
 
I = 7
while A(I) > N
I = I - 1
wend
M = N + B(I)
R = int(M / 18) +1
C = (M mod 18) +1
print "Atomic number "; using("###", N); " -> "; R; ", "; C
end sub
Output:
Same as FreeBASIC entry.

True BASIC[edit]

Translation of: FreeBASIC
SUB MostarPos (n)
DIM a(0 TO 7)
LET a(0) = 1
LET a(1) = 2
LET a(2) = 5
LET a(3) = 13
LET a(4) = 57
LET a(5) = 72
LET a(6) = 89
LET a(7) = 104
DIM b(0 TO 7)
LET b(0) = -1
LET b(1) = 15
LET b(2) = 25
LET b(3) = 35
LET b(4) = 72
LET b(5) = 21
LET b(6) = 58
LET b(7) = 7
LET i = 7
DO WHILE a(i) > n
LET i = i - 1
LOOP
LET m = n + b(i)
LET r = IP(m / 18) + 1
LET c = REMAINDER(m, 18) + 1
PRINT USING "Atomic number ###": n;
PRINT " ->"; r; c
END SUB
 
DIM element(0 TO 12)
LET element(0) = 1
LET element(1) = 2
LET element(2) = 29
LET element(3) = 42
LET element(4) = 57
LET element(5) = 58
LET element(6) = 59
LET element(7) = 71
LET element(8) = 72
LET element(9) = 89
LET element(10) = 90
LET element(11) = 103
LET element(12) = 113
FOR e = 0 TO UBOUND(element)
CALL MostarPos (element(e))
NEXT e
END
Output:
Similar to FreeBASIC entry.

XBasic[edit]

Works with: Windows XBasic
Translation of: FreeBASIC
PROGRAM  "Periodic table"
 
DECLARE FUNCTION Entry ()
DECLARE FUNCTION MostarPos (N)
 
FUNCTION Entry ()
DIM Element[12]
Element[0] = 1
Element[1] = 2
Element[2] = 29
Element[3] = 42
Element[4] = 57
Element[5] = 58
Element[6] = 59
Element[7] = 71
Element[8] = 72
Element[9] = 89
Element[10] = 90
Element[11] = 103
Element[12] = 113
 
FOR e = 0 TO 12 'UBOUND (Element())
MostarPos (Element[e])
NEXT
 
END FUNCTION
 
FUNCTION MostarPos (N)
DIM A[7]
A[0] = 1
A[1] = 2
A[2] = 5
A[3] = 13
A[4] = 57
A[5] = 72
A[6] = 89
A[7] = 104
DIM B[7]
B[0] = -1
B[1] = 15
B[2] = 25
B[3] = 35
B[4] = 72
B[5] = 21
B[6] = 58
B[7] = 7
I = 7
DO WHILE A[I] > N
DEC I
LOOP
M = N + B[I]
R = (M \ 18) + 1
C = (M MOD 18) + 1
PRINT "Atomic number "; FORMAT$ ("###", N); " ->"; R; ","; C
 
END FUNCTION
END PROGRAM
Output:
Similar to FreeBASIC entry.

Yabasic[edit]

Translation of: FreeBASIC
// Rosetta Code problem: http://rosettacode.org/wiki/Periodic_table
// by Jjuanhdez, 06/2022
 
dim Element(12)
Element(0) = 1 : Element(1) = 2
Element(2) = 29 : Element(3) = 42
Element(4) = 57 : Element(5) = 58
Element(6) = 59 : Element(7) = 71
Element(8) = 72 : Element(9) = 89
Element(10) = 90
Element(11) = 103 : Element(12) = 113
for e = 0 to arraysize(Element(),1)
MostarPos (Element(e))
next e
end
 
sub MostarPos (N)
dim A(7)
A(0) = 1 : A(1) = 2
A(2) = 5 : A(3) = 13
A(4) = 57 : A(5) = 72
A(6) = 89 : A(7) = 104
dim B(7)
B(0) = -1 : B(1) = 15
B(2) = 25 : B(3) = 35
B(4) = 72 : B(5) = 21
B(6) = 58 : B(7) = 7
 
I = 7
while A(I) > N
I = I - 1
wend
M = N + B(I)
R = int(M / 18) +1
C = mod(M, 18) +1
print "Atomic number ", N using("###"), " -> ", R, ", ", C
end sub
Output:
Same as FreeBASIC entry.

FreeBASIC[edit]

Translation of: XPL0
Sub MostarPos(N As Integer)
Dim As Integer M, I, R, C
Dim As Integer A(0 To 7) = { 1, 2, 5, 13, 57, 72, 89, 104} 'magic numbers
Dim As Integer B(0 To 7) = {-1, 15, 25, 35, 72, 21, 58, 7}
I = 7
While A(I) > N
I -= 1
Wend
M = N + B(I)
R = (M \ 18) +1
C = (M Mod 18) +1
Print Using "Atomic number ### -> #_, ##"; N; R; C
End Sub
 
Dim As Integer Element(0 To 12) = {1, 2, 29, 42, 57, 58, 59, 71, 72, 89, 90, 103, 113}
For I As Integer = 0 To Ubound(Element)
MostarPos(Element(I))
Next I
Output:
Atomic number   1 -> 1, 1 
Atomic number   2 -> 1, 18
Atomic number  29 -> 4, 11
Atomic number  42 -> 5, 6 
Atomic number  57 -> 8, 4 
Atomic number  58 -> 8, 5 
Atomic number  59 -> 8, 6 
Atomic number  71 -> 8, 18
Atomic number  72 -> 6, 4 
Atomic number  89 -> 9, 4 
Atomic number  90 -> 9, 5 
Atomic number 103 -> 9, 18
Atomic number 113 -> 7, 13

FutureBasic[edit]

Old fashioned way:

 
include "NSLog.incl"
 
local fn PeriodicTable( n as NSInteger ) as CFDictionaryRef
NSInteger i, row = 0, start = 0, finish, limits(6,6)
CFDictionaryRef dict = NULL
 
if n < 1 or n > 118 then NSLog( @"Atomic number is out of range." ) : exit fn
if n == 1 then dict = @{@"row":@1, @"col":@1}  : exit fn
if n == 2 then dict = @{@"row":@1, @"col":@18} : exit fn
if n >= 57 and n <= 71 then dict = @{@"row":@8, @"col":fn NumberWithInteger( n - 53 )} : exit fn
if n >= 89 and n <= 103 then dict = @{@"row":@9, @"col":fn NumberWithInteger( n - 85 )} : exit fn
 
limits(0,0) = 3  : limits(0,1) = 10
limits(1,0) = 11 : limits(1,1) = 18
limits(2,0) = 19 : limits(2,1) = 36
limits(3,0) = 37 : limits(3,1) = 54
limits(4,0) = 55 : limits(4,1) = 86
limits(5,0) = 87 : limits(5,1) = 118
 
for i = 0 to 5
if ( n >= limits(i,0) and n <= limits(i,1) )
row = i + 2
start = limits(i,0)
finish = limits(i,1)
break
end if
next
 
if ( n < start + 2 or row == 4 or row == 5 )
dict = @{@"row":fn NumberWithInteger(row), @"col":fn NumberWithInteger( n - start + 1 )} : exit fn
end if
dict = @{@"row":fn NumberWithInteger(row), @"col":fn NumberWithInteger( n - finish + 18 )}
end fn = dict
 
 
local fn BuildTable
NSInteger i, count
CFArrayRef numbers = @[@1, @2, @29, @42, @57, @58, @59, @71, @72, @89, @90, @103, @113]
 
count = fn ArrayCount( numbers )
 
for i = 0 to count -1
CFDictionaryRef coordinates = fn PeriodicTable( fn NumberIntegerValue( numbers[i] ) )
NSLog( @"Atomic number %3d -> (%d, %d)", fn NumberIntegerValue( numbers[i] ), fn NumberIntegerValue( coordinates[@"row"] ), fn NumberIntegerValue( coordinates[@"col"] ) )
next
end fn
 
fn BuildTable
 
HandleEvents
 
Output:
Atomic number   1 -> (1, 1)
Atomic number   2 -> (1, 18)
Atomic number  29 -> (4, 11)
Atomic number  42 -> (5, 6)
Atomic number  57 -> (8, 4)
Atomic number  58 -> (8, 5)
Atomic number  59 -> (8, 6)
Atomic number  71 -> (8, 18)
Atomic number  72 -> (6, 4)
Atomic number  89 -> (9, 4)
Atomic number  90 -> (9, 5)
Atomic number 103 -> (9, 18)
Atomic number 113 -> (7, 13)

Modern way. (Too bad you can no longer upload images to Rosetta Code.)

 
_window = 1
 
void local fn BuildPeriodicTableArrays
 
CFArrayRef periodicArr = @[@"",¬
@"H", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"He",¬
@"Li", @"Be", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"B", @"C", @"N", @"O", @"F", @"Ne",¬
@"Na", @"Mg", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"", @"Al", @"Si", @"P", @"S", @"Cl", @"Ar",¬
@"K", @"Ca", @"Sc", @"Ti", @"V", @"Cr", @"Mn", @"Fe", @"Co", @"Ni", @"Cu", @"Zn", @"Ga", @"Ge", @"As", @"Se", @"Br", @"Kr",¬
@"Rb", @"Sr", @"Y", @"Zr", @"Nb", @"Mo", @"Tc", @"Ru", @"Rh", @"Pd", @"Ag", @"Cd", @"In", @"Sn", @"Sb", @"Te", @"I", @"Xe",¬
@"Cs", @"Ba", @"Lu", @"Hf", @"Ta", @"W", @"Re", @"Os", @"Ir", @"Pt", @"Au", @"Hg", @"Tl", @"Pb", @"Bi", @"Po", @"At", @"Rn",¬
@"Fr", @"Ra", @"Lr", @"Rf", @"Db", @"Sg", @"Bh", @"Hs", @"Mt", @"Ds", @"Rg", @"Cn", @"Nh", @"Fl", @"Mc", @"Lv", @"Ts", @"Og",¬
@"", @"", @"La", @"Ce", @"Pr", @"Nd", @"Pm", @"Sm", @"Eu", @"Gd", @"Tb", @"Dy", @"Ho", @"Er", @"Tm", @"Yb", @"", @"",¬
@"", @"", @"Ac", @"Th", @"Pa", @"U", @"NP", @"Pu", @"Am", @"Cm", @"Bk", @"Cf", @"Es", @"Fm", @"Md", @"No", @"", @""]
AppSetProperty( @"periodicTable", periodicArr )
 
CFArrayRef numbersArr = @[@"",¬
@"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", @"71", @"72", @"73", @"74", @"75", @"76", @"77", @"78", @"79", @"80", @"81", @"82", @"83", @"84", @"85", @"86",¬
@"87", @"88", @"103", @"104", @"105", @"106", @"107", @"108", @"109", @"110", @"111", @"112", @"113", @"114", @"114", @"116", @"117", @"118",¬
@"", @"", @"57", @"58", @"59", @"60", @"61", @"62", @"63", @"64", @"65", @"66", @"67", @"68", @"59", @"70", @"", @"",¬
@"", @"", @"89", @"90", @"91", @"92", @"93", @"94", @"95", @"96", @"97", @"98", @"99", @"100", @"101", @"102", @"", @""]
AppSetProperty( @"periodicNumbers", numbersArr )
end fn
 
 
void local fn BuildWindow
NSInteger i, j, row
CGRect r
CFArrayRef periodicArr, numbersArr
CFStringRef tempStr
 
periodicArr = fn AppProperty( @"periodicTable" )
numbersArr = fn AppProperty( @"periodicNumbers" )
 
window _window, @"Periodic Table", ( 0, 0, 700, 400 )
WindowSetBackgroundColor( _window, fn ColorWhite )
 
j = 0 : row = 350
r = fn CGRectMake( 10, row, 36, 40 )
for i = 1 to 162
if fn StringIsEqual( periodicArr[i], @"" ) then tempStr = @"" else tempStr = fn StringWithFormat( @"%@\n%@", numbersArr[i], periodicArr[i] )
textfield i,, tempStr, r, _window
TextFieldSetBackgroundColor( i, fn ColorBlue )
TextFieldSetTextColor( i, fn ColorWhite )
ControlSetFontWithName( i, @"Menlo", 12.0 )
ControlSetAlignment(i, NSTextAlignmentCenter )
r = fn CGRectOffset( r, 38, 0 )
j++
if ( j == 18 )
row = row - 42
r = fn CGRectMake( 10, row, 36, 40 )
j = 0
end if
next
 
for i = 1 to 162
if fn StringIsEqual( fn ControlStringValue( i ), @"" ) then ViewRemoveFromSuperview( i )
next
end fn
 
fn BuildPeriodicTableArrays
fn BuildWindow
 
HandleEvents
 
Output:
[Sorry, screenshot can't be uploaded.]

Go[edit]

Translation of: Wren
package main
 
import (
"fmt"
"log"
)
 
var limits = [][2]int{
{3, 10}, {11, 18}, {19, 36}, {37, 54}, {55, 86}, {87, 118},
}
 
func periodicTable(n int) (int, int) {
if n < 1 || n > 118 {
log.Fatal("Atomic number is out of range.")
}
if n == 1 {
return 1, 1
}
if n == 2 {
return 1, 18
}
if n >= 57 && n <= 71 {
return 8, n - 53
}
if n >= 89 && n <= 103 {
return 9, n - 85
}
var row, start, end int
for i := 0; i < len(limits); i++ {
limit := limits[i]
if n >= limit[0] && n <= limit[1] {
row, start, end = i+2, limit[0], limit[1]
break
}
}
if n < start+2 || row == 4 || row == 5 {
return row, n - start + 1
}
return row, n - end + 18
}
 
func main() {
for _, n := range []int{1, 2, 29, 42, 57, 58, 59, 71, 72, 89, 90, 103, 113} {
row, col := periodicTable(n)
fmt.Printf("Atomic number %3d -> %d, %-2d\n", n, row, col)
}
}
Output:
Atomic number   1 -> 1, 1 
Atomic number   2 -> 1, 18
Atomic number  29 -> 4, 11
Atomic number  42 -> 5, 6 
Atomic number  57 -> 8, 4 
Atomic number  58 -> 8, 5 
Atomic number  59 -> 8, 6 
Atomic number  71 -> 8, 18
Atomic number  72 -> 6, 4 
Atomic number  89 -> 9, 4 
Atomic number  90 -> 9, 5 
Atomic number 103 -> 9, 18
Atomic number 113 -> 7, 13

J[edit]

Basically, here, we want a lookup table. For example:

PT=: (' ',.~[;._2) {{)n
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
}}
 
ptrc=: {{
tokens=. (#~ (3>#)@> * */@(tolower~:toupper)@>) ~.,;:,PT
ndx=. (>' ',L:0' ',L:0~tokens) {[email protected]@E."1 ,PT
Lantanoidi=. ndx{+/\'*'=,PT
Aktinoidi=. ndx{+/\'-'=,PT
j=. 13|3*Lantanoidi+3*Aktinoidi
k=. {:$PT
0,}."1/:~j,.(<.ndx%k),.1+(/:[email protected]~. i. ])k|ndx
}}
 
rowcol=: ptrc''

In other words, start with a hand crafted representation of the periodic table. Elements here are tokens with 1 or 2 letters. Locate the position of each token in the table. Get an initial row and column number from the character positions in the table. Translate character column to periodic table column by enumerating the unique (sorted) list of column numbers and using the index in that list. Character row was already periodic table row. Most elements here were already in atomic number order, and we can fix the exceptions by temporarily prefixing each row,col value and sorting. (Here, we use 0 for the first 56 elements, 3 for the next 17 elements (after Lantanoidi, before Aktinoidi), 12 for the next 15 (after Aktinoidi), 2 for the next 15 (the Lantanoidi) and 11 for the final 15 elements (the Aktinoidi).)

Thus:

   1 2 29 42 57 58 72 89 { rowcol
1 1
1 18
4 11
5 6
8 4
8 5
6 4
9 4


Julia[edit]

Translation of: Wren
const limits = [3:10, 11:18, 19:36, 37:54, 55:86, 87:118]
 
function periodic_table(n)
(n < 1 || n > 118) && error("Atomic number is out of range.")
n == 1 && return [1, 1]
n == 2 && return [1, 18]
57 <= n <= 71 && return [8, n - 53]
89 <= n <= 103 && return [9, n - 85]
row, limitstart, limitstop = 0, 0, 0
for i in eachindex(limits)
if limits[i].start <= n <= limits[i].stop
row, limitstart, limitstop = i + 1, limits[i].start, limits[i].stop
break
end
end
return (n < limitstart + 2 || row == 4 || row == 5) ?
[row, n - limitstart + 1] : [row, n - limitstop + 18]
end
 
for n in [1, 2, 29, 42, 57, 58, 59, 71, 72, 89, 90, 103, 113]
rc = periodic_table(n)
println("Atomic number ", lpad(n, 3), " -> ($(rc[1]), $(rc[2]))")
end
 
Output:
Atomic number   1 -> (1, 1)
Atomic number   2 -> (1, 18)
Atomic number  29 -> (4, 11)
Atomic number  42 -> (5, 6)
Atomic number  57 -> (8, 4)
Atomic number  58 -> (8, 5)
Atomic number  59 -> (8, 6)
Atomic number  71 -> (8, 18)
Atomic number  72 -> (6, 4)
Atomic number  89 -> (9, 4)
Atomic number  90 -> (9, 5)
Atomic number 103 -> (9, 18)
Atomic number 113 -> (7, 13)

Perl[edit]

Translation of: Raku
use strict;
use warnings; no warnings 'uninitialized';
use feature 'say';
use List::Util <sum head>;
 
sub divmod { int $_[0]/$_[1], $_[0]%$_[1] }
 
my $b = 18;
my(@offset,@span,$cnt);
push @span, ($cnt++) x $_ for <1 3 8 44 15 17 15 15>;
@offset = (16, 10, 10, (2*$b)+1, (-2*$b)-15, (2*$b)+1, (-2*$b)-15);
 
for my $n (<1 2 29 42 57 58 72 89 90 103 118>) {
printf "%3d: %2d, %2d\n", $n, map { $_+1 } divmod $n-1 + sum(head $span[$n-1], @offset), $b;
}
Output:
  1:  1,  1
  2:  1, 18
 29:  4, 11
 42:  5,  6
 57:  8,  4
 58:  8,  5
 72:  6,  4
 89:  9,  4
 90:  9,  5
103:  9, 18

Phix[edit]

with javascript_semantics
constant match_wp = false

function prc(integer n)
    constant t = {0,2,10,18,36,54,86,118,119}
    integer row = abs(binary_search(n,t,true))-1,
            col = n-t[row]
    if col>1+(row>1) then
        col = 18-(t[row+1]-n)
        if match_wp then
            if col<=2 then return {row+2,col+14} end if
        else -- matches above ascii:
            if col<=2+(row>5) then return {row+2,col+15} end if
        end if
    end if
    return {row,col}
end function

sequence pt = repeat(repeat("   ",19),10)
pt[1][2..$] = apply(true,sprintf,{{"%3d"},tagset(18)})  -- column headings
for i=1 to 9 do pt[i+1][1] = sprintf("%3d",i) end for -- row numbers
for i=1 to 118 do
    integer {r,c} = prc(i)
    pt[r+1][c+1] = sprintf("%3d",i)
end for
if not match_wp then -- (ascii only:)
    pt[7][4] = " L*"
    pt[8][4] = " A*"
    pt[9][2..4] = {"Lanthanide:"}
    pt[10][2..4] = {"  Actinide:"}
end if
printf(1,"%s\n",{join(apply(true,join,{pt,{"|"}}),"\n")})
Output:

With match_wp set to true:

   |  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15| 16| 17| 18
  1|  1|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |  2
  2|  3|  4|   |   |   |   |   |   |   |   |   |   |  5|  6|  7|  8|  9| 10
  3| 11| 12|   |   |   |   |   |   |   |   |   |   | 13| 14| 15| 16| 17| 18
  4| 19| 20| 21| 22| 23| 24| 25| 26| 27| 28| 29| 30| 31| 32| 33| 34| 35| 36
  5| 37| 38| 39| 40| 41| 42| 43| 44| 45| 46| 47| 48| 49| 50| 51| 52| 53| 54
  6| 55| 56| 71| 72| 73| 74| 75| 76| 77| 78| 79| 80| 81| 82| 83| 84| 85| 86
  7| 87| 88|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118
  8|   |   | 57| 58| 59| 60| 61| 62| 63| 64| 65| 66| 67| 68| 69| 70|   |
  9|   |   | 89| 90| 91| 92| 93| 94| 95| 96| 97| 98| 99|100|101|102|   |

Or with match_wp false:

   |  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15| 16| 17| 18
  1|  1|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |  2
  2|  3|  4|   |   |   |   |   |   |   |   |   |   |  5|  6|  7|  8|  9| 10
  3| 11| 12|   |   |   |   |   |   |   |   |   |   | 13| 14| 15| 16| 17| 18
  4| 19| 20| 21| 22| 23| 24| 25| 26| 27| 28| 29| 30| 31| 32| 33| 34| 35| 36
  5| 37| 38| 39| 40| 41| 42| 43| 44| 45| 46| 47| 48| 49| 50| 51| 52| 53| 54
  6| 55| 56| L*| 72| 73| 74| 75| 76| 77| 78| 79| 80| 81| 82| 83| 84| 85| 86
  7| 87| 88| A*|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118
  8|Lanthanide:| 57| 58| 59| 60| 61| 62| 63| 64| 65| 66| 67| 68| 69| 70| 71
  9|  Actinide:| 89| 90| 91| 92| 93| 94| 95| 96| 97| 98| 99|100|101|102|103

Python[edit]

A solution trying hard not to encode too much data about the table.

 
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 ''))
 
 

Raku[edit]

my $b = 18;
my @offset = 16, 10, 10, (2×$b)+1, (-2×$b)-15, (2×$b)+1, (-2×$b)-15;
my @span = flat ^8 Zxx <1 3 8 44 15 17 15 15>;
 
for <1 2 29 42 57 58 72 89 90 103> -> $n {
printf "%3d: %2d, %2d\n", $n, map {$_+1}, ($n-1 + [+] @offset.head(@span[$n-1])).polymod($b).reverse;
}
Output:
  1:  1,  1
  2:  1, 18
 29:  4, 11
 42:  5,  6
 57:  8,  4
 58:  8,  5
 72:  6,  4
 89:  9,  4
 90:  9,  5
103:  9, 18

Wren[edit]

Library: Wren-fmt

There is a discrepancy between how the periodic table is arranged in the Wikipedia article and how it is arranged in the task description. I've used the latter in the following script.

import "./fmt" for Fmt
 
var limits = [3..10, 11..18, 19..36, 37..54, 55..86, 87..118]
 
var periodicTable = Fn.new { |n|
if (n < 1 || n > 118) Fiber.abort("Atomic number is out of range.")
if (n == 1) return [1, 1]
if (n == 2) return [1, 18]
if (n >= 57 && n <= 71) return [8, n - 53]
if (n >= 89 && n <= 103) return [9, n - 85]
var row
var start
var end
for (i in 0...limits.count) {
var limit = limits[i]
if (n >= limit.from && n <= limit.to) {
row = i + 2
start = limit.from
end = limit.to
break
}
}
if (n < start + 2 || row == 4 || row == 5) return [row, n - start + 1]
return [row, n - end + 18]
}
 
for (n in [1, 2, 29, 42, 57, 58, 59, 71, 72, 89, 90, 103, 113]) {
var rc = periodicTable.call(n)
Fmt.print("Atomic number $3d -> $d, $-2d", n, rc[0], rc[1])
}
Output:
Atomic number   1 -> 1, 1 
Atomic number   2 -> 1, 18
Atomic number  29 -> 4, 11
Atomic number  42 -> 5, 6 
Atomic number  57 -> 8, 4 
Atomic number  58 -> 8, 5 
Atomic number  59 -> 8, 6 
Atomic number  71 -> 8, 18
Atomic number  72 -> 6, 4 
Atomic number  89 -> 9, 4 
Atomic number  90 -> 9, 5 
Atomic number 103 -> 9, 18
Atomic number 113 -> 7, 13

XPL0[edit]

proc ShowPosn(N);       \Show row and column for element
int N, M, A, B, I, R, C;
[A:= [ 1, 2, 5, 13, 57, 72, 89, 104]; \magic numbers
B:= [-1, 15, 25, 35, 72, 21, 58, 7];
I:= 7;
while A(I) > N do I:= I-1;
M:= N + B(I);
R:= M/18 +1;
C:= rem(0) +1;
IntOut(0, N); Text(0, " -> ");
IntOut(0, R); Text(0, ", ");
IntOut(0, C); CrLf(0);
];
 
int Element, I;
[Element:= [1, 2, 29, 42, 57, 58, 72, 89, 90, 103];
for I:= 0 to 10-1 do ShowPosn(Element(I));
]
Output:
1 -> 1, 1
2 -> 1, 18
29 -> 4, 11
42 -> 5, 6
57 -> 8, 4
58 -> 8, 5
72 -> 6, 4
89 -> 9, 4
90 -> 9, 5
103 -> 9, 18