Degré d'insaturation

11

Degré d'insaturation

Ce n'est pas un casse-tête de code particulièrement difficile - mais je suis intéressé de voir vos multiples façons de le résoudre.

Le degré d'insaturation est le nombre de doubles liaisons chimiques entre les atomes et / ou le nombre d'anneaux dans un composé chimique.

Vous recevrez la formule moléculaire d'un composé chimique sous la forme XaYbZc (où a, b et c sont le nombre d'atomes de X, Y ou Z dans le composé) - la formule peut être de n'importe quelle longueur et contenir n'importe quel élément chimique dans le tableau périodique (bien que des éléments autres que C, H, N, F, Cl, Br, I puissent être ignorés car ils ne figurent pas dans la formule). Le composé contiendra au moins un atome de carbone. Vous devez calculer et afficher son degré d'insaturation.

Par exemple, le composé benzène (illustré ci-dessous) a un DoU de 4 car il a trois doubles liaisons (représentées par une double ligne entre les atomes) et un seul cycle (un certain nombre d'atomes connectés en boucle):

anneau de benzène

Tel que défini par LibreTexts :

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

Où:

  • C est le nombre d'atomes de carbone
  • N est le nombre d'atomes d'azote
  • X est le nombre d'atomes d'halogène ( F, Cl, Br, I)
  • H est le nombre d'atomes d'hydrogène

Cas de test:

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

Pour une explication de CH voir ici

En substance, vous devez identifier s'il y a l'un des éléments ci-dessus (C, H, N, F, Cl, Br, I) dans le composé, et si oui, combien il y en a. Ensuite, calculez le degré d'insaturation à l'aide de la formule ci-dessus.

Seuls C, H, N, F, Cl, Br et I sont des entrées valides pour la formule DoU. Aux fins de ce casse-tête, tout autre élément peut être complètement ignoré (par exemple, si le composé était C6H6Mn, le résultat serait toujours 4). S'il n'y a aucun des composés ci-dessus, la réponse serait zéro.

Vous pouvez supposer que tous les composés entrés sont chimiquement possibles, contiennent au moins un atome de carbone et sont connus pour exister. Si l'entrée n'est pas valide, le programme peut sortir 0 ou -1 ou ne produire aucun résultat.

Règles

Les règles et les failles standard d'E / S s'appliquent. L'entrée doit être une chaîne standard et vous pouvez supposer que l'entrée ne sera pas vide. Ceci est codegolf - donc le code le plus court en octets l'emporte.

Archie Roques
la source
Cas d'essai proposés: Oxyde de sodium: Na2Oet méthylidyne: CHet CCl4He. Ce sont des cas d'angle qui peuvent casser quelques solutions. Soit dit en passant, ce n'est pas important pour quelqu'un d'autre que Mathematica (probablement), mais pouvons-nous supposer que les composés (peuvent) exister?
Stewie Griffin
Je ne comprends pas C9H2O1 --> 0. Ne devrait-il pas être 9? (2*9+2+0-0-2)/2
DLosc
selon le dernier paragraphe, voulez-vous dire que le code doit être capable de traiter les entrées invalides? Soit dit en passant, est-il garanti que chaque élément du composé a un «1» de fin comme dans C1H1?
Keyu Gan
@KeyuGan oui et oui.
Archie Roques

Réponses:

2

JavaScript (ES6), 117 112 octets

Renvoie 0les entrées non valides.

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

Cas de test

Version alternative, 103 octets

Si la contribution était garantie - comme le suggère l'introduction du défi de manière trompeuse - nous pourrions simplement faire:

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)

Démo

Arnauld
la source
2

Python 3 , 142 151 151 148 octets

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)

Renvoie 0 en cas d'erreur.

Merci à @HyperNeutrino de réduire les octets.

Essayez-le en ligne!

MooseOnTheRocks
la source
oups - cas de test mis à jour!
Archie Roques
@HyperNeutrino Les cas de test n'étaient pas clairs un peu. N'a maintenant aucune sortie sur une entrée invalide.
MooseOnTheRocks
148 octets
HyperNeutrino
Bon usage de dictlà - bas!
DLosc
0

Pip , 70 67 octets

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

Prend la formule chimique comme argument de ligne de commande. Sorties 0pour entrées invalides. Essayez-le en ligne!

Explication

Utilise une série de remplacements de regex pour transformer la formule chimique en une formule mathématique, l'évale et fait quelques ajustements pour obtenir la valeur finale.

Les remplacements (version légèrement non golfée):

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)

Nous évaluons la chaîne résultante avec V. Cela nous donne 2C + N − X − H. Pour obtenir la valeur correcte, nous effectuons les ajustements suivants:

`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
la source
0

C (gcc) , 195197 202 octets

Probablement la réponse la plus longue.

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

Essayez-le en ligne!

Renvoie 0 en cas d'erreur.

Keyu Gan
la source