Nombrar cadenas de carbono no cíclicas

30

(¡No soy químico! Podría estar equivocado en algunas cosas, estoy escribiendo lo que aprendí en la escuela secundaria)

Los átomos de carbono tienen un atributo especial: se pueden unir a otros 4 átomos (que no es tan especial) y se mantienen estables incluso en cadenas largas, lo cual es muy singular. Debido a que se pueden encadenar y combinar de muchas maneras diferentes, necesitamos algún tipo de convención de nomenclatura para nombrarlos.

Esta es la molécula más pequeña que podemos hacer:

CH4

Se llama metano. Se compone de un solo carbono y 4 átomos de hidrógeno. El siguiente es:

CH3 - CH3

Esto se llama etano. Está formado por 2 átomos de carbono y 6 de hidrógeno.

Los siguientes 2 son:

CH3 - CH2 - CH3
CH3 - CH2 - CH2 - CH3

Son propano y butano. Los problemas comienzan con las cadenas con 4 átomos de carbono, ya que se pueden construir de 2 maneras diferentes. Uno se muestra arriba y el otro es:

CH3 - CH - CH3
       |
      CH3

Obviamente, esto no es lo mismo que el otro. El número de átomos y las uniones son diferentes. ¡Por supuesto, simplemente doblar las uniones y rotar la molécula no la hará diferente! Así que esto:

CH3 - CH2 - CH2 - CH3

Y esto:

CH3 - CH2
       |
CH3 - CH2

Son lo mismo (si te gusta la teoría de grafos, puedes decir que si hay isomorfismo entre 2 moléculas; son lo mismo). De ahora en adelante no escribiré átomos de hidrógeno ya que no son esenciales para este desafío.

Como odias la química orgánica y tienes muchos átomos de carbono diferentes para nombrar, decides escribir un programa que haga esto por ti. No tienes demasiado espacio en tu disco duro, por lo que el programa debe ser lo más pequeño posible.

El reto

Escriba un programa que tome un texto de varias líneas como entrada (una cadena de carbono) y genere el nombre de la cadena de carbono. La entrada solo contendrá espacios, letras mayúsculas 'c' y '|' y '-' que representa un enlace. ¡La cadena de entrada nunca contendrá ciclos! Ejemplo:

Entrada:

C-C-C-C-C-C
  |   |
  C   C-C

Salida:

4-etil-2-metilhexano

Cualquier salida es aceptable siempre que sea legible por humanos y esencialmente igual (por lo que puede usar diferentes separadores, por ejemplo, si lo desea).

La convención de nomenclatura:

(Ver: reglas de IUPAC )

  1. Identifica la cadena de carbono más larga. Esta cadena se llama la cadena principal.

  2. Identifique todos los sustituyentes (grupos anexos de la cadena principal).

  3. Numere los carbonos de la cadena principal desde el extremo que les da a los sustituyentes los números más bajos. Al comparar una serie de números, la serie que es la "más baja" es la que contiene el número más bajo en la primera diferencia. Si dos o más cadenas laterales se encuentran en posiciones equivalentes, asigne el número más bajo al que aparezca primero en el nombre.

  4. Si se produce el mismo sustituyente más de una vez, se proporciona la ubicación de cada punto en el que se produce el sustituyente. Además, el número de veces que se produce el grupo sustituyente se indica mediante un prefijo (di, tri, tetra, etc.).

  5. Si hay dos o más sustituyentes diferentes, se enumeran en orden alfabético utilizando el nombre base (ignore los prefijos). El único prefijo que se utiliza al colocar los sustituyentes en orden alfabético es iso como en isopropilo o isobutilo. Los prefijos sec y tert no se usan para determinar el orden alfabético, excepto cuando se comparan entre sí.

  6. Si las cadenas de igual longitud compiten por la selección como la cadena principal, entonces la elección va en serie a:

    • La cadena que tiene el mayor número de cadenas laterales.
    • la cadena cuyos sustituyentes tienen los números más bajos.
    • La cadena tiene el mayor número de átomos de carbono en la cadena lateral más pequeña.
    • la cadena tiene las cadenas laterales menos ramificadas (un gráfico que tiene el menor número de hojas).

Para la cadena principal, el nombre es:

Number of carbons   Name
1                  methane
2                  ethane
3                  propane
4                  butane
5                  pentane
6                  hexane
7                  heptane
8                  octane
9                  nonane
10                 decane
11                 undecane
12                 dodecane

Ninguna cadena será más larga que 12, por lo que será suficiente. Para las subcadenas es lo mismo pero en lugar de 'ane' al final tenemos 'yl'.

Puede suponer que los Cs están en las columnas impares y los enlaces ( |y los -caracteres) tienen 1 longitud entre los átomos de carbono.

Casos de prueba:

Entrada:

C-C-C-C

Salida:

butano

Entrada:

C-C-C
  |
  C

Salida:

2-metilpropano

Entrada:

C-C-C-C
  |
  C
  |
  C-C

Salida:

3-metilhexano

Entrada:

C-C-C-C-C
  |
  C
  |
  C

Salida:

3-metilhexano

Entrada:

    C
    |
    C
    |
C-C-C-C
  |
  C-C-C
  |
  C-C

Salida:

3,4-dimetil-5-etilheptano

Editar: Perdón por los ejemplos equivocados. No era un buen estudiante :(. Deberían arreglarse ahora.

Peter Lenkefi
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Dennis
2
Según esta regla, If the same substituent occurs more than once, the location of each point on which the substituent occurs is given. In addition, the number of times the substituent group occurs is indicated by a prefix (di, tri, tetra, etc.).¿no debería llamarse el último ejemplo 3,4- di metil-5-etilheptano? (recién estamos comenzando la química orgánica, podría estar equivocado: P)
NieDzejkob
@NieDzejkob Estoy de acuerdo, ya que hay dos cadenas de metilo.
Jonathan Frech el
@NieDzejkob De hecho, arreglado.
Peter Lenkefi el

Respuestas:

18

Python 2 , 1876 1871 1870 1859 1846 1830 1826 1900 1932 1913 1847 1833 1635 1613 1596 bytes

s=input().split('\n')
W=enumerate
J=len
Y=sorted
l=J(s[0])
s=''.join(s)
S=set
M=max
A=min
p=map
f=lambda k:[(x/l,x%l)for x,V in W(s)if V==k]
g=lambda x,i,h=lambda x,i,j:x[:i]+(x[i]+j,)+x[i+1:]:[(h(q,i,-1),h(q,i,1))for q in x]
v=f('C');e=g(f('-'),1)+g(f('|'),0)
E=[V for V in v if sum(e,()).count(V)==1]
o=lambda v:[E[~E.index(v)]for E in e if v in E]
T=lambda a:lambda b:z((a,b))
Z=lambda a:p(T(a[0]),a[1])
n=lambda R:'mepbphhondudetrueeeco nothotnxptn ddh p t t'[R-1::12].strip()+(R>9)*'ec'
G=lambda K:[H[i]for i,V in W(K)if V==A(K)]
q=lambda x:[`k[0]`for k in H if k[1]==x]
B='-'.join
def z(n,c=[]):k=[x for x in S(o(n[0]))-S(c)];p=[z((j,n[1]),c+k)for j in k];return 1-~-(n[0]==n[1])*(p and A(p)or J(v))
C=[(a,b)for a in E for b in E]
a=p(z,C)
s=[(k,[E for E in v if~-z((k[0],E))+z((k[1],E))==z((k[0],k[1]))])for k in[C[x]for x,V in W(a)if V==M(a)]]
H=[]
R=0
for k,_ in s:R=M(J(_),R);_.sort(key=T(k[0]));a=sum([list(S(o(k))-S(_))for k in _],[]);H+=zip(p(lambda a:Z((a,_)).index(2),a),p(Z,[(O,[x for x in S(v)-S(_)if z((x,O),_)<J(v)])for O in a])),
X=n(R)
U=any(H)
if U:H=G([[h[0]for h in Q]for Q in H if J(Q)==M(p(J,H))]);K=[[J(Q[1])for Q in j]for j in H];H=[H[i]for i,V in W(K)if A(V)==A(sum(K,[]))];K=[J([Q[1]for Q in j if J(S(Q[1]))-J(Q[1])])for j in H];H=[[p[0]+1,n(M(p[1]))+[['isopropyl','butyl-tert','butyl-sec','isobutyl'][J(p[1])+p[1].count(3)-3],'yl'][Y(p[1])==range(1,1+M(p[1]))]]for p in G(K)[0]]
print(U and B([','.join(q(x))+'-'+'dttphhondireeeecoe itnxptnc  rtataaa  aa a '[J(q(x))-2::9].strip()+B(x.split('-')[::-1])for x in Y(list(S(zip(*H)[1])))])+X or[X,'meth']['t'==X])+'ane'

Pruébalo en línea!

Bueno, allá vas. Ciertamente no es el más golfista pero funciona (espero): D

Me llevó unas 10 horas, tal vez? Probablemente mi golf más largo tanto en tamaño como en tiempo, y eso dice algo considerando que solía usar Java D:

Lógica:

  1. Convierta de la representación ASCII a la representación gráfica con cada átomo de carbono como un nodo y cada enlace como un borde representado en forma de adyacencia.
  2. Encuentra todas las hojas; es decir, nodos con un solo enlace. Se garantiza que la cadena más larga sea de una a otra.
  3. Encuentra el producto diádico de las hojas; es decir, todos los pares de nodos de borde. Luego, toma la longitud de todas estas cadenas.
  4. Para cada cadena, encuentra sus subcadenas.
  5. Haz cosas para elegir la cadena correcta. Si hay vínculos, entonces realmente no importa. Dato curioso: siempre habrá un empate porque cada cadena se cuenta dos veces, una a la inversa.
  6. Imprimirlo correctamente.

EDITAR : Se corrigió el error donde solía causar errores si no había cadenas laterales.

EDITAR : Gracias a MD XF por notar algunos espacios adicionales (sangría para el bucle for).

EDITAR : Olvidé por completo el prefijo para tener el mismo sustituyente.

NOTA : cada línea debe tener el mismo ancho para que esto funcione. Es decir, se requieren espacios finales.

Dato curioso: la mayoría de los hidrocarburos cíclicos se determinarán como "metano"

Dato curioso: Si lo hace C-C-...-C-Ccon 13 Cs, se le dará ethane, a continuación, thanepara el 14, ropane15, etc.

-79 bytes gracias a Jonathan Frech
-119 bytes gracias a NieDzejkob
-17 bytes gracias a ovs

Hiperneutrino
fuente