Grado de insaturación

11

Grado de insaturación

Este no es un rompecabezas de código particularmente difícil, pero estoy interesado en ver sus múltiples formas de resolverlo.

El grado de insaturación es el número de enlaces químicos dobles entre átomos y / o el número de anillos en un compuesto químico.

Se le dará la fórmula molecular de un compuesto químico en la forma XaYbZc (donde a, byc son el número de átomos de X, Y o Z en el compuesto); la fórmula podría tener cualquier longitud y contener cualquier elemento químico en la tabla periódica (aunque se pueden ignorar elementos que no sean C, H, N, F, Cl, Br, ya que no figuran en la fórmula). El compuesto contendrá al menos un átomo de carbono. Debe calcular y mostrar su grado de insaturación.

Por ejemplo, el benceno compuesto (que se muestra a continuación) tiene una DoU de 4, ya que tiene tres enlaces dobles (mostrados por una línea doble entre los átomos) y un solo anillo (varios átomos conectados en un bucle):

anillo de benceno

Según lo definido por LibreTexts :

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

Dónde:

  • C es la cantidad de átomos de carbono
  • N es la cantidad de átomos de nitrógeno
  • X es el número de átomos de halógeno ( F, Cl, Br, I)
  • H es la cantidad de átomos de hidrógeno

Casos de prueba:

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

Para una explicación de CH ver aquí

En esencia, debe identificar si hay alguno de los elementos anteriores (C, H, N, F, Cl, Br, I) en el compuesto y, de ser así, cuántos hay. Luego, calcule el grado de insaturación utilizando la fórmula anterior.

Solo C, H, N, F, Cl, Br e I son entradas válidas para la fórmula DoU. Para los propósitos de este rompecabezas, cualquier otro elemento puede ignorarse por completo (por ejemplo, si el compuesto fuera C6H6Mn, el resultado aún sería 4). Si no hay ninguno de los compuestos anteriores, la respuesta sería cero.

Puede suponer que todos los compuestos de entrada son químicamente posibles, contienen al menos un átomo de carbono y se sabe que existen. Si la entrada no es válida, el programa puede generar 0 o -1, o no producir ningún resultado.

Reglas

Se aplican las normas estándar de E / S y lagunas . La entrada debe ser una cadena estándar y puede suponer que la entrada no estará vacía. Esto es codegolf, por lo que gana el código más corto en bytes.

Archie Roques
fuente
Casos de prueba propuestos: Óxido de sodio: Na2Oy Metilidino: CHy CCl4He. Estos son algunos casos de esquina que pueden romper algunas soluciones. Por cierto, no es que importe a nadie más que a Mathematica (probablemente), pero ¿podemos suponer que los compuestos (pueden) existir?
Stewie Griffin
No entiendo C9H2O1 --> 0. ¿No debería ser 9? (2*9+2+0-0-2)/2
DLosc
Según el último párrafo, ¿quiere decir que el código debe ser capaz de manejar entradas no válidas? Por cierto, ¿se garantiza que cada elemento individual en el compuesto tenga un '1' final como en C1H1?
Keyu Gan
@KeyuGan sí y sí.
Archie Roques

Respuestas:

2

JavaScript (ES6), 117 112 bytes

Devoluciones 0para entradas inválidas.

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

Casos de prueba

Versión alternativa, 103 bytes.

Si se garantiza que la entrada sea válida, como sugiere la introducción del desafío, podríamos hacer lo siguiente:

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)

Manifestación

Arnauld
fuente
2

Python 3 , 142 151 148 bytes

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)

Devuelve 0 por error.

Gracias a @HyperNeutrino por bajar los bytes.

Pruébalo en línea!

MooseOnTheRocks
fuente
¡Vaya! ¡Casos de prueba actualizados!
Archie Roques
No funciona del todo
HyperNeutrino
@HyperNeutrino Los casos de prueba no estuvieron claros por un momento. Ahora no tiene salida en entrada inválida.
MooseOnTheRocks
148 bytes
HyperNeutrino
Buen uso de dictallí!
DLosc
0

Pip , 70 67 bytes

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

Toma la fórmula química como un argumento de línea de comandos. Salidas 0para entradas no válidas. Pruébalo en línea!

Explicación

Utiliza una serie de reemplazos de expresiones regulares para convertir la fórmula química en una fórmula matemática, evaluarla y hacer un par de ajustes para obtener el valor final.

Los reemplazos (versión ungolfed):

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)

Evaluamos la cadena resultante con V. Esto nos da 2C + N − X − H. Para obtener el valor correcto, hacemos los siguientes ajustes:

`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
fuente
0

C (gcc) , 195197 202 bytes

Probablemente la respuesta más larga.

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);}

Pruébalo en línea!

Devuelve 0 por error.

Keyu Gan
fuente