An elementary challenge

16

This challenge is inspired by this Oliver Sacks quote:

“At 11, I could say ‘I am sodium’ (Element 11), and now at 79, I am gold.” ― Oliver Sacks

I want you you find numbers in a string and replace them with their corresponding elements' symbols. (1 is H, 2 is He, 3 is Li, etc.) There are a few rules to follow:

  • Single and double digits get replaced with their corresponding elements as normal. Ignore 0s at the start of numbers. If there are just 0s in a number, ignore it. E.g. 1 01 10 0 00 becomes H H Ne 0 00
  • More than 2 digits together get divided into groups of 2. An odd number of digits should have the extra single digit at the end. E.g. 0153 5301 153 would become HI IH PLi Because of this rule, you will only need to know the elements from 1 to 99
  • Numbers shall be treated the same no matter what characters surround them and commas and decimal points are not parts of numbers. P90X 42,800 3.14159 would become PThX Mo,Hg0 Li.SiPF

Example Inputs/Outputs (I/O):

I: 32289216
O: GeNiUS

I: J08017 5811
O: JOHN CeNa

I: M18227 0592tt10r
O: MArTiN BUttNer

I: De072816
O: DeNNiS

I: D088r1907085
O: DOOrKNOB

I: 13ex A.
O: Alex A.

Input will be in the closest format to a string that your language has.

A periodic table for reference:

This is , so your program will be scored in bytes.

DanTheMan

Posted 2015-10-27T23:21:00.527

Reputation: 3 140

17John Cena is a moderator at PPCG? ;-) – Level River St – 2015-10-28T00:27:55.157

5Please give a warm welcome to our new moderator JOHN CENA music and airhorns start blaring – a spaghetto – 2015-10-29T01:58:20.760

instantcena.com – DanTheMan – 2015-10-29T12:54:01.087

Answers

7

Mathematica, 96 94 89 bytes

StringReplace[#,n:DigitCharacter~Repeated~2/;(d=FromDigits@n)>0:>d~ElementData~"Symbol"]&

Mma has several datasets...

LegionMammal978

Posted 2015-10-27T23:21:00.527

Reputation: 15 731

Well of course a built-in dataset will beat a 139-byte compressed string. ;) – ETHproductions – 2015-10-28T14:08:52.137

@ETHproductions I'm just surprised that this has been the shortest answer for 9 hours. Usually, this place is reserved for CJam and Pyth :D – LegionMammal978 – 2015-10-28T20:57:28.130

Well, let's see: to beat 89 bytes, one would either need to super-condense the 184 necessary alphabetic characters—AND create a program to decode it—in under 89 bytes (very very unlikely), OR find another language which has a built-in dataset of the proper elements (neither CJam or Pyth). So this will likely end up being the winner. – ETHproductions – 2015-10-29T15:14:14.723

3

JavaScript (ES6), 202 bytes

x=>x.replace(/\d\d?/g,y=>+y?btoa`(139 bytes; see hexdump below)`.match(/[A-Z][a-z]?/g)[+y]:y)

The omitted string contains unprintable characters, so here is a (hopefully reversible) hexdump:

00000000: 0071 de2e 205e 0423 4e14 d78d 68c8 0095 288f  .qÞ. ^.#N.×.hÈ..(.
00000012: 4829 40ac a09a 49c4 e254 2acc 9c57 82a0 d882  H)@¬ .IÄâT*Ì.W. Ø.
00000024: b999 c668 6780 b127 81ac aad1 6d2a d866 b35b  ¹.Æhg.±'.¬ªÑm*Øf³[
00000036: 3284 dc46 e461 3dd0 2009 d227 4a74 9b4d e217  2.ÜFäa=Ð .Ò'Jt.Mâ.
00000048: 782b 0168 b682 78fa cd74 f992 984b 8675 36c3  x+.h¶.xúÍtù..K.u6Ã
0000005a: c87a 04ad 3998 6cbb 877d 3696 45e3 ac22 b3ed  Èz..­9.l».}6.Eã¬"³í
0000006c: 02e1 e04e 53db 0623 e802 d467 16b4 5a01 c4e1  .áàNSÛ.#è.Ôg.´Z.Äá
0000007e: 3da5 0da4 fb80 9829 8190 27c4 b0              =¥.¤û..)..'Ä°

The technique here was to put all the element abbreviations in one string, separated by nothing—that's what the second regex /[A-Z][a-z]?/g is for; it matches each capital letter, optionally followed by a lowercase letter. The first regex, /\d\d?/g, matches each set of 2 (or 1) digits in the input, so this replaces each set of digits N with the element at index N in the decompressed, matched string.

Here's the original string, if anyone else would like to use it: (the A's at the ends are fillers)

AHHeLiBeBCNOFNeNaMgAlSiPSClArKCaScTiVCrMnFeCoNiCuZnGaGeAsSeBrKrRbSrYZrNbMoTcRuRhPdAgCdInSnSbTeIXeCsBaLaCePrNdPmSmEuGdTbDyHoErTmYbLuHfTaWReOsIrPtAuHgTlPbBiPoAtRnFrRaAcThPaUNpPuAmCmBkCfEsA

Questions and suggestions welcome!

ETHproductions

Posted 2015-10-27T23:21:00.527

Reputation: 47 880

1What about Uus and Uuo? – Conor O'Brien – 2015-10-28T02:42:25.267

3@CᴏɴᴏʀO'Bʀɪᴇɴ - The question only requires up to element 99, which is Einsteinium (Es), so the unconfirmed elements (which therefore don't have final names, and are written with three characters) don't factor in at all. – Glen O – 2015-10-28T05:19:58.540

Nice. I think you don't need the check +y?...:... as you are replacing digit groups – edc65 – 2015-10-28T07:05:37.230

@edc65 Thanks. One of the rules is that any 00's in the input need to be unchanged, so that check is necessary. – ETHproductions – 2015-10-28T13:00:49.210

now I see. Still you can use [y] instead of [+y] and save 1 byte – edc65 – 2015-10-29T07:09:29.923

@edc65 Thanks again, but this time, numbers in the range 01-09 become undefined. – ETHproductions – 2015-10-29T15:10:23.640

1

Python 3, 278 285 bytes

import re;f=lambda a:re.sub('(?!00)\d\d?',lambda m:'0HHLBBCNOFNNMASPSCAKCSTVCMFCNCZGGASBKRSYZNMTRRPACISSTIXCBLCPNPSEGTDHETYLHTWROIPAHTPBPARFRATPUNPACBCE  eie     eagli  lr aci rneoiunaeserrbr rbocuhdgdnnbe esaaerdmmudbyormbufa esrtuglbiotnracha pummkfs'[int(m.group())::100].strip(),a)

Test cases:

>>> f('32289216')
'GeNiUS'
>>> f('J08017 5811')
'JOHN CeNa'
>>> f('M18227 0592tt10r')
'MArTiN BUttNer'
>>> f('De072816')
'DeNNiS'
>>> f('D088r1907085')
'DOOrKNOB'
>>> f('13ex A.')
'Alex A.'
>>> f('P90X 42,800 3.14159')
'PThX Mo,Hg0 Li.SiPF'
>>> f('1 01 10 0 00')
'H H Ne 0 00'

kennytm

Posted 2015-10-27T23:21:00.527

Reputation: 6 847

f('P90X 42,800 3.14159') returns 'PThX Mo,Hgs Li.SiPF' instead of 'PThX Mo,Hg0 Li.SiPF' and f('1 01 10 0 00') returns 'H H Ne s s' instead of 'H H Ne 0 00'. By the way, I just used your extended slicing approach in my Python 2 solution. Thanks! – cr3 – 2015-10-29T01:26:00.497

@cr3: Fixed 0 and 00. – kennytm – 2015-10-29T02:56:18.887

nice, you beat me by 19 bytes! – cr3 – 2015-10-29T03:29:03.913

0

Python 2, 312 304 bytes

import re
f=lambda a:''.join([j or'0HHLBBCNOFNNMASPSCAKCSTVCMFCNCZGGASBKRSYZNMTRRPACISSTIXCBLCPNPSEGTDHETYLHTWROIPAHTPBPARFRATPUNPACBCE0 eie     eagli  lr aci rneoiunaeserrbr rbocuhdgdnnbe esaaerdmmudbyormbufa esrtuglbiotnracha pummkfs'[int(i)::100].strip() for i,j in re.findall('(\d\d|[1-9])|(.)',a)])

This one creates a function f which takes a string of numbers as argument and returns the corresponding string with element symbols replaced.

The function iterates over strings of one to two digits ('1', '01', '10', '00' but not '0') or one character ('a', '0' but not '1'). In the case of digits, the string is converted to an integer and looked up in a concatenated string of element symbols where each symbol is padded to two characters. In the case of characters, the string is simply used without lookup.

The tests for each example in the question all pass:

assert f('P90X 42,800 3.14159') == 'PThX Mo,Hg0 Li.SiPF'
assert f('1 01 10 0 00') == 'H H Ne 0 00'
assert f('0153 5301 153') == 'HI IH PLi'
assert f('32289216') == 'GeNiUS'
assert f('J08017 5811') == 'JOHN CeNa'
assert f('M18227 0592tt10r') == 'MArTiN BUttNer'
assert f('De072816') == 'DeNNiS'
assert f('D088r1907085') == 'DOOrKNOB'
assert f('13ex A.') == 'Alex A.'

cr3

Posted 2015-10-27T23:21:00.527

Reputation: 181