Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Al+Fe2O4->Fe+Al2O3
- 2Al+Fe2O3->2Fe+Al2O3
- 40Al+20Fe2O3->40Fe+20Al2O3
- Nope!
- Pb->Au
- C7H16+O2->CO2+H2O
- C7H16+11O2->7CO2+8H2O
- Al+Fe2O3->Fe+Al2O3
- 2Al+Fe2O3->2Fe+Al2O3
- Pb->Au
- Nope!
- // element use table, then once parsed reused as molecule weights
- u,t[99];
- // molecules
- char*s,*m[99]; // name and following separator
- c,v[99][99]; // count-1, element vector
- i,j,n;
- // brute force solver, n==0 upon solution - assume at most 30 of each molecule
- b(k){
- if(k<0)for(n=j=0;!n&&j<u;j++)for(i=0;i<=c;i++)n+=t[i]*v[i][j]; // check if sums to zero
- else for(t[k]=0;n&&t[k]++<30;)b(k-1); // loop through all combos of weights
- }
- main(int r,char**a){
- // parse
- for(s=m[0]=a[1];*s;){
- // parse separator, advance next molecule
- if(*s==45)r=0,s++;
- if(*s<65)m[++c]=++s;
- // parse element
- j=*s++;
- if(*s>96)j=*s+++j<<8;
- // lookup element index
- for(i=0,t[u]=j;t[i]-j;i++);
- u+=i==u;
- // parse amount
- for(n=0;*s>>4==3;)n=n*10+*s++-48;
- n+=!n;
- // store element count in molecule vector, flip sign for other side of '->'
- v[c][i]=r?n:-n;
- }
- // solve
- b(c);
- // output
- for(i=0,s=n?"Nope!":a[1];*s;putchar(*s++))s==m[i]&&t[i++]>1?printf("%d",t[i-1]):0;
- putchar(10);
- }
- ./a.out "C7H16+O2->CO2+H2O"
- ./a.out "Al+Fe2O4->Fe+Al2O3"
- ./a.out "Pb->Au"
- C7H16+11O2->7CO2+8H2O
- 8Al+3Fe2O4->6Fe+4Al2O3
- Nope!
- b@t_ :=Quiet@Check[Module[{s = StringSplit[t, "+" | "->"], g = StringCases, k = Length,
- e, v, f, z, r},
- e = Union@Flatten[g[#, _?UpperCaseQ ~~ ___?LowerCaseQ] & /@ s];v = k@e;
- s_~f~e_ := If[g[s, e] == {}, 0, If[(r = g[s, e ~~ p__?DigitQ :> p]) == {}, 1,
- r /. {{x_} :> ToExpression@x}]];z = k@s - v;
- r = #/(GCD @@ #) &[Inverse[Join[SparseArray[{{i_, j_} :> f[s[[j]], e[[i]]]}, k /@ {e, s}],
- Table[Join[ConstantArray[0, {z, v}][[i]], #[[i]]], {i, k[#]}]]][[All, -1]] &
- [IdentityMatrix@z]];
- Row@Flatten[ReplacePart[Riffle[Partition[Riffle[Abs@r, s], 2], " + "],
- 2 Count[r, _?Negative] -> " -> "]]], "Nope!"]
- b["C7H16+O2->CO2+H2O"]
- b["Al+Fe2O3->Fe+Al2O3"]
- b["Pb->Au"]
- import sys,re
- from sympy.solvers import solve
- from sympy import Symbol
- from fractions import gcd
- from collections import defaultdict
- Ls=list('abcdefghijklmnopqrstuvwxyz')
- eq=sys.argv[1]
- Ss,Os,Es,a,i=defaultdict(list),Ls[:],[],1,1
- for p in eq.split('->'):
- for k in p.split('+'):
- c = [Ls.pop(0), 1]
- for e,m in re.findall('([A-Z][a-z]?)([0-9]*)',k):
- m=1 if m=='' else int(m)
- a*=m
- d=[c[0],c[1]*m*i]
- Ss[e][:0],Es[:0]=[d],[[e,d]]
- i=-1
- Ys=dict((s,eval('Symbol("'+s+'")')) for s in Os if s not in Ls)
- Qs=[eval('+'.join('%d*%s'%(c[1],c[0]) for c in Ss[s]),{},Ys) for s in Ss]+[Ys['a']-a]
- k=solve(Qs,*Ys)
- if k:
- N=[k[Ys[s]] for s in sorted(Ys)]
- g=N[0]
- for a1, a2 in zip(N[0::2],N[1::2]):g=gcd(g,a2)
- N=[i/g for i in N]
- pM=lambda c: str(c) if c!=1 else ''
- print '->'.join('+'.join(pM(N.pop(0))+str(t) for t in p.split('+')) for p in eq.split('->'))
- else:print 'Nope!'
- python chem-min.py "C7H16+O2->CO2+H2O"
- python chem-min.py "Al+Fe2O4->Fe+Al2O3"
- python chem-min.py "Pb->Au"
- C7H16+11O2->7CO2+8H2O
- 8Al+3Fe2O4->6Fe+4Al2O3
- Nope!
- from sympy import*
- import sys,re
- from sympy.solvers import*
- from collections import*
- P=str.split
- L=map(chr,range(97,123))
- q=sys.argv[1]
- S,O,a,i,u,v=defaultdict(list),L[:],1,1,'+','->'
- w=u.join
- for p in P(q,v):
- for k in P(p,u):
- c=L.pop(0)
- for e,m in re.findall('([A-Z][a-z]*)(d*)',k):
- m=int(m or 1)
- a*=m
- S[e][:0]=[c,m*i],
- i=-1
- Y=dict((s,Symbol(s))for s in set(O)-set(L))
- Q=[eval(w('%d*%s'%(c[1],c[0])for c in S[s]),{},Y)for s in S]+[Y['a']-a]
- k=solve(Q,*Y)
- if k:
- N=[k[Y[s]]for s in sorted(Y)]
- g=gcd(N[:1]+N[1::2])
- print v.join(w((lambda c:str(c)*(c!=1))(N.pop(0)/g)+str(t)for t in P(p,u))for p in P(q,v))
- else:print'Nope!'
Add Comment
Please, Sign In to add comment