非環状炭素鎖の命名


30

(私は化学者ではありません!私はいくつかの点で間違っているかもしれません、私は高校で学んだことを書いています)

炭素原子には特別な属性があります:他の4つの原子(これは特別ではありません)に結合でき、非常にユニークな長い鎖であっても安定しています。これらはさまざまな方法で連鎖および結合できるため、それらに名前を付けるには何らかの命名規則が必要です。

これは、作成可能な最小の分子です。

CH4

メタンと呼ばれます。1つの炭素と4つの水素原子のみで構成されています。次は:

CH3 - CH3

これはエタンと呼ばれます。2つの炭素と6つの水素原子で構成されています。

次の2つは:

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

それらはプロパンとブタンです。問題は2つの異なる方法で構築できるため、4つの炭素原子を持つ鎖から始まります。1つは上に示し、もう1つは次のとおりです。

CH3 - CH - CH3
       |
      CH3

これは明らかに他のものと同じではありません。原子の数と結合は異なります。もちろん、結合を折り畳んで分子を回転させるだけでは、別のものになりません!したがって、この:

CH3 - CH2 - CH2 - CH3

この:

CH3 - CH2
       |
CH3 - CH2

同じです(グラフ理論に興味があるなら、2つの分子の間に同型があると言うかもしれません;それらは同じです)。水素原子はこの挑戦に不可欠ではないので、今後は書きません。

有機化学が嫌いで、名前を付ける炭素原子がたくさんあるので、これを行うプログラムを作成することにします。ハードドライブの空き容量があまりないため、プログラムはできるだけ小さくする必要があります。

チャレンジ

複数行のテキストを入力(カーボンチェーン)として取り込み、カーボンチェーンの名前を出力するプログラムを作成します。入力には、スペース、大文字の「c」文字、および「|」のみが含まれます。および「-」はバインディングを表します。入力チェーンにサイクルが含まれることはありません!例:

入力:

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

出力:

4-エチル-2-メチルヘキサン

人間が読める形式であり、本質的に同じである限り、どんな出力も受け入れられます(たとえば、必要に応じて異なるセパレータを使用できます)。

命名規則:

(参照:IUPACルール

  1. 最長の炭素鎖を特定します。このチェーンは、親チェーンと呼ばれます。

  2. すべての置換基(親鎖から付加するグループ)を特定します。

  3. 置換基に最小の数を与える末端から親鎖の炭素に番号を付けます。一連の数値を比較する場合、「最も低い」系列は、最初の違いの際に最も小さい数値を含むものです。2つ以上のサイドチェーンが同等の位置にある場合は、名前の最初に来るものに最も小さい番号を割り当てます。

  4. 同じ置換基が複数回出現する場合、置換基が出現する各ポイントの位置が示されます。さらに、置換基が発生する回数は、接頭辞(di、tri、tetraなど)で示されます。

  5. 2つ以上の異なる置換基がある場合、それらはベース名を使用してアルファベット順にリストされます(プレフィックスは無視します)。アルファベット順に置換基を配置するときに使用される唯一の接頭辞は、イソプロピルまたはイソブチルのように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- ethylheptane?(私たちはちょうど有機化学を始めている、私は間違っているかもしれない:P)
-NieDzejkob

@NieDzejkob 2つのメチル鎖があるので、私は同意するでしょう。
ジョナサン

@NieDzejkob確かに、修正されました。
ピーターレンケフィ

回答:


18

パイソン21876 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. すべての葉を見つけます。つまり、結合が1つだけのノードです。最も長いチェーンは、これらの1つから別のものへの保証です。
  3. 葉のダイアディック製品を見つけます。つまり、エッジノードのすべてのペア。次に、これらすべてのチェーンの長さを取得します。
  4. 各チェーンについて、そのサブチェーンを見つけます。
  5. 適切なチェーンを選択するための作業を行います。関係がある場合、それは実際には問題ではありません。おもしろい事実:各チェーンは逆に1回ずつ2回カウントされるため、常に同点になります。
  6. 正しく印刷してください。

編集:サイドチェーンがなかった場合にエラーが発生するバグを修正しました。

編集:いくつかの余分なスペース(forループのインデント)に気づいたMD XFに感謝します。

編集:同じ置換基を持つための接頭辞を完全に忘れました。

注意:これを機能させるには、各行を同じ幅にする必要があります。つまり、末尾のスペースが必要です。

楽しい事実:ほとんどの環状炭化水素は「メタン」として決定されます

楽しい事実:これを行うとC-C-...-C-C13件のCsと、それが与えるethane、その後、thane14のためropaneなど、15のために

-79バイト、Jonathan Frechに
感謝-119バイト、NieDzejkobに
感謝-17バイト、ovsに感謝

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.