24
\$\begingroup\$

Question

Given the atomic number of an element in the range [1-118] output the group and period, of that element as given by the following Periodic Table Of Elements.

For elements in the Lanthanide and Actinide series, (ranges [57-71] and [89-103]), you should instead return L for the Lanthanides and A for the Actinides

You may write a program or a function and use any of the our standard methods of receiving input and providing output.

You may use any programming language, but note that these loopholes are forbidden by default.

enter image description here

[Source]

Test Cases

Since there are only 118 possible inputs, a full list of the expected inputs and outputs is given below.

Created by hand, let me know if there's a mistake!

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

Scoring

Simple . Shortest number of bytes wins

\$\endgroup\$
  • 5
    \$\begingroup\$ I just know that Mathematica will have a built-in for this... \$\endgroup\$ – Okx Mar 17 '17 at 8:49
  • \$\begingroup\$ @Okx, I'm hoping that the Lanthanides and Actinides mess up any built-ins :) \$\endgroup\$ – James Webster Mar 17 '17 at 8:50
  • 2
    \$\begingroup\$ Are you allowed to return "6,L" and "7,A" for the Lanthanides and Actinides? \$\endgroup\$ – Neil Mar 17 '17 at 9:05
  • 1
    \$\begingroup\$ can't comment (yet) but sometimes Hydrogen is placed in group 17 - but I acknowledge that you've used an image to justify why group 1 and don't know if this makes things harder or easier? \$\endgroup\$ – sjb-2812 Mar 17 '17 at 10:58
  • 1
    \$\begingroup\$ L is fine. That's actually what I intended. But since the CSV outputted L, I'll accept both \$\endgroup\$ – James Webster Mar 17 '17 at 12:06

18 Answers 18

10
\$\begingroup\$

CJam, 64 59 58 56 54 bytes

Thanks to Dennis for saving 2 bytes.

{_80-zG-z8<{80>"LA"=}{_"X8"f>[-14_AAGH].*+:+Imd)}?}

Try it online!

Leaves either period and group or a single character on the stack.

Explanation

There are two main ideas here:

  • First, we deal with the Lanthanides and Actinides. We have the condition 56 < x < 72 for Lanthanides and 88 < x < 104 for Actinides. Both of these can be expressed as a single comparison by taking an absolute difference to the centre of the range: the inequalities become |x - 64| < 8 and |x - 96| < 8, respectively. But these are still very similar, and doing the two comparisons separately is expensive. So we apply the same idea of checking a symmetric range, by taking another absolute difference with the centre between the two ranges, 80, first: ||x-80| - 16| < 8. This condition indicates that the atom is either a Lanthanide or an Actinide, but distinguishing between these two cases is then as trivial as comparing against 80 (or some other value between the ranges).
  • Since the output is really an index in a table of width 18, an obvious approach is to try base-converting the value to base 18, so that the two digits give group and period. To do that, we need to shift some values around though. All the we really need to do is to add the gaps in periods 1, 2 and 3 and close the gaps in periods 6 and 7. It's easiest to do this from the end, so that the values of the other gaps aren't affected (and keep their values).

_            e# Make a copy of the input, to figure out whether the output
             e# should be L or A.
80-z         e# Absolute difference from 80.
G-z          e# Absolute difference from 16.
8<           e# Check whether the result is less than 8.
{            e# If so...
  80>        e#   Check whether the input is greater than 80.
  "LA"=      e#   Select 'L or 'A accordingly.
}{           e# ...otherwise...
  _          e#   Duplicate input again.
  "X8"    e#   Push a string with character codes [88 56 12 4 1].
             e#   These are the values just before the gaps.
  f>         e#   Compare the input to each of these.
  [-14_AAGH] e#   Push [-14 -14 10 10 16 17]. These are the changes we need to
             e#   make to remove or insert the gaps corresponding to the above
             e#   positions. Note that the 17 doesn't get paired with an offset.
             e#   It's a constant offset to itself, which is equivalent to
             e#   decrementing the input (to make it zero based) and adding 18
             e#   to make the increment the period and make it 1-based.
  .*         e#   Multiply each gap by whether it's before the input value.
  +:+        e#   Add all of the applicable gaps to the input value.
  Imd        e#   Divmod 18, gives 1-based period and 0-based group.
  )          e#   Increment the group to make it one-based.
}?
\$\endgroup\$
10
\$\begingroup\$

05AB1E, 113 102 99 bytes

X18©XY‚Dˆ13®Ÿ¯13®Ÿ®LD¯15'L×S15L3+©¯15'A×S®)˜¹<è,XXY8×SD>4 18×SD>S66Sð14×S6 15×S77Sð15×S7 15×S)˜¹<è,

Explanation:

(start to construct the period part)
X18 ~ push 1 and 18
© ~ store 18 in register_c without p-opping
XY ~ push 1 and 2
13® ~ push 13 and the top element in register_c (18)
Ÿ ~ range - pop 2 values and push [a .. b]
XY ~ push 1 and 2
13®Ÿ ~ range - 13 to 18
XY ~ push 1, 2
13®Ÿ ~ range - 13 to 18
®LD ~ range - 1 to 18 (twice)
2L ~ range - 1 to 2
15'L×S ~ push 'L' 15 times
15L ~ range - 1 to 15
3+ ~ add 3 to each value in topmost element in stack
© ~ store in register-c without popping
2L ~ range - 1 to 2
15'A×S ~ push 'A' 15 times
® ~ push topmost value in register_c
) ~ wrap stack to array
˜ ~ deep flatten
¹<è ~ 1-indexed value of input in array
, ~ print & pop
(start to construct the group part)
XX ~ push 1 twice
Y8×SD ~ push 2 eight times (twice)
> ~ increment each value by 1
4 18×S ~ push 4 eighteen times (twice)
> ~ increment each value by one
66S ~ push 6 twice
ð15×S ~ push a space character 15 times
6 15×S ~ push 6 fifteen times
77S ~ push 7 two times
ð15×S ~ push a space character 15 times
7 15×S ~ push 7 fifteen times
)˜ ~ wrap stack to array and deep flatten
¹<è, ~ get 1-indexed value of input in array, then pop & print

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Using a mask like 1000000000000000000000000000000001 1100000000000000000000000000111111 1100000000000000000000000000111111 1112222222222222221111111111111111 1113333333333333331111111111111111 may reduce bytecount, otherwise nice! \$\endgroup\$ – Magic Octopus Urn Mar 21 '17 at 15:07
7
\$\begingroup\$

Mathematica, 77 bytes

e=ElementData;Which[56<#<72,"L",88<#<104,"A",1>0,{#~e~"Group",#~e~"Period"}]&

It would also be quite easy to use ElementData to determine whether the input is a Lanthanide or Actinide, but it would take about 20 more bytes.

\$\endgroup\$
  • 3
    \$\begingroup\$ Seriously, builtins again? \$\endgroup\$ – lol Mar 17 '17 at 10:37
  • 1
    \$\begingroup\$ @MatthewRoh I'm sure a well-golfed arithmetic solution in a golfing language will easily beat this. \$\endgroup\$ – Martin Ender Mar 17 '17 at 10:43
  • \$\begingroup\$ @MartinEnder Well, I'm actually sure of the exact opposite. \$\endgroup\$ – Erik the Outgolfer Mar 17 '17 at 12:45
  • \$\begingroup\$ @EriktheOutgolfer Well, there you go. I'm sure Jelly could cut off another 30-50%. \$\endgroup\$ – Martin Ender Mar 17 '17 at 13:04
  • \$\begingroup\$ @MartinEnder I'll most probably leave that up to Dennis, I can't do such a thing in exam period. \$\endgroup\$ – Erik the Outgolfer Mar 17 '17 at 13:14
6
\$\begingroup\$

Python 2, 205 136 bytes

-26 bytes thanks to @Dead Possum

def f(x):a=(x>71)+(x>99);print((((x-2*(x>1)-8*(x>4)-8*(x>12)+4*a-1)%18+1,(x-(x>17)-14*a)/18+(x>2)+(x>10)+1),'L'),'A')[88<x<104][56<x<72]

Try it online!

\$\endgroup\$
3
\$\begingroup\$

PHP, 144 bytes

Note: uses IBM-850 encoding

$x=($a=$argn-1)<57|$a>70?$a>88&$a<103?A:0:L;foreach([16,19=>10,37=>10,92=>-14,110=>-14]as$l=>$m)$a>$l&&$a+=$m;echo$x?:$a%18+1 .~Ë.ceil(++$a/18);

Run like this:

echo 118 | php -nR '$x=($a=$argn-1)<57|$a>70?$a>88&$a<103?A:0:L;foreach([16,19=>10,37=>10,92=>-14,110=>-14]as$l=>$m)$a>$l&&$a+=$m;echo$x?:$a%18+1 .~Ë.ceil(++$a/18);';echo
> 18,7

Explanation

Check whether input is within the ranges for L or A; the "exception" ranges. Then modify the input to fill the missing cells in the grid (or get rid of the extra cells). Finally, print the exception (unless that is falsy 0) or convert the position to grid coordinates.

\$\endgroup\$
  • \$\begingroup\$ Running your example, the output I receive is 18<t7. Is this something I'm doing wrong? (running on Mac El Capitan) \$\endgroup\$ – James Webster Mar 17 '17 at 14:14
  • 1
    \$\begingroup\$ @JamesWebster that's because of the encoding I used for the comma. If you can't switch your terminal's encoding, you can replace the thing between the 2 dots (just before ceil) with "," for 1 extra byte \$\endgroup\$ – aross Mar 17 '17 at 14:18
3
\$\begingroup\$

Jelly, 57 bytes

“9Ḳ*!}ḣE’ṃ“¢£Æ¥Ø‘r2/;€"“ⱮḶıð’ḃ7¤µ⁵,12Ṭœṗ;"⁾LAṁ€15¤j“”$⁺³ị

Full program that prints the desired output.

Try it online! (A slightly modified program which prints all input : output may be seen here).

How?

Builds a list of the 118 possible outputs and then picks the entry at the index of the input.

Some prep:

“9Ḳ*!}ḣE’ - base 250 number: 14334152882934570 (call this A)

“¢£Æ¥Ø‘   - a list using Jelly's code page: [1, 2, 13, 4, 18] (call this B)

“ⱮḶıð’    - base 250 number: 2354944025 (call this C)

The program (shortened by substituting A, B, and C) :

AṃBr2/;€"Cḃ7¤µ⁵,12Ṭœṗ;"⁾LAṁ€15¤j“”$⁺³ị - Main link: atomicNumber
AṃB                                    - number A with digits B: [1,1,18,18,1,2,13,18,1,2,13,18,1,18,1,18,1,2,4,18,1,2,4,18]
    2/                                 - pair-wise reduce with
   r                                   -     inclusive range: [[1],[18],[1,2],[13,14,15,16,17,18],[1,2],[13,14,15,16,17,18],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18],[1,2],[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18],[1,2],[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]]
            ¤                          - nilad followed by link(s) as a nilad:
         C                             -     number C
          ḃ7                           -     converted to bijective base 7: [1,1,2,2,3,3,4,5,6,6,7,7]
        "                              - zip with:
      ,€                               -     pair each: [[1,1],[18,1],[[1,2],[2,2]],[[13,2],[14,2],[15,2],[16,2],[17,2],[18,2]],[[1,3],[2,3]],[[13,3],[14,3],[15,3],[16,3],[17,3],[18,3]],[[1,4],[2,4],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[9,4],[10,4],[11,4],[12,4],[13,4],[14,4],[15,4],[16,4],[17,4],[18,4]],[[1,5],[2,5],[3,5],[4,5],[5,5],[6,5],[7,5],[8,5],[9,5],[10,5],[11,5],[12,5],[13,5],[14,5],[15,5],[16,5],[17,5],[18,5]],[[1,6],[2,6]],[[4,6],[5,6],[6,6],[7,6],[8,6],[9,6],[10,6],[11,6],[12,6],[13,6],[14,6],[15,6],[16,6],[17,6],[18,6]],[[1,7],[2,7]],[[4,7],[5,7],[6,7],[7,7],[8,7],[9,7],[10,7],[11,7],[12,7],[13,7],[14,7],[15,7],[16,7],[17,7],[18,7]]]
             µ                         - monadic chain separation (call the result x)
              ⁵                        - 10
               ,12                     - pair with 12: [10,12]            10↓ 12↓
                  Ṭ                    - truthy indexes: [0,0,0,0,0,0,0,0,0,1,0,1]
                   œṗ                  - partition x at the truthy indexes 
                                       -     (the locations of the runs of L's and A's)
                              ¤        - nilad followed by link(s) as a nilad:

                       ⁾LA             -     ['L','A']
                          ṁ€15         -     mould each like 15: [['L','L','L','L','L','L','L','L','L','L','L','L','L','L','L'],['A','A','A','A','A','A','A','A','A','A','A','A','A','A','A']]
                      "                - zip with:
                     ;                 -     concatenation: [[[1,1],[18,1],[[1,2],[2,2]],[[13,2],[14,2],[15,2],[16,2],[17,2],[18,2]],[[1,3],[2,3]],[[13,3],[14,3],[15,3],[16,3],[17,3],[18,3]],[[1,4],[2,4],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[9,4],[10,4],[11,4],[12,4],[13,4],[14,4],[15,4],[16,4],[17,4],[18,4]],[[1,5],[2,5],[3,5],[4,5],[5,5],[6,5],[7,5],[8,5],[9,5],[10,5],[11,5],[12,5],[13,5],[14,5],[15,5],[16,5],[17,5],[18,5]],[[1,6],[2,6]],'L','L','L','L','L','L','L','L','L','L','L','L','L','L','L'],[[[4,6],[5,6],[6,6],[7,6],[8,6],[9,6],[10,6],[11,6],[12,6],[13,6],[14,6],[15,6],[16,6],[17,6],[18,6]],[[1,7],[2,7]],'A','A','A','A','A','A','A','A','A','A','A','A','A','A','A'],[[4,7],[5,7],[6,7],[7,7],[8,7],[9,7],[10,7],[11,7],[12,7],[13,7],[14,7],[15,7],[16,7],[17,7],[18,7]]]

             µ⁵,12Ṭœṗ;"⁾LAṁ€15¤j“”$⁺³ị
                                  $    - last two links as a monad:
                               j“”     -     join with [''] (a workaround for no "flatten by 1")
                                   ⁺   - repeat last link (flatten once more): [[1,1],[18,1],[1,2],[2,2],[13,2],[14,2],[15,2],[16,2],[17,2],[18,2],[1,3],[2,3],[13,3],[14,3],[15,3],[16,3],[17,3],[18,3],[1,4],[2,4],[3,4],[4,4],[5,4],[6,4],[7,4],[8,4],[9,4],[10,4],[11,4],[12,4],[13,4],[14,4],[15,4],[16,4],[17,4],[18,4],[1,5],[2,5],[3,5],[4,5],[5,5],[6,5],[7,5],[8,5],[9,5],[10,5],[11,5],[12,5],[13,5],[14,5],[15,5],[16,5],[17,5],[18,5],[1,6],[2,6],'L','L','L','L','L','L','L','L','L','L','L','L','L','L','L',[4,6],[5,6],[6,6],[7,6],[8,6],[9,6],[10,6],[11,6],[12,6],[13,6],[14,6],[15,6],[16,6],[17,6],[18,6],[1,7],[2,7],'A','A','A','A','A','A','A','A','A','A','A','A','A','A','A',[4,7],[5,7],[6,7],[7,7],[8,7],[9,7],[10,7],[11,7],[12,7],[13,7],[14,7],[15,7],[16,7],[17,7],[18,7]]
                                    ³  - program's first input
                                     ị - index into the list
\$\endgroup\$
2
\$\begingroup\$

Perl5, 202 bytes

$x=substr(" !2ABMNOPQRabmnopqr\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\301\302LLLLLLLLLLLLLLL\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\341\342KKKKKKKKKKKKKKK\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362",$ARGV[0],1);print$x=~/K/?"A":$x=~/L/?$x:(ord($x)&31).",".(ord($x)>>5)
\$\endgroup\$
  • \$\begingroup\$ I would recommend shortening the '\201\202\203\...\362' part of the string. Seriously, its long as heck. \$\endgroup\$ – lol Mar 17 '17 at 10:33
  • 1
    \$\begingroup\$ Curious how @MatthewRoh measured heck. \$\endgroup\$ – hBy2Py Mar 17 '17 at 13:28
2
\$\begingroup\$

Ruby, 130 bytes

->a{(w=32767)[a-57]>0??L:w[a-89]>0??A:([[1,2],[20,8],[38,8],[107,32],[125,32]].map{|x,y|a>x&&a+=18-y};[(b=a%18)>0?b:18,~-a/18+1])}

First get the 'A' and 'L' with the bitmask trick, then try to fit into a 18*7 rectangle and use a div/mod.

\$\endgroup\$
2
\$\begingroup\$

Python 2, 137 bytes

lambda x:[(1+(x>2)+(x>10)+min((~-x/18),3)+(x>86),(x+(x>1)*15+((x>4)+(x>12))*10-((x>71)+(x>103))*14)%18+1),"AL"[89<x]][57<x<72or 89<x<104]

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 2, 115 bytes

def f(n):n+=([0,17]+[33]*3+[43]*8+[53]*45+[200]*14+[39]*18+[400]*14+[25]*15)[n];print[(n%18+1,n/18),'L','A'][n/200]

Try it online!

The idea is to div-mod the grid position to get the group and period. The grid position is the input n adjusted by a displacement to account for gaps and the L/A contraction. These are extracted from a list.

The Lanthanide and Actinide handling is ugly. These are assigned large displacements 200 and 400 that can be detected with /200. I'd like to put the characters L and A here, but then n+=... will add a char to a number, giving an error even if n is not used. If not for the 1-indexing, divmod could be used to refer to n only once, and then it could be replaced with its expression,

\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES7), 100 98 bytes

f=(n,p=1,x=0,y=x+2*(p+2>>1)**2)=>(n-57&95)<15?n>71?'A':'L':n>y?f(n,p+1,y):[n-x-1>p/2?n-y+18:n-x,p]
<input type=number min=1 max=118 oninput=o.textContent=f(this.value)><pre id=o>

Explanation: The 'L' and 'A' series are special-cased, using some bitwise logic that saved me 3 bytes over direct comparisons. Otherwise the function recursively finds the period p containing the desired atomic number, the number of the last element in the previous period x, and the number of the last element in the period y which is computed each time by noting that the differences are 2, 2, 8, 8, 18, 18 i.e. repeated doubled square numbers. The group is then found by offsetting from the left or right of the table depending on whether the element lies under the Beryllium-Scandium diagonal or not.

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 136 bytes

n=>[...'112626ii2ff2fff'].reduce((p,i,j)=>(n-=parseInt(i,36))>0?n:+p?+(x='112233456L67A7'[j])?[p+(9258>>j&1?j>5?3:j>2?12:17:0),x]:x:p,n)

Test

let f =

n=>[...'112626ii2ff2fff'].reduce((p,i,j)=>(n-=parseInt(i,36))>0?n:+p?+(x='112233456L67A7'[j])?[p+(9258>>j&1?j>5?3:j>2?12:17:0),x]:x:p,n)
<input oninput="o.innerHTML=f(+value)" type="number" min=1 max=118/>
<pre id="o"></pre>

\$\endgroup\$
1
\$\begingroup\$

Python 2, 264 227 217 bytes

lambda x:((((((((((((((1,1),(18,1))[x>1],(x-2,2))[x>2],(x+8,2))[x>4],(x-10,3))[x>10],(x,3))[x>12],(x-18,4))[x>18],(x-36,5))[x>36],(x-54,6))[x>54],'L')[x>56],(x-68,6))[x>71],(x-86,7))[x>86],'A')[x>88],(x-100,7))[x>103]

Try it online!

Way too many brackets. It looks more like Brain-Flak.

\$\endgroup\$
  • \$\begingroup\$ can't you place that while outside the function? it would save a byte (space) \$\endgroup\$ – Felipe Nardi Batista Mar 17 '17 at 12:44
  • \$\begingroup\$ @FelipeNardiBatista - Managed to get rid of the while loop altogether :) \$\endgroup\$ – ElPedro Mar 17 '17 at 13:17
1
\$\begingroup\$

Excel, 192 bytes

Far from pretty. Borrows from existing Python answers

=SUBSTITUTE(SUBSTITUTE(IF(ABS(ABS(A1-80)-16)<8,IF(A1<80,"L","A"),MOD(A1-2*(A1>1)-8*(A1>4)-8*(A1>12)+4*((A1>71)+(A1>99)),18)&" ,"&1+(A1>2)+(A1>10)+(A1>18)+(A1>36)+(A1>54)+(A1>86)),0,18),118,10)

Struggling to handle the case where MOD(x,18)=0 for Group value gracefully.

\$\endgroup\$
  • \$\begingroup\$ I think I've found a mistake. Should the IF for determining lanthanides and actinides read IF(A1<80? \$\endgroup\$ – James Webster Sep 11 '17 at 17:41
  • \$\begingroup\$ @JamesWebster, well spotted. Have corrected. \$\endgroup\$ – Wernisch Sep 12 '17 at 11:28
0
\$\begingroup\$

Ruby, 116 bytes

->n{a=(17..143).map{|i|"#{[i%18+1,i/18]}"}
a[2..17]=a[21..30]=a[39..48]=[]
a[57]=[?L]*15
a[75]=[?A]*15
a.flatten[n]}

Commented in test program

f=->n{
a=(17..143).map{|i|"#{[i%18+1,i/18]}"} #Make an array with strings "[18,0]" to "[18,7]" (first value required as input is 1 indexed.)
a[2..17]=a[21..30]=a[39..48]=[]        #Delete "missing" elements from first three periods. 
a[57]=[?L]*15                          #Replace position 57 in the table with a 15-element array ["L".."L"]
a[75]=[?A]*15                          #Replace the correct position in the table with a 15-element array ["A".."A"]
a.flatten[n]}                          #Flatten the array (break the two above elements into 15) and output element n of the array.

1.upto(118){|n|print n,f[n],$/}
\$\endgroup\$
0
\$\begingroup\$

PHP, 120 bytes

echo(($n=--$argn)-56&95)<15?LA[$n>70]:(($n-=14*($n>88)+14*($n>56)-10*($n>11)-10*($n>3)-16*!!$n)%18+1).",".(($n/18|0)+1);

takes input from STDIN, run with -nR.

some bitwise magic for the Lanthanides and Actinides,
the $n-= part adds and subtracts offsets for the gaps and Lanthanides/Actinides,
the rest is simple mod/div.

An iterative port of Neil´s answer takes 108 bytes:

for(;(95&71+$n=$argn)>14&&$n>$y+=2*(++$p+2>>1)**2;)$x=$y;
echo$p?$n-$x>$p/2+1?$n-$y+18:$n-$x:LA[$n>70],",$p";
\$\endgroup\$
0
\$\begingroup\$

Perl, 169 bytes

90>($n-=14)&&($g=A)if($n=$v=pop)>88;58>($n-=14)&&($g=L)if$n>56;if(!$g){$c+=vec"\1\0\xe\xc0?\0".("\xff"x9)."?",$i++,1
while$c<$n;$p=1+($i-($g=$i%18||18))/18}say"$v,$g,$p"

Using:

perl -E '90>($n-=14)&&($g=A)if($n=$v=pop)>88;58>($n-=14)&&($g=L)if$n>56;if(!$g){$c+=vec"\1\0\xe\xc0?\0".("\xff"x9)."?",$i++,1 while$c<$n;$p=1+($i-($g=$i%18||18))/18}say"$v,$g,$p"' 103
\$\endgroup\$
0
\$\begingroup\$

Jelly, 49 43 42 41 39 bytes

45“ÞØ\€a€⁶;l;i‘bx/€F’ḣ¹Sḃ18µV=“?I‘⁾LAxȯ

Try it online!

Background

With the exception of lanthanides and actinides, the output will consist of an integer expressed in bijective base 18. For example, hydrogen corresponds to 1910 = 11b18, helium to 3610 = 1Ib18, and eka-radon/ununoctium/oganesson to 11410 = 7Ib18.

We start by mapping all atomic numbers we can to the corresponding integers, while mapping lanthanides and actinides to those that correspond to lanthanum (11110 = 63b18) and actinium (12910 = 73b18).

To do this, we record the forward differences of the integers that represent the atoms. For example, the first is 1Ib18 - 11b18 = Hb18 = 1710, the second is 1 (as are all differences between consecutive elements of the unexpanded periodic table), the fourth (B to Be) is 2Db18 - 22b18 = Bb18 = 1110, and so on. To map all lanthanides and all actinides, we'll consider all differences between two lanthanides or to actinides (e.g., La to Ce) to be 0.

To get the desired integer for an atomic number n, all we have to do is prepend 19 (hydrogen) to the differences and compute the sum of the first n elements of the resulting vector. The output is then simply displayed in bijective base 18, unless this would display 6 3 (lanthanides) or 7 3 (actinides). In the latter case, we simply replace the computed result with L or A.

Wrapped for horizontal sanity, the vector we have to encode looks as follows.

19 17  1  1 11  1  1  1  1  1  1  1 11  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1
 1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1
 1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1  1  1  1  1  1
 1  1  1  1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1  1
 1  1  1  1  1  1

After run-length encoding, we get the following.

19 1    17 1    1 2    11 1    1 7    11 1    1 44    0 14    1 18    0 14    1 15

To reduce the space required to encode the vector even more, we strip rightmost 1's (lengths) and add 1 to the runs.

20      18      2 2    12      2 7    12      2 44    1 14    2 18    1 14    2 15

Now we can reversibly convert these digit arrays from base 45 to integers.

20      18      92     12      97     12      134     59      108     59      105

All of these are smaller than 250, so we can represent them with characters from Jelly's code page. Surrounded with (literal start) and (interpret as integer array), we get the Jelly literal

“ÞØ\€a€⁶;l;i‘

which appears verbatim in the code.

How it works

45“…‘bx/€F’ḣ¹Sḃ18µV=“?I‘⁾LAxȯ  Main link. Argument: n (atomic number)

45                             Set the return value to 45.
  “…‘                          Yield [20,18,92,12,97,12,134,59,108,59,105].
     b                         Convert the integers in the array to base 45.
      x/€                      Reduce each resulting digit array (length 1 or 2)
                               by repetition, mapping [z] -> [z] and
                               [y,z] -> [y,…,y] (z times).
         F                     Flatten the result.
          ’                    Decrement, yielding the vector of length 118 from
                               the previous section.
           ḣ¹                  Head; take the first n elements of the vector.
             S                 Compute their sum.
              ḃ18              Convert to bijective base 18, yielding [p, g].
                 µ             Begin a new chain with argument [p,g].
                  V            Eval. The atom casts to string first, so [6,3]
                               , e.g., is mapped to 63, [7,18] to 718, etc.
                   =“?I‘       Compare the result with [63,73], yielding
                               [1,0] for lanthanides, [0,1] for actinides, and
                               [0,0] otherwise.
                        ⁾LAx   Repeat 'L' and 'A' that many times, yielding "L" for
                               lanthanides, "A" for actinides, and "" otherwise.
                            ȯ  Flat logical OR; replace "" with [p,g].
\$\endgroup\$
  • \$\begingroup\$ While this is an interesting answer, I'm afraid I think it falls down on the output. Instead of outputting the group and the period for the input, it appears to output the atomic number, group and period for the full table. Consider if I'd asked you for a dictionary definition of a word and you just outputted a dictionary. \$\endgroup\$ – James Webster Mar 27 '17 at 8:29
  • \$\begingroup\$ The footer provides a test suite for easy verification. If you remove it and provide the input as an argument, it will just print yhe information the spec asks for. tio.run/nexus/jelly#@29i@qhhzuF5h2fEPGpakwjEjxq3WedYZz5qmJFUoQ/… \$\endgroup\$ – Dennis Mar 27 '17 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.