Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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

share|improve this question
1  
I just know that Mathematica will have a built-in for this... – Okx 16 hours ago
    
@Okx, I'm hoping that the Lanthanides and Actinides mess up any built-ins :) – James Webster 16 hours ago
2  
Are you allowed to return "6,L" and "7,A" for the Lanthanides and Actinides? – Neil 16 hours ago
1  
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? – sjb-2812 14 hours ago
1  
L is fine. That's actually what I intended. But since the CSV outputted L, I'll accept both – James Webster 13 hours ago

13 Answers 13

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!

share|improve this answer

CJam, 64 59 58 bytes

{_80-zG-z8<{80>"LA"=}{_['X56C4X]f>[-14_AAG].*+:+(Imd)\)}?}

Try it online!

Leaves either group and period 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.
  ['X56C4X]  e#   Push ['X 56 12 4 1], where 'X has character code 88 (integers
             e#   and characters can be compared ignoring their types).
             e#   These are the values just before the gaps.
  f>         e#   Compare the input to each of these.
  [-14_AAG]  e#   Push [-14 -14 10 10 16]. These are the changes we need to
             e#   make to remove or insert the gaps corresponding to the above
             e#   positions.
  .*         e#   Multiply each gap by whether it's before the input value.
  +:+        e#   Add all of the applicable gaps to the input value.
  (          e#   Decrement to make it 0-based.
  Imd        e#   Divmod 18, gives 0-based group and period.
  )\)        e#   Increment both outputs.
}?
share|improve this answer

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!

share|improve this answer

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.

share|improve this answer
2  
Seriously, builtins again? – Matthew Roh 14 hours ago
1  
@MatthewRoh I'm sure a well-golfed arithmetic solution in a golfing language will easily beat this. – Martin Ender 14 hours ago
    
@MartinEnder Well, I'm actually sure of the exact opposite. – Erik the Outgolfer 12 hours ago
    
@EriktheOutgolfer Well, there you go. I'm sure Jelly could cut off another 30-50%. – Martin Ender 12 hours ago
    
@MartinEnder I'll most probably leave that up to Dennis, I can't do such a thing in exam period. – Erik the Outgolfer 12 hours ago

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)
share|improve this answer
    
I would recommend shortening the '\201\202\203\...\362' part of the string. Seriously, its long as heck. – Matthew Roh 14 hours ago
    
Curious how @MatthewRoh measured heck. – hBy2Py 11 hours ago

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.

share|improve this answer
    
Running your example, the output I receive is 18<t7. Is this something I'm doing wrong? (running on Mac El Capitan) – James Webster 10 hours ago
1  
@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 – aross 10 hours ago

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.

share|improve this answer

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>

share|improve this answer

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.

share|improve this answer
    
can't you place that while outside the function? it would save a byte (space) – Felipe Nardi Batista 12 hours ago
    
@FelipeNardiBatista - Managed to get rid of the while loop altogether :) – ElPedro 11 hours ago

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
share|improve this answer

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!

share|improve this answer

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,

share|improve this answer

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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