Nomeando cadeias de carbono não cíclicas

30

(Eu não sou químico! Posso estar errado em algumas coisas, estou escrevendo o que aprendi no ensino médio)

Os átomos de carbono têm um atributo especial: eles podem se ligar a outros 4 átomos (o que não é tão especial) e permanecem estáveis ​​mesmo em cadeias longas, o que é muito único. Como eles podem ser encadeados e combinados de várias maneiras diferentes, precisamos de algum tipo de convenção de nomes para nomeá-los.

Esta é a menor molécula que podemos fazer:

CH4

Chama-se metano. Consiste em apenas um carbono e 4 átomos de hidrogênio. O próximo é:

CH3 - CH3

Isso é chamado etano. É composto de 2 átomos de carbono e 6 de hidrogênio.

Os próximos 2 são:

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

Eles são propano e butano. Os problemas começam com as cadeias com 4 átomos de carbono, pois podem ser construídas de duas maneiras diferentes. Um é mostrado acima e o outro é:

CH3 - CH - CH3
       |
      CH3

Obviamente, isso não é o mesmo que o outro. O número de átomos e as ligações são diferentes. É claro que apenas dobrar as ligações e girar a molécula não a tornará diferente! Então, é isso:

CH3 - CH2 - CH2 - CH3

E isto:

CH3 - CH2
       |
CH3 - CH2

São os mesmos (se você gosta da teoria dos grafos, pode dizer que, se houver isomorfismo entre duas moléculas; elas são iguais). De agora em diante, não escreverei átomos de hidrogênio, pois eles não são essenciais para esse desafio.

Como você odeia química orgânica e tem muitos átomos de carbono diferentes para citar, você decide escrever um programa que faz isso por você. Você não tem muito espaço no disco rígido, portanto o programa deve ser o menor possível.

O desafio

Escreva um programa que receba um texto de várias linhas como entrada (uma cadeia de carbono) e emita o nome da cadeia de carbono. A entrada conterá apenas espaços, caracteres 'c' maiúsculos e '|' e '-' que representa uma ligação. A cadeia de entrada nunca conterá ciclos! Exemplo:

Entrada:

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

Saída:

4-etil-2-metil-hexano

Qualquer saída é aceitável desde que seja legível por humanos e essencialmente a mesma (portanto, você pode usar separadores diferentes, por exemplo, se desejar).

A convenção de nomenclatura:

(Veja: regras da IUPAC )

  1. Identifique a cadeia de carbono mais longa. Essa cadeia é chamada de cadeia pai.

  2. Identifique todos os substituintes (grupos anexados à cadeia parental).

  3. Numere os carbonos da cadeia parental a partir do final que fornece aos substituintes os números mais baixos. Ao comparar uma série de números, a série que é a "mais baixa" é aquela que contém o número mais baixo na ocasião da primeira diferença. Se duas ou mais cadeias laterais estiverem em posições equivalentes, atribua o número mais baixo àquele que virá primeiro no nome.

  4. Se o mesmo substituinte ocorrer mais de uma vez, é dada a localização de cada ponto em que o substituinte ocorre. Além disso, o número de vezes que o grupo substituinte ocorre é indicado por um prefixo (di, tri, tetra, etc.).

  5. Se houver dois ou mais substituintes diferentes, eles serão listados em ordem alfabética usando o nome da base (ignore os prefixos). O único prefixo que é usado ao colocar os substituintes em ordem alfabética é iso como em isopropil ou isobutil. Os prefixos sec e tert- não são usados ​​para determinar a ordem alfabética, exceto quando comparados entre si.

  6. Se cadeias de comprimento igual estão competindo pela seleção como a cadeia pai, a escolha vai em série para:

    • a corrente que tem o maior número de cadeias laterais.
    • a cadeia cujos substituintes têm os números mais baixos.
    • a cadeia com o maior número de átomos de carbono na menor cadeia lateral.
    • a cadeia com as cadeias laterais menos ramificadas (um gráfico com o menor número de folhas).

Para a cadeia pai, a nomeação é:

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

Nenhuma corrente terá mais de 12 anos, portanto isso será suficiente. Para as sub-cadeias é o mesmo, mas em vez de 'ane' no final, temos 'yl'.

Você pode assumir que os Cs estão nas colunas ímpares e as ligações ( |e -caracteres) têm 1 comprimento entre os átomos de carbono.

Casos de teste:

Entrada:

C-C-C-C

Saída:

butano

Entrada:

C-C-C
  |
  C

Saída:

2-metilpropano

Entrada:

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

Saída:

3-metilhexano

Entrada:

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

Saída:

3-metilhexano

Entrada:

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

Saída:

3,4-dimetil-5-etil-heptano

Edit: Desculpe pelos exemplos errados. Eu não era um bom aluno :(. Eles devem ser corrigidos agora.

Peter Lenkefi
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Dennis
2
De acordo com essa regra, 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.).o último exemplo não deveria ser chamado de 3,4- di -metil-5-etil-heptano? (nós estamos apenas começando a química orgânica, eu poderia estar errado: P)
NieDzejkob
@NieDzejkob Eu concordo, pois existem duas cadeias de metil.
Jonathan Frech
@NieDzejkob De fato, corrigido.
27568 Peter Pan

Respostas:

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'

Experimente online!

Bem, lá vai você. Certamente não é o golfiest, mas funciona (espero): D

Levei cerca de 10 horas, talvez? Provavelmente o meu golfe mais longo, tanto em tamanho quanto em tempo, e isso está dizendo algo, considerando que eu costumava usar o Java D:

Lógica:

  1. Converta da representação ASCII para representação gráfica com cada átomo de carbono como um nó e cada ligação como uma aresta representada na forma de adjacência.
  2. Encontre todas as folhas; isto é, nós com apenas uma ligação. A cadeia mais longa é garantida de uma para outra.
  3. Encontre o produto diádico das folhas; ou seja, todos os pares de nós de borda. Depois, pegue o comprimento de todas essas cadeias.
  4. Para cada cadeia, encontre suas sub-cadeias.
  5. Faça coisas para escolher a corrente certa. Se houver laços, isso realmente não importa. Curiosidade: sempre haverá um empate, pois cada cadeia é contada duas vezes, uma vez ao contrário.
  6. Imprima corretamente.

EDIT : Corrigido o erro em que costumava causar erros se não houvesse cadeias laterais.

EDIT : Agradecimentos ao MD XF por observar alguns espaços extras (recuo para o loop for).

EDIT : Esqueci completamente o prefixo por ter o mesmo substituinte.

NOTA : Cada linha precisa ter a mesma largura para que isso funcione. Ou seja, são necessários espaços à direita.

Curiosidade: a maioria dos hidrocarbonetos cíclicos será determinada como "metano"

Curiosidade: se você fizer C-C-...-C-C13 Cs, ele dará ethane, então thane, 14, ropane15, etc.

-79 bytes graças a Jonathan Frech
-119 bytes graças a NieDzejkob
-17 bytes graças a ovs

HyperNeutrino
fonte