命名非环状碳链


30

(我不是化学家!我可能在某些方面写错了,我正在写我在高中学到的东西)

碳原子具有特殊的属性:它们可以与其他4个原子键合(不是很特殊),即使在长链中也保持稳定,这是非常独特的。因为它们可以通过许多不同的方式链接和组合,所以我们需要某种命名约定来命名它们。

这是我们可以制造的最小分子:

CH4

叫做甲烷。它仅包含一个碳原子和4个氢原子。下一个是:

CH3 - CH3

这称为乙烷。它由2个碳原子和6个氢原子组成。

接下来的两个是:

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

它们是丙烷和丁烷。问题始于具有4个碳原子的链,因为它可以用2种不同的方式构建。上面显示了一个,另一个是:

CH3 - CH - CH3
       |
      CH3

显然这与另一个不同。原子数和键数不同。当然,仅仅折叠结合物并旋转分子不会使它变得与众不同!所以这:

CH3 - CH2 - CH2 - CH3

和这个:

CH3 - CH2
       |
CH3 - CH2

是相同的(如果您从事图论,您可以说两个分子之间存在同构;它们是相同的)。从现在开始,我将不再写氢原子,因为氢原子对于这一挑战不是必需的。

当您讨厌有机化学并且要命名的碳原子很多时,您决定编写一个程序来为您完成此任务。您的硬盘驱动器上没有太多空间,因此程序必须尽可能小。

挑战

编写一个程序,将多行文本作为输入(碳链)并输出碳链的名称。输入将仅包含空格,大写的“ c”字符和“ |” 和“-”表示绑定。输入链将永远不会包含循环!例:

输入:

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

输出:

4-乙基-2-甲基己烷

任何输出都是可接受的,只要它是人类可读的并且基本上是相同的(因此,您可以根据需要使用不同的分隔符)。

命名约定:

(请参阅:IUPAC规则

  1. 确定最长的碳链。该链称为父链。

  2. 确定所有取代基(从母链附加的基团)。

  3. 从赋予取代基最低编号的末端开始编号母链碳原子。比较一系列数字时,“最低”的序列是在出现第一个差异时包含最低数字的序列。如果两个或多个侧链在相同位置,则将最低编号分配给名称中最先出现的编号。

  4. 如果相同的取代基出现不止一次,则给出取代基出现在每个点的位置。另外,取代基出现的次数由前缀(di,tri,tetra等)表示。

  5. 如果有两个或多个不同的取代基,则使用基本名称按字母顺序列出(忽略前缀)。当按字母顺序排列取代基时,唯一使用的前缀是异丙​​基或异丁基中的iso。除非彼此比较,否则前缀sec-和tert-不会用于确定字母顺序。

  6. 如果长度相等的链竞争作为父链的选择,那么选择将依次进行:

    • 侧链数量最多的链。
    • 取代基数最低的链。
    • 在最小的侧链中碳原子数最大的链。
    • 侧链最少的链(叶子数量最少的图表)。

对于父链,命名为:

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

没有链长于12,因此就足够了。对于子链来说是相同的,但是最后没有“ ane”,而是“ yl”。

您可以假设Cs在奇数列中,|并且-碳原子之间的绑定(和字符)长1。

测试用例:

输入:

C-C-C-C

输出:

丁烷

输入:

C-C-C
  |
  C

输出:

2-甲基丙烷

输入:

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

输出:

3-甲基己烷

输入:

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

输出:

3-甲基己烷

输入:

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

输出:

3,4-二甲基-5-乙基庚烷

编辑:对不起,错误的例子。我不是一个好学生:(。他们现在应该固定。


评论不作进一步讨论;此对话已转移至聊天
丹尼斯,

2
根据此规则,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.).不应将最后一个例子称为3,4- 甲基-5-乙基庚烷吗?(我们才刚刚开始有机化学,我可能是错的:P)
NieDzejkob

@NieDzejkob我同意,因为有两条甲基链。
乔纳森·弗雷希

@NieDzejkob确实,已修复。
彼得·伦克菲

Answers:


18

Python 2中1876年 1871 1870 1859 1846 1830 1826 1900 1932 1913 1847 1833 1635 1613 1596个字节

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'

在线尝试!

好吧,你去。当然不是最高尔夫的,但它能起作用(我希望):D

大概花了我10个小时?可能是我在时间和尺寸上最长的一次高尔夫,这是考虑到我以前使用Java D的一些信息:

逻辑:

  1. 从ASCII表示转换为图形表示,每个碳原子为一个节点,每个键为边,以邻接形式表示。
  2. 找到所有叶子;也就是说,只有一个键的节点。最长的链保证是从其中一个到另一个。
  3. 找到叶子的二乘积;即所有边缘节点对。然后,计算所有这些链的长度。
  4. 对于每个链,找到其子链。
  5. 做一些事情来选择正确的链条。如果有联系,那就没关系了。有趣的事实:总会有一个平局,因为每个链条都被计算两次,一次反向。
  6. 正确打印。

编辑:修复了如果没有侧链会导致错误的错误。

编辑:感谢MD XF注意到一些额外的空格(for循环的缩进)。

编辑:我完全忘记了具有相同取代基的前缀。

注意:每行都必须具有相同的宽度才能正常工作。即,需要尾随空格。

有趣的事实:大多数环状烃将被确定为“甲烷”

有趣的事实:如果您C-C-...-C-C使用13 C,它将给出ethane,然后thane取14,ropane取15,等等。

-79字节归功于Jonathan Frech
-119字节归功于NieDzejkob
-17字节归功于ovs

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.