Stopień nienasycenia

11

Stopień nienasycenia

Nie jest to szczególnie trudna łamigłówka - ale interesuje mnie twoje wiele sposobów jej rozwiązania.

Stopień nienasycenia to liczba podwójnych wiązań chemicznych między atomami i / lub liczba pierścieni w związku chemicznym.

Otrzymasz wzór cząsteczkowy związku chemicznego w postaci XaYbZc (gdzie a, b i c to liczba atomów X, Y lub Z w związku) - wzór może mieć dowolną długość i zawierać dowolny pierwiastek chemiczny w układzie okresowym (chociaż elementy inne niż C, H, N, F, Cl, Br, I mogą zostać zignorowane, ponieważ nie występują we wzorze). Związek będzie zawierał co najmniej jeden atom węgla. Musisz obliczyć i wyświetlić stopień nienasycenia.

Na przykład związek benzenu (na zdjęciu poniżej) ma DoU równą 4, ponieważ ma trzy wiązania podwójne (pokazane podwójną linią między atomami) i pojedynczy pierścień (kilka atomów połączonych w pętli):

pierścień benzenowy

Zgodnie z definicją LibreTexts :

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

Gdzie:

  • C to liczba atomów węgla
  • N to liczba atomów azotu
  • X Jest to liczba atomów chlorowca ( F, Cl, Br, I)
  • H to liczba atomów wodoru

Przypadki testowe:

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

Wyjaśnienie CH patrz tutaj

Zasadniczo musisz określić, czy w związku występuje którykolwiek z powyższych pierwiastków (C, H, N, F, Cl, Br, I), a jeśli tak, to ile ich jest. Następnie obliczyć stopień nienasycenia, korzystając z powyższego wzoru.

Tylko C, H, N, F, Cl, Br i I są poprawnymi danymi wejściowymi dla formuły DoU. Na potrzeby tej układanki wszelkie inne elementy można całkowicie zignorować (np. Jeśli związek miałby postać C6H6Mn, wynik nadal wynosiłby 4). Jeśli nie ma żadnego z powyższych związków, odpowiedź wynosiłaby zero.

Możesz założyć, że wszystkie wprowadzone związki są chemicznie możliwe, zawierają co najmniej jeden atom węgla i wiadomo, że istnieją. Jeśli dane wejściowe są niepoprawne, program może wyprowadzić wartość 0 lub -1 lub nie wygenerować żadnego wyniku.

Zasady

Obowiązują standardowe zasady i luki we / wy . Dane wejściowe muszą być ciągiem standardowym i można założyć, że dane wejściowe nie będą puste. To jest codegolf - więc wygrywa najkrótszy kod w bajtach.

Archie Roques
źródło
Proponowane przypadki testowe: tlenek sodu: Na2Oi metyloidyna: CHi CCl4He. Oto niektóre narożne przypadki, które mogą złamać kilka rozwiązań. Nawiasem mówiąc, nie to, że ma to znaczenie dla kogokolwiek innego niż Mathematica (prawdopodobnie), ale czy możemy założyć, że związki (mogą) istnieć?
Stewie Griffin
Nie rozumiem C9H2O1 --> 0. Czy nie powinno być 9? (2*9+2+0-0-2)/2
DLosc
zgodnie z ostatnim akapitem, czy masz na myśli, że kod musi być w stanie poradzić sobie z nieprawidłowymi danymi wejściowymi? Nawiasem mówiąc, czy jest zagwarantowane, że każdy pojedynczy element w związku ma końcowe „1” jak w C1H1?
Keyu Gan
@KeyuGan tak i tak.
Archie Roques,

Odpowiedzi:

2

JavaScript (ES6), 117 112 bajtów

Zwraca 0za nieprawidłowe dane wejściowe.

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

Przypadki testowe

Alternatywna wersja, 103 bajty

Gdyby zagwarantowano, że dane wejściowe są prawidłowe - jak sugeruje wprowadzenie w błąd wprowadzające w błąd - moglibyśmy po prostu:

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)

Próbny

Arnauld
źródło
2

Python 3 , 142 151 148 bajtów

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)

Zwraca 0 w przypadku błędu.

Dzięki @HyperNeutrino zmniejszeniu bajtów.

Wypróbuj online!

MooseOnTheRocks
źródło
Ups - zaktualizowano przypadki testowe!
Archie Roques
Nie całkiem działa
HyperNeutrino
@HyperNeutrino Przypadki testowe były nieco niejasne. Teraz nie ma danych wyjściowych przy nieprawidłowych danych wejściowych.
MooseOnTheRocks
148 bajtów
HyperNeutrino
Niezłe wykorzystanie dict!
DLosc
0

Pip , 70 67 bajtów

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

Bierze wzór chemiczny jako argument wiersza polecenia. Dane wyjściowe 0dla nieprawidłowych danych wejściowych. Wypróbuj online!

Wyjaśnienie

Wykorzystuje serię zamienników wyrażeń regularnych, aby przekształcić wzór chemiczny w wzór matematyczny, sprawdzić go i dokonać kilku poprawek, aby uzyskać ostateczną wartość.

Zamienniki (wersja nieco nie golfowa):

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)

Analizujemy powstały ciąg za pomocą V. To nam daje 2C + N − X − H. Aby uzyskać prawidłową wartość, dokonujemy następujących korekt:

`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
źródło
0

C (gcc) , 195197 202 bajty

Prawdopodobnie najdłuższa odpowiedź.

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

Wypróbuj online!

Zwraca 0 w przypadku błędu.

Keyu Gan
źródło