Chemistry solver with molar mass calculator, moles/mass conversions, gas volume at STP, solution dilution (C1V1=C2V2), pH calculator, mass percentage, and element table.
# Chem Solver - NumWorks # Created by Alvar Laigna - https://alvarlaigna.com # Arrows:select OK:choose Back:back from kandinsky import fill_rect as F,draw_string as D from ion import keydown as K from time import sleep as Z from math import log SW,SH=320,222 BK=(0,)*3;WH=(255,)*3 BL=(50,110,230);TL=(0,190,190) YL=(220,200,60);DG=(120,)*3 okv=1 if K(4)or K(52) else 0 def okd(): return K(4)or K(52) def okp(): global okv d=okd() if d and not okv: okv=1 return True if not d:okv=0 return False def wup(): while okd():Z(0.02) Z(0.12) EL={"H":1.008,"He":4.003,"Li":6.941,"Be":9.012, "B":10.81,"C":12.011,"N":14.007,"O":15.999, "F":18.998,"Ne":20.18,"Na":22.99,"Mg":24.305, "Al":26.982,"Si":28.086,"P":30.974,"S":32.065, "Cl":35.453,"Ar":39.948,"K":39.098,"Ca":40.078, "Ti":47.867,"Cr":51.996,"Mn":54.938,"Fe":55.845, "Co":58.933,"Ni":58.693,"Cu":63.546,"Zn":65.38, "Br":79.904,"Ag":107.87,"Sn":118.71,"I":126.9, "Ba":137.33,"Au":196.97,"Hg":200.59,"Pb":207.2} def menu(title,items,sub=False): sel=0;n=len(items) while True: F(0,0,SW,SH,BK) D(title,SW//2-len(title)*5,6,TL,BK) F(0,24,SW,2,(40,)*3) for i in range(n): y=34+i*22 if i==sel: F(8,y,SW-16,20,BL) D("> "+items[i],14,y+2,WH,BL) else: D(" "+items[i],14,y+2,DG,BK) if sub:D("Back=return",100,SH-16,(60,)*3,BK) else:D("Back=quit",115,SH-16,(60,)*3,BK) while True: if K(1):sel=(sel-1)%n;Z(0.15);break if K(2):sel=(sel+1)%n;Z(0.15);break if okp():wup();return sel if K(17):return-1 Z(0.04) def inp(prompt): try:return float(input(prompt)) except:return None def inps(prompt): return input(prompt).strip() def show(lines): F(0,0,SW,SH,BK) D("RESULT",130,6,TL,BK) F(0,24,SW,2,(40,)*3) for i,ln in enumerate(lines): c=YL if i==len(lines)-1 else WH D(str(ln),14,34+i*20,c,BK) D("OK=back",130,SH-16,DG,BK) while True: if okp()or K(17):wup();return Z(0.04) def parse(fm): el={};i=0 while i<len(fm): if fm[i].isupper(): s=fm[i];i+=1 while i<len(fm) and fm[i].islower(): s+=fm[i];i+=1 n="" while i<len(fm) and fm[i].isdigit(): n+=fm[i];i+=1 n=int(n) if n else 1 el[s]=el.get(s,0)+n else:i+=1 return el def molar(fm): el=parse(fm);m=0 for s,n in el.items(): if s not in EL:return None,s m+=EL[s]*n return m,None def f_molar(): fm=inps("Formula (eg H2O): ") if fm: m,err=molar(fm) if err:show(["Unknown element: "+err]) elif m: el=parse(fm) r=["Formula: "+fm] for s,n in el.items(): r+=[s+": "+str(n)+"x"+str(EL[s])+"="+str(round(EL[s]*n,3))] r+=["M = "+str(round(m,4))+" g/mol"] show(r) def f_moles(): c=menu("Moles / Mass", ["n = m / M (find moles)", "m = n x M (find mass)", "M = m / n (find molar mass)"],True) if c==0: m=inp("Mass m (g): ");mm=inp("Molar mass M (g/mol): ") if m is not None and mm and mm!=0: show(["n = m / M", "m="+str(m)+"g M="+str(mm)+"g/mol", "n = "+str(round(m/mm,6))+" mol"]) elif c==1: n=inp("Moles n (mol): ");mm=inp("Molar mass M (g/mol): ") if n is not None and mm is not None: show(["m = n x M", "n="+str(n)+"mol M="+str(mm)+"g/mol", "m = "+str(round(n*mm,6))+" g"]) elif c==2: m=inp("Mass m (g): ");n=inp("Moles n (mol): ") if m is not None and n and n!=0: show(["M = m / n", "m="+str(m)+"g n="+str(n)+"mol", "M = "+str(round(m/n,4))+" g/mol"]) def f_gas(): c=menu("Gas at STP (22.4 L/mol)", ["V = n x Vm (find volume)", "n = V / Vm (find moles)", "From mass (enter M)"],True) if c==0: n=inp("Moles n (mol): ") if n is not None: show(["V = n x Vm (STP)", "n="+str(n)+" mol Vm=22.4 L/mol", "V = "+str(round(n*22.4,4))+" L"]) elif c==1: v=inp("Volume V (L): ") if v is not None: show(["n = V / Vm (STP)", "V="+str(v)+" L Vm=22.4 L/mol", "n = "+str(round(v/22.4,6))+" mol"]) elif c==2: m=inp("Mass m (g): ");mm=inp("Molar mass M (g/mol): ") if m is not None and mm and mm!=0: n=m/mm;v=n*22.4 show(["Gas from mass (STP)", "m="+str(m)+"g M="+str(mm)+"g/mol", "n = "+str(round(n,6))+" mol", "V = "+str(round(v,4))+" L"]) def f_dilute(): c=menu("Dilution C1V1=C2V2", ["Find C2 (final conc)", "Find V2 (final volume)", "Find C1 (initial conc)", "Find V1 (initial volume)"],True) if c==0: c1=inp("C1 (mol/L): ");v1=inp("V1 (L): ") v2=inp("V2 (L): ") if c1 is not None and v1 is not None and v2 and v2!=0: show(["C2 = C1*V1/V2", "C1="+str(c1)+" V1="+str(v1)+" V2="+str(v2), "C2 = "+str(round(c1*v1/v2,6))+" mol/L"]) elif c==1: c1=inp("C1 (mol/L): ");v1=inp("V1 (L): ") c2=inp("C2 (mol/L): ") if c1 is not None and v1 is not None and c2 and c2!=0: show(["V2 = C1*V1/C2", "C1="+str(c1)+" V1="+str(v1)+" C2="+str(c2), "V2 = "+str(round(c1*v1/c2,6))+" L"]) elif c==2: v1=inp("V1 (L): ");c2=inp("C2 (mol/L): ") v2=inp("V2 (L): ") if v1 and v1!=0 and c2 is not None and v2 is not None: show(["C1 = C2*V2/V1", "V1="+str(v1)+" C2="+str(c2)+" V2="+str(v2), "C1 = "+str(round(c2*v2/v1,6))+" mol/L"]) elif c==3: c1=inp("C1 (mol/L): ");c2=inp("C2 (mol/L): ") v2=inp("V2 (L): ") if c1 and c1!=0 and c2 is not None and v2 is not None: show(["V1 = C2*V2/C1", "C1="+str(c1)+" C2="+str(c2)+" V2="+str(v2), "V1 = "+str(round(c2*v2/c1,6))+" L"]) def f_ph(): c=menu("pH Calculator", ["pH from [H+]", "[H+] from pH", "pOH from pH", "pH from pOH"],True) if c==0: h=inp("[H+] (mol/L): ") if h and h>0: ph=-log(h)/log(10) show(["pH = -log10[H+]", "[H+] = "+str(h)+" mol/L", "pH = "+str(round(ph,4)), "pOH = "+str(round(14-ph,4))]) elif c==1: ph=inp("pH: ") if ph is not None: h=10**(-ph) show(["[H+] = 10^(-pH)", "pH = "+str(ph), "[H+] = "+str(h)+" mol/L", "pOH = "+str(round(14-ph,4))]) elif c==2: ph=inp("pH: ") if ph is not None: show(["pOH = 14 - pH", "pH = "+str(ph), "pOH = "+str(round(14-ph,4))]) elif c==3: poh=inp("pOH: ") if poh is not None: show(["pH = 14 - pOH", "pOH = "+str(poh), "pH = "+str(round(14-poh,4))]) def f_masspct(): c=menu("Mass Percentage", ["w% (find percentage)", "Find solute mass", "Find solution mass"],True) if c==0: ms=inp("Solute mass (g): ");mt=inp("Solution mass (g): ") if ms is not None and mt and mt!=0: show(["w% = m_solute/m_solution x100", "m_solute="+str(ms)+"g", "m_solution="+str(mt)+"g", "w = "+str(round(ms/mt*100,4))+" %"]) elif c==1: w=inp("Mass % (w%): ");mt=inp("Solution mass (g): ") if w is not None and mt is not None: show(["m_solute = w%/100 x m_solution", "w="+str(w)+"% m_sol="+str(mt)+"g", "m_solute = "+str(round(w/100*mt,4))+" g"]) elif c==2: ms=inp("Solute mass (g): ");w=inp("Mass % (w%): ") if ms is not None and w and w!=0: show(["m_solution = m_solute/(w%/100)", "m_solute="+str(ms)+"g w="+str(w)+"%", "m_solution = "+str(round(ms/(w/100),4))+" g"]) def f_elem(): keys=sorted(EL.keys()) sel=0;n=len(keys);vis=7 while True: F(0,0,SW,SH,BK) t="Elements ("+str(n)+")" D(t,SW//2-len(t)*5,6,TL,BK) F(0,24,SW,2,(40,)*3) top=max(0,min(sel-vis//2,n-vis)) for i in range(vis): idx=top+i if idx>=n:break y=34+i*22 s=keys[idx] txt=s+" - "+str(EL[s])+" g/mol" if idx==sel: F(8,y,SW-16,20,BL) D("> "+txt,14,y+2,WH,BL) else: D(" "+txt,14,y+2,DG,BK) D("Back=return",100,SH-16,(60,)*3,BK) while True: if K(1):sel=(sel-1)%n;Z(0.15);break if K(2):sel=(sel+1)%n;Z(0.15);break if K(17):return Z(0.04) CATS=["Molar Mass Calculator", "Moles / Mass / M", "Gas Volume (STP)", "Dilution (C1V1=C2V2)", "pH Calculator", "Mass Percentage", "Element Table"] FNS=[f_molar,f_moles,f_gas,f_dilute, f_ph,f_masspct,f_elem] def run(): while True: c=menu("Chem Solver",CATS) if c<0:return FNS[c]() run()