Disclaimer: This challenge is extremely scientifically inaccurate. ;)
Given an input of a list of molecules, output what the result would be if they were to all combine via dehydration synthesis, if possible.
For the purposes of this challenge, although this description is inaccurate, a dehydration reaction between two molecules is performed as follows:
Remove
OH(one oxygen and one hydrogen atom) from either of the two molecules.Remove
H(a single hydrogen atom) from the other one.Combine the two molecules into one.
For instance, combining two
C6H12O6 molecules via dehydration
synthesis would result in
C12H22O11. Note that there are
two less Hs and one less O in the product than in the reactants. (These
missing parts would form H2O, hence "dehydration," but
that's irrelevant to this challenge.)
An example of molecules that cannot be combined via dehydration synthesis is
C6H12O6 +
CO2. The required amount of hydrogen and oxygen is
present, but neither OH nor H can be taken from the
CO2.
The format of the input for each molecule is a list of atoms concatenated. An
atom is always a single capital letter, possibly followed by a single lowercase
letter (you don't have to handle atoms like Uuo). Atoms may also have
integers ≥ 2 after them, representing how many of them there are; if this
number is not present, it is assumed to be 1. Atoms will never be repeated
within the same molecule.
Input may be provided as either an array/list/etc. of strings, or a single string separated by any non-alphanumeric character. Output must be a single string, but the output for "invalid input" (i.e. a list of molecules that cannot be combined via dehydration synthesis) may be any string containing at least one non-alphanumeric character (to distinguish from valid output). The order of the atoms in the output does not matter.
Since this is code-golf, the shortest code in bytes will win.
Test cases (invalid output is represented here by an asterisk *):
In Out
------------------------------------------------------------------
C6H12O6 C6H12O6 C6H12O6 C6H12O6 C6H12O6 C6H12O6 | C36H62O31
CHO5 CH2 CH2 CH2 CH2 CH2 | C6H
CHO4 CH2 CH2 CH2 CH2 CH2 | *
H H H CH3O3 | C
H H H CH4O2 | *
C6H12O6 ABCDELMNOP C6H12O6 | *
HO HO HO H3 | <empty string>
HgO4 C6H12O6 | *
HgHO4 C6H12O6 | HgH11O9C6
PdZnXeRaHO KrArKRbFH | PdZnXeRaKrArKRbF
-
1\$\begingroup\$ Flashbacks to my chem class... Nice challenge though. \$\endgroup\$Riker– Riker2016年02月17日 22:06:29 +00:00Commented Feb 17, 2016 at 22:06
2 Answers 2
Pyth (95 chars)
After seeing tiny, unreadable programs in CJam, Jelly, and Pyth, I decided to learn a golfing language, and because I am familiar with Python, I learned Pyth. Here is my code to solve this question:
FNQ aY.dm.Dd0:N"([A-Z][a-z]*)(\d*)"4;FNYFkN XkH|s@Nk1; X"O"HJ-1lQ; X"H"H*2J;FNHI@HNpNI>@HN1p@HN
The method that I have used to combine the molecules is similar to the one that I have used above implemented in Python. Here is a breakdown of that happens, statement by statement, character by character.
FNQ For N in Q (input):
m Map (same as python map())
.Dd0 Function for removing first element
:N"([A-Z][a-z]*)(\d*)"4; Get array of matches & groups
.d Convert to dict
aY Append to Y (pre-defined as an array)
FNY For N in Y:
FkN For K in N:
XkH Increment/set H[k] (H pre-defined as a dict) to the following value
|s@Nk1; if N[k] is null, then 1; else int(N[k])
X"O"HJ-1lQ; Decrement H["O"] by length of Q - 1, and set J to length of Q - 1
X"H"H*2J; Decrement H["H"] by 2 * J
FNH For N in H:
I@HN If H[N] (!= 0):
pN Print N
I>@HN1 If H[N] > 1:
p@HN Print H[N]
Test it! Note: The spaces in the code are for suppressing outputs.
Python ((削除) 337 (削除ここまで) 336 chars)
import re
i=input().split()
a,d,o,e=[],{},"",len(i)-1
for b in i:a.append(dict(re.findall(r"([A-Z][a-z]*)(\d*)",b)))
a=[{b:int(c[b])if c[b]else 1for b in c}for c in a]
for b in a:
for c in b:d[c]=c in d and d[c]+b[c]or b[c]
if"H"not in b:d["-"]=0
d["H"]-=2*e;d["O"]-=e
for b in d:o+=b+(str(d[b])if d[b]-1else"")if d[b]else""
print(o)
Here is an example of how to use this program:
sh3.14$ python dehydrate.py <-Run the program
C6H12O6 HgHO4 <-Input
O9H11C6Hg <-Output
-
\$\begingroup\$ I don't think having the user define
iis acceptable as input. Try definingiasi=input(). \$\endgroup\$Riker– Riker2016年03月17日 02:29:27 +00:00Commented Mar 17, 2016 at 2:29 -
\$\begingroup\$ @EasterlyIrk Really? I think it's valid. Look at the question again: "Input may be provided as either an array/list/etc. of strings, or a single string separated by any non-alphanumeric character." \$\endgroup\$K Zhang– K Zhang2016年03月17日 20:45:54 +00:00Commented Mar 17, 2016 at 20:45
-
\$\begingroup\$ @KZhange yes, but consensus is that you may not force the user to do anything that modifies the code. \$\endgroup\$Riker– Riker2016年03月17日 21:39:47 +00:00Commented Mar 17, 2016 at 21:39
-
-
\$\begingroup\$ @EasterlyIrk Okay, I have modified the program to be a function instead. Thanks for notifying me, by the way. \$\endgroup\$K Zhang– K Zhang2016年03月17日 22:14:24 +00:00Commented Mar 17, 2016 at 22:14