Periodic table: Difference between revisions
→{{header|ASIC}}: Added. |
→{{header|Minimal BASIC}}: Added. |
||
Line 486:
{{out}}
<pre>Same as FreeBASIC entry.</pre>
=== {{header|Minimal BASIC}} ===
{{trans|Nascom BASIC}}
{{works with|Commodore BASIC|3.5}}
<lang gwbasic>
10 REM Periodic table
20 GOSUB 200
30 FOR J = 0 TO 9
40 READ N
50 GOSUB 400
60 NEXT J
70 END
190 REM Set arrays A, B.
200 DIM A(7), B(7)
210 FOR I = 0 TO 7
220 READ A(I)
230 NEXT I
240 FOR I = 0 TO 7
250 READ B(I)
260 NEXT I
270 RETURN
390 REM Show row and column for element
400 LET I = 7
410 IF A(I) <= N THEN 440
420 LET I = I-1
430 GOTO 410
440 LET M = N+B(I)
450 LET R = INT(M/18)+1
460 LET C = M-INT(M/18)*18+1
470 PRINT N; "->"; R; C
480 RETURN
990 REM Data.
1000 REM Arrays A, B.
1010 DATA 1, 2, 5, 13, 57, 72, 89, 104
1020 DATA -1, 15, 25, 35, 72, 21, 58, 7
1030 REM Example elements (atomic numbers).
1040 DATA 1, 2, 29, 42, 57, 58, 72, 89, 90, 103
</lang>
=== {{header|Nascom BASIC}} ===
|
Revision as of 22:33, 12 August 2022
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
- the periodic table
- This task was an idea from CompSciFact
- The periodic table in ascii that was used as template
6502 Assembly
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?
<lang 6502asm>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,...</lang>
68000 Assembly
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.)
<lang 68000devpac>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.</lang>
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; # 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</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 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
BASIC
Applesoft BASIC
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. <lang gwbasic>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</lang>
ASIC
<lang basic> REM Periodic table DIM A(7) DIM B(7) REM Arrays A, B. DATA 1, 2, 5, 13, 57, 72, 89, 104 DATA -1, 15, 25, 35, 72, 21, 58, 7 REM Example elements (atomic numbers). DATA 1, 2, 29, 42, 57, 58, 72, 89, 90, 103
GOSUB SetAB: FOR J = 0 TO 9
READ AtomicNum GOSUB ShowRowAndColumn:
NEXT J END
SetAB: FOR I = 0 TO 7
READ A(I)
NEXT I FOR I = 0 TO 7
READ B(I)
NEXT I RETURN
ShowRowAndColumn: I = 7 WHILE A(I) > AtomicNum
I = I - 1
WEND M = AtomicNum + B(I) R = M / 18 R = R + 1 C = M MOD 18 C = C + 1 PRINT AtomicNum; PRINT " ->"; PRINT R; PRINT C RETURN </lang>
- 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
BASIC256
<lang BASIC256>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</lang>
- Output:
Same as FreeBASIC entry.
FreeBASIC
<lang freebasic>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</lang>
- 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
Old fashioned way: <lang futurebasic> 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 </lang>
- 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.) <lang futurebasic> _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 </lang>
- Output:
[Sorry, screenshot can't be uploaded.]
Gambas
<lang gambas>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</lang>
- Output:
Same as FreeBASIC entry.
Minimal BASIC
<lang gwbasic> 10 REM Periodic table 20 GOSUB 200 30 FOR J = 0 TO 9 40 READ N 50 GOSUB 400 60 NEXT J 70 END 190 REM Set arrays A, B. 200 DIM A(7), B(7) 210 FOR I = 0 TO 7 220 READ A(I) 230 NEXT I 240 FOR I = 0 TO 7 250 READ B(I) 260 NEXT I 270 RETURN 390 REM Show row and column for element 400 LET I = 7 410 IF A(I) <= N THEN 440 420 LET I = I-1 430 GOTO 410 440 LET M = N+B(I) 450 LET R = INT(M/18)+1 460 LET C = M-INT(M/18)*18+1 470 PRINT N; "->"; R; C 480 RETURN 990 REM Data. 1000 REM Arrays A, B. 1010 DATA 1, 2, 5, 13, 57, 72, 89, 104 1020 DATA -1, 15, 25, 35, 72, 21, 58, 7 1030 REM Example elements (atomic numbers). 1040 DATA 1, 2, 29, 42, 57, 58, 72, 89, 90, 103 </lang>
Nascom BASIC
<lang basic> 10 REM Periodic table 20 GOSUB 200 30 FOR J=0 TO 9:READ ANUM:GOSUB 400:NEXT J 40 END 190 REM ** Set arrays A, B. 200 DIM A(7),B(7) 210 FOR I=0 TO 7:READ A(I):NEXT I 220 FOR I=0 TO 7:READ B(I):NEXT I 230 RETURN 390 REM ** Show row and column for element 400 I=7 410 IF A(I)>ANUM THEN I=I-1:GOTO 410 420 M=ANUM+B(I) 430 R=INT(M/18)+1 440 C=M-INT(M/18)*18+1 450 PRINT ANUM;"->";R;C 460 RETURN 990 REM ** Data. 1000 REM ** Arrays A, B. 1010 DATA 1,2,5,13,57,72,89,104 1020 DATA -1,15,25,35,72,21,58,7 1030 REM ** Example elements (atomic numbers). 1040 DATA 1,2,29,42,57,58,72,89,90,103 </lang>
- 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
QBasic
<lang qbasic>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</lang>
- Output:
Same as FreeBASIC entry.
Run BASIC
<lang lb>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</lang>
- Output:
Same as FreeBASIC entry.
True BASIC
<lang qbasic>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</lang>
- Output:
Similar to FreeBASIC entry.
XBasic
<lang xbasic>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</lang>
- Output:
Similar to FreeBASIC entry.
Yabasic
<lang 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</lang>
- Output:
Same as FreeBASIC entry.
Go
<lang ecmascript>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) }
}</lang>
- 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
Basically, here, we want a lookup table. For example:
<lang J>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=: Template:Tokens=. (
rowcol=: ptrc</lang>
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:
<lang J> 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</lang>
Julia
<lang ruby>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
</lang>
- 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)
Mathematica /Wolfram Language
Mathematica and the Wolfram language include the period and group in the function ElementData but has slightly different definitions for the lantanides and aktinoides. <lang Mathematica>ClearAll[FindPeriodGroup] FindPeriodGroup[n_Integer] := Which[57 <= n <= 70,
{8, n - 53} , 89 <= n <= 102, {9, n - 85} , 1 <= n <= 118, {ElementData[n, "Period"], ElementData[n, "Group"]} , True, Missing["Element does not exist"]
] Row[{"Element ", #, " -> ", FindPeriodGroup[#]}] & /@ {1, 2, 29, 42, 57, 58, 59, 71, 72, 89, 90, 103, 113} // Column Graphics[Text[#, {1, -1} Reverse@FindPeriodGroup[#]] & /@ Range[118]]</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 59 -> {8,6} Element 71 -> {6,3} Element 72 -> {6,4} Element 89 -> {9,4} Element 90 -> {9,5} Element 103 -> {7,3} Element 113 -> {7,13} [graphical representation of the periodic table positions]
Perl
<lang perl>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;
}</lang>
- 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
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
alternate
constant ptxt = """ __________________________________________________________________________ | 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 | |__________________________________________________________________________| """ function tablify(string ptxt) sequence lines = split(ptxt,"\n"), res = {} for l in lines do integer ln = l[2]-'0', c = 0 if ln>=1 and ln<=9 then res = append(res,{}) for j=5 to length(l) by 4 do c += 1 if l[j]>='A' and l[j+2]<=' ' then res[$] = append(res[$],{trim(l[j..j+1]),ln,c}) end if end for end if end for res[7][3..2] = res[9] res[6][3..2] = res[8] res = join(res[1..7],{},{}) return res end function constant pt = apply(true,sprintf,{{"(%s) is at %d, %d"},tablify(ptxt)}) for e in {1,2,29,42,57,58,59,71,72,89,90,103,113} do printf(1,"Element %d %s\n",{e,pt[e]}) end for
- Output:
Element 1 (H) is at 1, 1 Element 2 (He) is at 1, 18 Element 29 (Cu) is at 4, 11 Element 42 (Mo) is at 5, 6 Element 57 (La) is at 8, 4 Element 58 (Ce) is at 8, 5 Element 59 (Pr) is at 8, 6 Element 71 (Lu) is at 8, 18 Element 72 (Hf) is at 6, 4 Element 89 (Ak) is at 9, 4 Element 90 (Th) is at 9, 5 Element 103 (Lr) is at 9, 18 Element 113 (Nh) is at 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>
Raku
<lang perl6>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;
}</lang>
- 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
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. <lang ecmascript>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])
}</lang>
- 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
<lang XPL0>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)); ]</lang>
- 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