képletelemzés (kémia)
Sziasztok!
Kémiai (félkonstitúciós) képleteket szeretnék elemezni. A képlet alapján a php programommal szeretném megmondani, hogy melyik atomból mennyi van az adott molekulában. Elsősorban szerves anyagokat.
Pl.:
A metán a legegyszerűbb eset. [CH4: 1db C és 4 db H atom]
Még a hex-1-én is könnyű. [C6H12: 6 db C és 12 db H atom]
De az ecetsavnál már bonyolódik a helyzet. [CH3COOH: 2 db C, 4db H és 2db O atom]
Nem beszélve például a trimetil-amin-ról [(CH3)3N: 3 db C, 9 db H és 1 db N atom]
és a N-metil-formamid-ról. [CH3N(H)HCO: 2 db C, 5 db H, 1 db O és 1db N atom]
Ha még ez sem volna elég, akkor lehet még fűszerezni kationokkal. :-)
Pl.: A nátrium-palmitát (egyfajta szappan). [CH3(CH2)14COONa: 16 db C atom, 31 db H, 2 db O és 1 db Na (!)]
Szóval a rövid probléma felvázolás után a segítségeteket szeretném kérni. Már többféleképpen próbáltam megoldani a problémát, a nagy része már megvan, de még az egyszerű zárójeleket (az egymásba ágyazottakról nem beszélve) nem tudom kezelni.
Az első megközelítésben a szabványos kifejezésekhez fordultam, de mivel nem nagyon ismerem ezt a témát (most olvastam el az ide vonatkozó részeket), nem jutottam velük előrébb. Utána a képleten karakterenként mentem végig, de így borzasztó bonyolult lett, és megmaradt a fent említetett probléma. Biztos van egyszerűbb megoldás is, csak már nem látom az erdőtől a fát... (Fordítva jobb, de így kifejezőbb. :-) )
A forráskódhoz lásd az első hozzászólást. A print()-el megjelenített információk csak a tesztelést segítik.
A szabályok, amiket figyelembe kell venni. (Leegyszerűsítve, nem definíció szerint.):
1.) Minden atom nagybetűvel kezdődik, amit követhet a kisbetűs folytatása, ha több betűs. (pl.: C: szén, Na: nátrium) Összesen max. 2 betűs lehet.
2.) Az atom utáni alsó indexben lévő szám (itt nincs alsó indexelve), azt jelenti, hogy az adott atomból hány darab van. (C6H12: 6 db C és 12 db H atom)
3.) Ha egy szám a zárójel után szerepel, akkor a zárójelben lévő összes atom számát, ennyivel kell megszorozni. Ha nincs az atom után szám, akkor 1 van belőle. [(CH3)3N: 3 db C, 9 db H és 1 db N atom]
Kérem, aki tud, segítsen. Előre is köszönöm.
■ Kémiai (félkonstitúciós) képleteket szeretnék elemezni. A képlet alapján a php programommal szeretném megmondani, hogy melyik atomból mennyi van az adott molekulában. Elsősorban szerves anyagokat.
Pl.:
A metán a legegyszerűbb eset. [CH4: 1db C és 4 db H atom]
Még a hex-1-én is könnyű. [C6H12: 6 db C és 12 db H atom]
De az ecetsavnál már bonyolódik a helyzet. [CH3COOH: 2 db C, 4db H és 2db O atom]
Nem beszélve például a trimetil-amin-ról [(CH3)3N: 3 db C, 9 db H és 1 db N atom]
és a N-metil-formamid-ról. [CH3N(H)HCO: 2 db C, 5 db H, 1 db O és 1db N atom]
Ha még ez sem volna elég, akkor lehet még fűszerezni kationokkal. :-)
Pl.: A nátrium-palmitát (egyfajta szappan). [CH3(CH2)14COONa: 16 db C atom, 31 db H, 2 db O és 1 db Na (!)]
Szóval a rövid probléma felvázolás után a segítségeteket szeretném kérni. Már többféleképpen próbáltam megoldani a problémát, a nagy része már megvan, de még az egyszerű zárójeleket (az egymásba ágyazottakról nem beszélve) nem tudom kezelni.
Az első megközelítésben a szabványos kifejezésekhez fordultam, de mivel nem nagyon ismerem ezt a témát (most olvastam el az ide vonatkozó részeket), nem jutottam velük előrébb. Utána a képleten karakterenként mentem végig, de így borzasztó bonyolult lett, és megmaradt a fent említetett probléma. Biztos van egyszerűbb megoldás is, csak már nem látom az erdőtől a fát... (Fordítva jobb, de így kifejezőbb. :-) )
A forráskódhoz lásd az első hozzászólást. A print()-el megjelenített információk csak a tesztelést segítik.
A szabályok, amiket figyelembe kell venni. (Leegyszerűsítve, nem definíció szerint.):
1.) Minden atom nagybetűvel kezdődik, amit követhet a kisbetűs folytatása, ha több betűs. (pl.: C: szén, Na: nátrium) Összesen max. 2 betűs lehet.
2.) Az atom utáni alsó indexben lévő szám (itt nincs alsó indexelve), azt jelenti, hogy az adott atomból hány darab van. (C6H12: 6 db C és 12 db H atom)
3.) Ha egy szám a zárójel után szerepel, akkor a zárójelben lévő összes atom számát, ennyivel kell megszorozni. Ha nincs az atom után szám, akkor 1 van belőle. [(CH3)3N: 3 db C, 9 db H és 1 db N atom]
Kérem, aki tud, segítsen. Előre is köszönöm.
forráskód
Nekem sikerült :-)
Annyi bizgatta a fantáziámat a dolog, hogy egy jó fél óra alatt összedobtam. Végtére is vegyész (is) lennék, vagy mi a szösz :D Nekem működik, bár a nem a legszebb kód.
Az egyetlen igazán hasznos észrevételem: a zárójeles dolog kiértékelését érdemes rrekurzívan megoldani, így tetszőlegesen sok zárójellel is működik.
az én változatom
Ha már egy vegyésszel beszélek... , akkor ilyen alapon lehetne egy egyenletrendező programot is írni, így nem kell majd bajlódni az oxidációs számváltozásokkal... ;-)
Mit jelent a rekurzív módszer? Mitől lesz egy kiértékelés rekurzív?
Tehát a forráskódom:
Veremautomata
A zárójelezés egy eleve bonyolult dolog, ezért reguláris kifejezésekkel nem biztos, hogy sikerre jut az ember, habár lehet. Az én ötletem a veremautomaták és a reguláris kifejezések használata lenne. Algoritmus következő:
Van egy függvény, ami elkezdi olvasni a karaktereket, amolyan sorjában. Ha nyitó zárójelet talál, akkor rekurzívan meghívja önmagát átadva neki a jelenlegi olvasási pozíticót. Ha záró zárójelet talál, akkor kilép és visszaadja az eddigi eredmény stacket.
Miután lehet olyan is, hogy a zárójel értékét kell valahányszor venni, azt le kell ellenőrizni, hogy van-e szám utána. Ha igen, akkor azt megszorzod. Ami részek pedig a zárójelek között kvázi kijönnek, azokat reguláris kifejezéssel értelmezed.
Ez az algoritmus persze csak akkor jó, ha helyes a képlet, de elég könnyen meg lehet oldani, hogy mást is ellenőrizzen.