7
\$\begingroup\$

Homologous series, any of numerous groups of chemical compounds in each of which the difference between successive members is a simple structural unit.

As an example, Alkane is a homologous group where the chemical compounds are in \$C_nH_{2n+2}\$ format. \$CH_4\$ (Methane) is part of the Alkane group because \$CH_4 \to C_{1}H_{2\cdot 1+2}\$ and there because there is \$n=1\$ carbon atom, so there should be \$2n+2\$ hydrogen atoms. And there is \$2×1+2 = 4\$ hydrogen atoms. So Methane or \$CH_4\$ qualifies for the Alkane group.

In this challenge we will be matching against 6 homologous groups:

  • Alkane : \$C_nH_{2n+2}\$
  • Alkene : \$C_nH_{2n}\$
  • Alkyne : \$C_nH_{2n-2}\$
  • Alcohol : \$C_nH_{2n+1}OH\$
  • Aldehyde : \$C_nH_{2n+1}CHO\$
  • Carboxylic Acid : \$C_nH_{2n+1}COOH\$

Input format will be like CH_4 \$ \to CH_4\$, CH_3CHO \$ \to CH_3CHO \$, meaning that you need to write the subscript using an underscore (_). Output should be the group the compound belongs to.

Test Cases

CH_4 -> Alkane
C_2H_4 -> Alkene
C_2H_2 -> Alkyne
CH_3OH -> Alcohol
CH_3CHO -> Aldehyde
CH_3COOH -> Carboxylic Acid

Standard loopholes apply, shortest code wins. Input is guaranteed to be in these 6 categories and valid. Output needs to be exactly capitalized as in question. \$n\$ can be less than 2 (if it is omitted assume it is 1). There will be no leading zeros in \$n\$.

\$\endgroup\$
8
  • \$\begingroup\$ Sandbox \$\endgroup\$
    – Wasif
    Apr 15, 2021 at 6:51
  • \$\begingroup\$ @tsh input is guaranteed to valid, you don't require to check for errors in input \$\endgroup\$
    – Wasif
    Apr 15, 2021 at 6:55
  • \$\begingroup\$ Is HCHO (Formaldehyde) a valid input? \$\endgroup\$
    – tsh
    Apr 15, 2021 at 6:57
  • \$\begingroup\$ @Tsh you will get input in the upper 6 formats not in others, so you will not get formaldehyde \$\endgroup\$
    – Wasif
    Apr 15, 2021 at 6:57
  • 2
    \$\begingroup\$ Suggest testcases with more than 1 digits number, such as C_12H_24 \$\endgroup\$
    – tsh
    Apr 15, 2021 at 7:15

5 Answers 5

6
\$\begingroup\$

Python 3, 134 bytes

-3 bytes thanks to @tsh

Note that it fails for CH_2. It is unclear whether such a test case is valid, but I will keep this solution for now.

lambda e:['Aldehyde','Alcohol','Carboxylic Acid',0][e[::-1].rfind('O')]or'Alk%sne'%'eay'[eval(e.translate({67:45,72:43,95:43})+'//2')]

Try it online!

Python 3, 137 bytes

Works for all cases including CH_2.

lambda e:['Aldehyde','Alcohol','Carboxylic Acid',0][e[::-1].rfind('O')]or'Alk%sne'%'yae'[eval(e.translate({67:43,72:43,95:'~-'})+'//-2')]

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ Maybe 'eay'[eval(e.translate({67:45,72:43,95:43})+'//2')]? \$\endgroup\$
    – tsh
    Apr 15, 2021 at 9:25
  • \$\begingroup\$ @tsh Thanks for the improvement! It does seem to fail on CH_2, but I don't think the question every addresses whether that is a valid case or not. I've added it, regardless. \$\endgroup\$ Apr 15, 2021 at 10:06
  • \$\begingroup\$ CH_2 is invalid as OP said (in comment) \$\endgroup\$
    – tsh
    Apr 15, 2021 at 10:10
  • 1
    \$\begingroup\$ @tsh Did the OP mention anything about CH_2? I see that it must follow the 6 formats, but it is still unclear. \$\endgroup\$ Apr 15, 2021 at 10:31
  • \$\begingroup\$ @dingledooper I was just asking the same question. :-) \$\endgroup\$
    – Arnauld
    Apr 15, 2021 at 10:32
5
\$\begingroup\$

JavaScript (Node.js), 115 bytes

s=>[[x,y]=s.match(/\d+/g),'Aldehyde','Alcohol','Carboxylic Acid'][s.length-s.search`O`]||`Alk${'aey'[x-y/2+1|0]}ne`

Try it online!

Thanks A username, -3 bytes.

\$\endgroup\$
4
  • \$\begingroup\$ String.search is shorter than String.indexOf if you can find a way to make that work? \$\endgroup\$
    – emanresu A
    Apr 15, 2021 at 9:39
  • \$\begingroup\$ 123 bytes: s=>[[x,y]=s.match(/\d+/g),'Aldehyde','Alcohol','Carboxylic Acid'][s.length-s.search`O`]||`Alk${2*x>y?'y':2*x==y?'e':'a'}ne` \$\endgroup\$
    – emanresu A
    Apr 15, 2021 at 9:52
  • \$\begingroup\$ 118 if you can use the experimental Array.at function: s=>[[x,y]=s.match(/\d+/g),'Aldehyde','Alcohol','Carboxylic Acid'].at(-s.search`O`)||`Alk${2*x>y?'y':2*x==y?'e':'a'}ne` \$\endgroup\$
    – emanresu A
    Apr 15, 2021 at 9:56
  • \$\begingroup\$ Array#at seems a good idea here. But since no browser currently support it, I will leave my code as is and avoid use it... \$\endgroup\$
    – tsh
    Apr 15, 2021 at 10:16
1
\$\begingroup\$

Retina 0.8.2, 110 bytes

.*O..
Carboxylic Acid
.*O.
Alcohol
.*O
Aldehyde
_\d+
$*
CH.*|C(1+)H11\1\1
Alkane
C(1+)H\1\1
Alkene
C1.*
Alkyne

Try it online! Link includes test cases. Explanation:

.*O..
Carboxylic Acid
.*O.
Alcohol
.*O
Aldehyde

Identify these three groups by the position of the O from the end.

_\d+
$*

Convert the suffixes to unary.

CH.*|C(1+)H11\1\1
Alkane
C(1+)H\1\1
Alkene
C1.*
Alkyne

Identify these three groups by comparing the number of carbon and hydrogen atoms.

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 122 bytes

I tried to gather all information within a single .map() statement, but this is not as competitive as I thought it would be.

s=>[`Alcohol`,`Alk${"aey"[s.split(/(\D_?)/).map(n=>++k*n?d=p-(p=n)/2:0,k=p=1)|-~d]}ne`,`Aldehyde`,,`Carboxylic Acid`][k%5]

Try it online!

How?

We split the input with:

s.split(/(\D_?)/)

Each entry in the resulting array is:

  • a letter followed by an optional _ if its position is odd
  • either an empty string or a number of its position is even

We walk through all entries and compute:

  • \$d\$ : the difference between the penultimate number and the last one divided by \$2\$, assuming that there's an additional \$1\$ at the beginning (in case it's omitted like in CH_4)
  • \$k\$ : the length of the array \$+1\$

We use \$k\bmod5\$ to figure out the main type of the homologous group:

 type     |  k | mod 5 | example
----------+----+-------+--------------------------------------------------------------
 Alk*ne   |  6 |   1   | C_2H_4   -> ['','C_','2','H_','4']
 Alcohol  | 10 |   0   | CH_3OH   -> ['','C','','H_','3','O','','H','']
 Aldehyde | 12 |   2   | CH_3CHO  -> ['','C','','H_','3','C','','H','','O','']
 Acid     | 14 |   4   | CH_3COOH -> ['','C','','H_','3','C','','O','','O','','H','']

We use the sign of \$d\$ to distinguish between Alkane, Alkene and Alkyne.

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 190 188 186 bytes

Thanks to ceilingcat for the -2.

The string is passed through a state machine that stores the initial C and O values and terminates early if there are no trailing characters after the second value. If the state ends early, then the difference between the two values is used to determine which type the molecule is; otherwise the first two trailing characters are used.

Annotated version

b,t, // State, molecule type
m[2], // C and O amounts
*a[]={"Aldehyde","Carboxylic Acid","Alcohol"};
f(char*s){
  for(b=3;*s++&&b--;) // Final states: 1 (alk[aey]ne), -1 (other)
    t=b? // Initial C and O
      m[b-1]=*s-95? // Is there an underscore (implies number)?
        1: // No, assume 1
        strtol(s+1,&s,0) // Yes, get number and go to next part
      : // Trailing characters (not alk[aey]ne)
        s[-1]-67? // First character is 'C'?
          2: // No, is alcohol
          *s==79; // Yes, either aldehyde or acid
  printf(~b?"Alk%cne":a[t],"y e a"[*m-m[1]*2+2]);
}
b,t,m[2],*a[]={"Aldehyde","Carboxylic Acid","Alcohol"};f(char*s){for(b=3;*s++&&b--;)t=b?m[b-1]=*s-95?1:strtol(s+1,&s,0):s[-1]-67?2:*s==79;printf(~b?"Alk%cne":a[t],"y e a"[*m-m[1]*2+2]);}

Try it online!

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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