DEV Community

Cover image for Periodic table code golf
Eduardo Lanchares
Eduardo Lanchares

Posted on

Periodic table code golf

The other day I came across this tweet:

I thought this was a nice challenge to solve and refresh some programming stuff, so I opened my editor and started coding a solution 🤓

Understanding the problem

Reading about periodic table in Wikipedia I've discovered that there's more than one way to display it. Taking into account the example in the tweet, we're going to assume it's the standard form.

If we take a look at the table, the first thing to notice is how elements are disposed in it

Periodic table

As we can see it's just a regular table but with some exceptions. For instance, helium with an atomic number of 2 should start at group 2, but it doesn't (check this if you want to know why), so we need to keep track of these special cases. In total we have 3 exceptions (He, B and Al).

There's another special case to consider: Lanthanoids and actinoids. For the sake of simplicity we're not going to consider it for this challenge.

Now that everything is clear, let's start!

Step 1 - 1D to 2D

First task is finding a way to map an atomic number to a row and a column in the table. We know that atomic numbers are sequential and goes from 1 to 118 and also that periodic table has 18 groups. Considering a regular table we could do the following:

function getElementPosition(atomicNumber) {
  const groups = 18
  const index = atomicNumber - 1;
  const row = Math.trunc(index / groups)
  const column = index % groups

  return [row + 1, column + 1]
}
Enter fullscreen mode Exit fullscreen mode

Here we're transforming a one dimensional index into a two dimensional one. That's a good starting point but we need to take special cases into consideration

Step 2 - Special cases

For special cases we can use an array to store when they start and what's the offset we need to apply:

function getElementPosition(atomicNumber) {
  let groups = 18
  let index = atomicNumber - 1;
  let specialNumbers = [
    [2, 16], 
    [5, 10],
    [13, 10],
  ]

  for (let [number, offset] of specialNumbers) {
    if (number <= atomicNumber) {
      index += offset
    }
  }

  let row = Math.trunc(index / groups)
  let column = index % groups

  return [row + 1, column + 1]
}
Enter fullscreen mode Exit fullscreen mode

In this case we're adding the required offset based on our special numbers (He, B and Al). We can now do getElementPosition(2) and it'll return [1, 18] 💪.

But wait a minute, what happens with gold? Calling getElementPosition(79) returns [7, 7]. Nope, something is definetively not working

Step 3 - Lanthanoids and actinoids

Ok, we didn't thought of lanthanoids and actinoids. Let's try to fix it with our special cases array:

function getElementPosition(atomicNumber) {
  let groups = 18
  let index = atomicNumber - 1;
  let specialNumbers = [
    [2, 16], 
    [5, 10],
    [13, 10],
    [71, -14],
    [103, -14],
  ]

  for (let [number, offset] of specialNumbers) {
    if (number <= atomicNumber) {
      index += offset
    }
  }

  let row = Math.trunc(index / groups)
  let column = index % groups

  return [row + 1, column + 1]
}
Enter fullscreen mode Exit fullscreen mode

In this case instead of expanding (positive offset) we're collapsing (negative offset). Yes, it works now, calling getElementPosition(79) returns [6, 11] 🙂.

Almost there, let's go to final step

Step 4 - Minification

After using a minification service the code looks like this:

function getElementPosition(t){let e=t-1,n=[[2,16],[5,10],[13,10],[71,-14],[103,-14]];for(let[o,r]of n)o<=t&&(e+=r);return[Math.trunc(e/18)+1,e%18+1]}
Enter fullscreen mode Exit fullscreen mode

150 bytes characters in total (far below 280 for a tweet). Not bad but we can still short it a bit:

g=(e=>{let r=e-1,t=[[2,16],[5,10],[13,10],[71,-14],[103,-14]];for(let[f,l]of t)f<=e&&(r+=l);return[~~(r/18)+1,r%18+1]});
Enter fullscreen mode Exit fullscreen mode

By using arrow function syntax and changing Math.trunc to ~~ we've trimmed it to just 120 characters!

Conclusion

This was a great challenge, nothing too hard but difficult enough to train our brains. And we also have learned some interesting thing about this famous table 👨‍🔬

Cover image source https://www.flickr.com/photos/mindfrieze/258644767

Top comments (0)