Степень ненасыщенности

11

Степень ненасыщенности

Это не особенно сложная головоломка, но мне интересно увидеть ваши многочисленные способы ее решения.

Степень ненасыщенности - это число двойных химических связей между атомами и / или число колец в химическом соединении.

Вам будет дана молекулярная формула химического соединения в форме XaYbZc (где a, b и c - число атомов X, Y или Z в соединении) - формула может иметь любую длину и содержать любой химический элемент в периодической таблице (хотя элементы, отличные от C, H, N, F, Cl, Br, I могут игнорироваться, поскольку они не фигурируют в формуле). Соединение будет содержать по меньшей мере один атом углерода. Вы должны рассчитать и отобразить его степень ненасыщенности.

Например, сложный бензол (изображенный ниже) имеет DoU 4, поскольку он имеет три двойные связи (показаны двойной линией между атомами) и одно кольцо (число атомов, соединенных в петлю):

бензольное кольцо

Как определено LibreTexts :

DoU = (2C + 2 + N - X - H) / 2

Куда:

  • C это число атомов углерода
  • N это число атомов азота
  • X это число атомов галогена ( F, Cl, Br, I)
  • H это число атомов водорода

Тестовые случаи:

C6H6 --> 4
C9H2O1 --> 0
C9H9N1O4 --> 6
U1Pt1 --> Not a valid input, no carbon
Na2O1 --> Not a valid input, no carbon
C1H1 --> 1.5, although in practice this would be one, but is a part of a compound rather than a compound in entirety. 
N1H3 would return 0 - though in practice it isn't an organic compound (in other words it contains no carbon) so the formula wouldn't apply and it isn't a valid input

Для объяснения CH см. Здесь

По сути, вы должны определить, есть ли какие-либо из вышеперечисленных элементов (C, H, N, F, Cl, Br, I) в соединении, и если да, то сколько их. Затем вычислите степень ненасыщенности, используя приведенную выше формулу.

Только C, H, N, F, Cl, Br и I являются допустимыми значениями для формулы DoU. В целях этой загадки любые другие элементы могут быть полностью проигнорированы (например, если соединение было C6H6Mn, результат все равно будет 4). Если нет ни одного из вышеперечисленных соединений, ответ будет нулевым.

Можно предположить, что все вводимые соединения химически возможны, содержат по меньшей мере один атом углерода и, как известно, существуют. Если ввод неверен, программа может вывести либо 0, либо -1, либо не дать результата.

правила

Применяются стандартные правила ввода-вывода и лазейки . Ввод должен быть стандартной строкой, и вы можете предположить, что ввод не будет пустым. Это Codegolf - поэтому выигрывает самый короткий код в байтах.

Арчи Рокес
источник
Предлагаемые тестовые случаи: Оксид натрия: Na2Oи Метилидин: CHи CCl4He. Это некоторые угловые случаи, которые могут сломать несколько решений. Кстати, не то, чтобы это имело значение для кого-либо, кроме Mathematica (вероятно), но можем ли мы предположить, что соединения (могут) существовать?
Стьюи Гриффин
Я не понимаю C9H2O1 --> 0. Разве это не должно быть 9? (2*9+2+0-0-2)/2
DLosc
согласно последнему абзацу, вы имеете в виду, что код должен иметь возможность обрабатывать неверные данные? Кстати, гарантируется ли, что каждый элемент в соединении имеет завершающий «1», как в C1H1?
Кейу Ган
@KeyuGan да и да.
Арчи Рок

Ответы:

2

JavaScript (ES6), 117 112 байт

Возвращает 0для неверных входов.

s=>s.split(/(\d+)/).reduce((p,c,i,a)=>p+[0,k=a[i+1]/2,2*k,-k][n='NCFHIClBr'.search(c||0)+1,s|=n==2,n>2?3:n],1)*s

Контрольные примеры

Альтернативная версия, 103 байта

Если входные данные гарантированно действительны - как вводит в заблуждение введение в заблуждение - мы могли бы просто сделать:

s=>s.split(/(\d+)/).reduce((p,c,i,a)=>p+[0,k=a[i+1]/2,2*k,-k][n='NCFHIClBr'.search(c||0)+1,n>2?3:n],1)

демонстрация

Arnauld
источник
2

Python 3 , 142 151 148 байт

import re
l=dict(re.findall("(\D+)(\d+)",input()))
m=lambda k:int(l.get(k,0))
print(m("C")and m("C")+1+(m("N")-sum(map(m,"F I H Cl Br".split())))/2)

Возвращает 0 при ошибке.

Благодаря @HyperNeutrino, сбивающим байты.

Попробуйте онлайн!

MooseOnTheRocks
источник
упс - тестовые случаи обновлены!
Арчи Рок
@HyperNeutrino Тестовые случаи были немного неясны. Теперь не имеет вывода на неверный ввод.
MooseOnTheRocks
148 байт
HyperNeutrino
Хорошее использование dictтам!
DLosc
0

Пип , 70 67 байт

`C\d`Na&1+/2*VaR+XDs._R['C'NC`H|F|I|Cl|Br`].s["+2*"'+'-]RXU.XX"+0*"

Принимает химическую формулу в качестве аргумента командной строки. Выходы 0для неверных входов. Попробуйте онлайн!

объяснение

Использует ряд замен регулярных выражений, чтобы превратить химическую формулу в математическую формулу, выявляет ее и вносит пару изменений, чтобы получить окончательное значение.

Замены (слегка негольфированная версия):

aR+XDs._R"C ""+2*"R"N "'+R`(H|F|I|Cl|Br) `'-RXU.XX"+0*"

a                    Cmdline arg
 R+XD                 Replace runs of 1 or more digits (\d+)
     s._               with a callback function that prepends a space
                       (putting a space between each element and the following number)
 R"C "                Replace carbon symbol
      "+2*"            with +2* (add 2* the number of carbon atoms to the tally)
 R"N "                Replace nitrogen symbol
      '+               with + (add the number of nitrogen atoms to the tally)
 R`(H|F|I|Cl|Br) `    Replace hydrogen or halogen symbol
                  '-   with - (subtract the number of atoms from the tally)
 RXU.XX               Replace uppercase letter followed by another char ([A-Z].)
       "+0*"           with +0* (cancel out numbers of all other kinds of atoms)

Мы оцениваем полученную строку с V. Это дает нам 2C + N − X − H. Чтобы получить правильное значение, мы вносим следующие корректировки:

`C\d`Na&1+/2*V...

             V...  Value of expression calculated above
          /2*      multiplied by 1/2
        1+         plus 1
`C\d`Na            Is carbon in the original formula? (i.e. C followed by a digit)
       &           Logical AND: if no carbon, return 0, otherwise return the formula value
DLosc
источник
0

C (gcc) , 195197 202 байтов

Вероятно, самый длинный ответ.

d,c,b,e,n;f(char*a){for(c=d=0;b=*a;d+=e?e-1?b-66?b-67?0:e-2?0:-n:e-3?0:-n:b-67?b-78?b/70*73/b?-n:0:n:(c=2*n):0)e=*++a>57?*a-108?*a-114?0:3:2:1,a+=e>1,n=strtol(a,&a,10);printf("%.1f",c?d/2.+1:0);}

Попробуйте онлайн!

Возвращает 0 при ошибке.

Кейу Ган
источник