Check if a String of Text can be Composed Entirely of Chemical Element Symbols

Dec 27, 2022

Now here's smartly fun nonsense in script you can play with that's super neat. It's a small javascript function that takes an input string and determines whether or not it can be reproduced entirely using chemical element symbols. You know the ones. The one and two letter codes from the Periodic Table of the Elements.

Helium Neon Argon Krypton Xenon Radon Oganesson Boron Silicon Germanium Arsenic Antimony Tellurium Aluminium Gallium Indium Thallium Nihonium Tin Lead Flerovium Bismuth Moscovium Polonium Livermorium Fluorine Chlorine Bromine Iodine Astatine Tennessine Lawrencium Actinium Thorium Protactinium Uranium Neptunium Plutonium Americium Curium Berkelium Californium Einsteinium Fermium Mendelevium Nobelium Lutetium Lanthanum Cerium Praseodymium Neodymium Promethium Samarium Europium Gadolinium Terbium Dysprosium Holmium Erbium Thulium Ytterbium Scandium Yttrium Titanium Zirconium Hafnium Rutherfordium Vanadium Niobium Tantalum Dubnium Chromium Molybdenum Tungsten Seaborgium Manganese Technetium Rhenium Bohrium Iron Ruthenium Osmium Hassium Cobalt Rhodium Iridium Meitnerium Nickel Palladium Platinum Darmstadtium Copper Silver Gold Roentgenium Zinc Cadmium Mercury Copernicium Lithium Sodium Potassium Rubidium Cesium Francium Beryllium Magnesium Calcium Strontium Barium Radium Hydrogen Carbon Nitrogen Phosphorus Oxygen Sulfur Selenium Group Period 1 2 3 4 5 6 7 1 1HHydrogen 3LiLithium 11NaSodium 19KPotassium 37RbRubidium 55CsCesium 87FrFrancium 2 4BeBeryllium 12MgMagnesium 20CaCalcium 38SrStrontium 56BaBarium 88RaRadium * ** * ** 3 21ScScandium 39YYttrium 71LuLutetium 103LrLawrencium 57LaLanthanum 89AcActinium 4 22TiTitanium 40ZrZirconium 72HfHafnium 104RfRutherfordium 58CeCerium 90ThThorium 5 23VVanadium 41NbNiobium 73TaTantalum 105DbDubnium 59PrPraseodymium 91PaProtactinium 6 24CrChromium 42MoMolybdenum 74WTungsten 106SgSeaborgium 60NdNeodymium 92UUranium 7 25MnManganese 43TcTechnetium 75ReRhenium 107BhBohrium 61PmPromethium 93NpNeptunium 8 26FeIron 44RuRuthenium 76OsOsmium 108HsHassium 62SmSamarium 94PuPlutonium 9 27CoCobalt 45RhRhodium 77IrIridium 109MtMeitnerium 63EuEuropium 95AmAmericium 10 28NiNickel 46PdPalladium 78PtPlatinum 110DsDarmstadtium 64GdGadolinium 96CmCurium 11 29CuCopper 47AgSilver 79AuGold 111RgRoentgenium 65TbTerbium 97BkBerkelium 12 30ZnZinc 48CdCadmium 80HgMercury 112CnCopernicium 66DyDysprosium 98CfCalifornium 13 5BBoron 13AlAluminium 31GaGallium 49InIndium 81TlThallium 113NhNihonium 67HoHolmium 99EsEinsteinium 14 6CCarbon 14SiSilicon 32GeGermanium 50SnTin 82PbLead 114FlFlerovium 68ErErbium 100FmFermium 15 7NNitrogen 15PPhosphorus 33AsArsenic 51SbAntimony 83BiBismuth 115McMoscovium 69TmThulium 101MdMendelevium 16 8OOxygen 16SSulfur 34SeSelenium 52TeTellurium 84PoPolonium 116LvLivermorium 70YbYtterbium 102NoNobelium 17 9FFluorine 17ClChlorine 35BrBromine 53IIodine 85AtAstatine 117TsTennessine 18 2HeHelium 10NeNeon 18ArArgon 36KrKrypton 54XeXenon 86RnRadon 118OgOganesson

Paste a Sentence

Examples:

The periodicSentence() function will return an object with three properties. The html property will be the original text but with <span> elements wrapping each one and two letter chemical element symbols that were found (with the title attribute set to the name of the element), and <del> elements wrapping letter characters that couldn't be matched with a chemical element symbol. The result above is this first type of output.

The flags property will be an array of numbers indicating which characters in the input sentence were matched. You can then use that array to manipulate the input text character by character however you like! Example output of this second kind may look like the following.

If the original input text is "Candy Mountain" then the output array would be:

[1, 2, 1, 2, 1, 0, 1, 2, 1, 1, 1, 2, 1, 2]

Each 1 indicates that the first letter of either a one or two letter chemical element symbol was found for this letter. If the next number in the array is a 2 then the two letters together make up a two letter chemical element symbol. If instead the next number is a 1 or 0, then the the first letter is only a single letter chemical element symbol. Array elements of 0 are either letters that could not be matched, or non-letter characters that were passed through unchecked.

The final property is the elements property which is an object where the keys are all the elements used by the output, and the values associated with each key are the counts for each time those elements are used. So if the input string is "Candy Mountain" the output elements property will be:

{
  "Ca": 1,
  "Nd": 1,
  "Y": 1,
  "Mo": 1,
  "U": 1,
  "N": 1,
  "Ta": 1,
  "In": 1
}

The Javascript Code
function periodicSentence(text) {
  let output = {
    'html': '',
    'flags': Array(text.length).fill(0, 0),
    'elements': {}
  };

  let Elements = {
     'H': 'Hydrogen',     'He': 'Helium',        'Li': 'Lithium',
    'Be': 'Beryllium',     'B': 'Boron',          'C': 'Carbon',
     'N': 'Nitrogen',      'O': 'Oxygen',         'F': 'Fluorine',
    'Ne': 'Neon',         'Na': 'Sodium',        'Mg': 'Magnesium',
    'Al': 'Aluminium',    'Si': 'Silicon',        'P': 'Phosphorus',
     'S': 'Sulfur',       'Cl': 'Chlorine',      'Ar': 'Argon',
     'K': 'Potassium',    'Ca': 'Calcium',       'Sc': 'Scandium',
    'Ti': 'Titanium',      'V': 'Vanadium',      'Cr': 'Chromium',
    'Mn': 'Manganese',    'Fe': 'Iron',          'Co': 'Cobalt',
    'Ni': 'Nickel',       'Cu': 'Copper',        'Zn': 'Zinc',
    'Ga': 'Gallium',      'Ge': 'Germanium',     'As': 'Arsenic',
    'Se': 'Selenium',     'Br': 'Bromine',       'Kr': 'Krypton',
    'Rb': 'Rubidium',     'Sr': 'Strontium',      'Y': 'Yttrium',
    'Zr': 'Zirconium',    'Nb': 'Niobium',       'Mo': 'Molybdenum',
    'Tc': 'Technetium',   'Ru': 'Ruthenium',     'Rh': 'Rhodium',
    'Pd': 'Palladium',    'Ag': 'Silver',        'Cd': 'Cadmium',
    'In': 'Indium',       'Sn': 'Tin',           'Sb': 'Antimony',
    'Te': 'Tellurium',     'I': 'Iodine',        'Xe': 'Xenon',
    'Cs': 'Cesium',       'Ba': 'Barium',        'La': 'Lanthanum',
    'Ce': 'Cerium',       'Pr': 'Praseodymium',  'Nd': 'Neodymium',
    'Pm': 'Promethium',   'Sm': 'Samarium',      'Eu': 'Europium',
    'Gd': 'Gadolinium',   'Tb': 'Terbium',       'Dy': 'Dysprosium',
    'Ho': 'Holmium',      'Er': 'Erbium',        'Tm': 'Thulium',
    'Yb': 'Ytterbium',    'Lu': 'Lutetium',      'Hf': 'Hafnium',
    'Ta': 'Tantalum',      'W': 'Tungsten',      'Re': 'Rhenium',
    'Os': 'Osmium',       'Ir': 'Iridium',       'Pt': 'Platinum',
    'Au': 'Gold',         'Hg': 'Mercury',       'Tl': 'Thallium',
    'Pb': 'Lead',         'Bi': 'Bismuth',       'Po': 'Polonium',
    'At': 'Astatine',     'Rn': 'Radon',         'Fr': 'Francium',
    'Ra': 'Radium',       'Ac': 'Actinium',      'Th': 'Thorium',
    'Pa': 'Protactinium',  'U': 'Uranium',       'Np': 'Neptunium',
    'Pu': 'Plutonium',    'Am': 'Americium',     'Cm': 'Curium',
    'Bk': 'Berkelium',    'Cf': 'Californium',   'Es': 'Einsteinium',
    'Fm': 'Fermium',      'Md': 'Mendelevium',   'No': 'Nobelium',
    'Lr': 'Lawrencium',   'Rf': 'Rutherfordium', 'Db': 'Dubnium',
    'Sg': 'Seaborgium',   'Bh': 'Bohrium',       'Hs': 'Hassium',
    'Mt': 'Meitnerium',   'Ds': 'Darmstadtium',  'Rg': 'Roentgenium',
    'Cn': 'Copernicium',  'Nh': 'Nihonium',      'Fl': 'Flerovium',
    'Mc': 'Moscovium',    'Lv': 'Livermorium',   'Ts': 'Tennessine',
    'Og': 'Oganesson'
  };

  for (let x = 0, bit1, bit2; x < text.length; x++) {
    bit1 = text.substring(x, x + 1).toUpperCase();

    // If first character is not a letter, skip
    if (!bit1.match(/[A-Z]/)) continue;

    bit2 = text.substring(x + 1, x + 2).toLowerCase();

    // Check if next two letters are an element
    if (typeof Elements[bit1 + bit2] != 'undefined') {

      // If we are backtracking, the previous element letter must
      // succeed as a single letter element
      if (output['flags'][x]) {
        let bit0 = text.substring(x - 1, x).toUpperCase();
        if (typeof Elements[bit0] == 'undefined') {
          x++;
          continue;
        }
      }
      output['flags'][x] = 1;
      output['flags'][x + 1] = 2;
      x++;

    // We are currently backtracking and didn't find a match
    } else if (output['flags'][x]) {
      x++;

    // Else check if next single letter is an element
    } else if (typeof Elements[bit1] != 'undefined') {
      output['flags'][x] = 1;

    // An element was not found; if the previous symbol was a two
    // character match, backtrack to see if breaking it up will help
    } else if (x > 1 && output['flags'][x - 1] == 2) {
      x -= 2;

    }
  }

  for (let x = 0, bit1, bit2; x < text.length; x++) {
    bit1 = text.substring(x, x + 1).toUpperCase();
    bit2 = text.substring(x + 1, x + 2).toLowerCase();

    // Two character elements
    if (output['flags'][x] == 1 && x < text.length - 1 && output['flags'][x + 1] == 2) {
      output['html'] += '<span title="' + Elements[bit1 + bit2] + '">';
      output['html'] += text.substring(x, x + 2);
      output['html'] += '</span>';
      if (typeof output['elements'][bit1 + bit2] == 'undefined') {
        output['elements'][bit1 + bit2] = 1;
      } else output['elements'][bit1 + bit2]++;
      x++;

    // Single character elements
    } else if (output['flags'][x] == 1) {
      output['html'] += '<span title="' + Elements[bit1] + '">';
      output['html'] += text.substring(x, x + 1);
      output['html'] += '</span>';
      if (typeof output['elements'][bit1] == 'undefined') {
        output['elements'][bit1] = 1;
      } else output['elements'][bit1]++;

    // Non-matching letter characters
    } else if (bit1.match(/[a-zA-Z]/)) {
      output['html'] += '<del>' + text.substring(x, x + 1) + '</del>';

    // Sanitise, but otherwise ignore all other output
    } else output['html'] += text.substring(x, x + 1).replace(/</g, '&lt;').replace(/>/g, '&gt;');
  }

  return output;
}

Errors while running this script are still possible. If you don't get any output for your input, check your console output, and please let me know via comment or my contact form!

What's the longest sentence you can come up with that can be fully written in chemical element symbols? :)

Periodic table SVG image adapted from the public domain original at Wikimedia.


Comments closed

Recent posts

  1. Customize Clipboard Content on Copy: Caveats Dec 2023
  2. Orcinus Site Search now available on Github Apr 2023
  3. Looking for Orca Search 3.0 Beta Testers! Apr 2023
  4. Simple Wheel / Tire Size Calculator Feb 2023
  5. Dr. Presto - Now with MUSIC! Jan 2023
  6. Archive