Golf compuesto iónico

12

Desafío

Dadas dos entradas, un ion positivo y un ion negativo, debe generar la fórmula para el compuesto iónico que se formaría a partir de los dos iones. Esto básicamente significa equilibrar las cargas para que sean iguales a cero.

No se moleste en formatear la fórmula con números de subíndice, pero debe tener corchetes para los iones de átomos múltiples (como NO3).

No tiene que dar cuenta de ningún error (por ejemplo, si alguien ingresa dos iones negativos, puede dejar que el programa falle).

Nota: Tome Fe para tener un cargo de 3+

Iones

Todos los iones que deben tenerse en cuenta se encuentran junto con sus cargas en la segunda parte de la hoja de datos de química AQA GCSE .

Iones positivos

  • H +

  • Na +

  • Ag +

  • K +

  • Li +

  • NH 4 +

  • Ba 2+

  • Ca 2+

  • Cu 2+

  • Mg 2+

  • Zn 2+

  • Pb 2+

  • Fe 3+

  • Al 3+

Iones negativos

  • Cl -

  • Br -

  • F -

  • Yo -

  • OH -

  • NO 3 -

  • O 2-

  • S 2-

  • SO 4 2-

  • CO 3 2-

Ejemplos

Algunos ejemplos:

H y O regresa: -H2O

Retornos de Ca y CO 3 : -CaCO3

Al y SO 4 regresa: -Al2(SO4)3

Tenga en cuenta el siguiente caso que debe tener en cuenta:

H y OH devuelve: - H2O no H(OH)

Decaimiento Beta
fuente
¿El ión positivo siempre aparece primero?
xnor
¿ FeTiene un cargo de 2+ o 3+?
Pomo de la puerta
@xnor No, pueden cambiar
Beta Decay
Esto me recuerda a mi clase de química que tuve hace un año. Balanceando cosas ...
Spikatrix
Supongo que los corchetes deben usarse cuando sea necesario y solo cuando sea necesario. ¿Correcto?
Level River St

Respuestas:

0

CJam, 176 bytes

"O S SO4 CO3 ""Cl Br F I OH NO3 """"H Na Ag K Li NH4 ""Ba Ca Cu Mg Zn Pb ""Fe Al "]_2{r\1$S+f#Wf=0#((z@}*_2$*_4=2*-_@/\@/@\]2/{~_({1$1>_el={'(@@')\}|0}&;}/]s"HOHH"1$#){;"H2O"}&

Pruébalo en línea

Esto fue algo doloroso, particularmente con todos los casos especiales para paréntesis, mostrando conteos, el H2O, etc.

Los datos no están en un formato súper compacto. Podría recortarse más, pero el código necesario para interpretarlo probablemente compensaría los ahorros. Así que fui con una serie de cadenas, donde cada cadena contiene los átomos con la misma carga, ordenada de -2 a +3 (donde la cadena para 0 está vacía).

Explicación:

[..]  Data, as explained above.
_     Duplicate data, will need it for both inputs.
2{    Loop over two inputs.
  r     Get input.
  \     Swap data to top.
  1$    Copy input to top (keep original for later).
  S+    Add a space to avoid ambiguity when searching in data.
  f#    Search for name in all strings of data.
  Wf=   Convert search results to truth values by comparing them to -1.
  0#    Find the 0 entry, which gives the index of the matching string.
  ((    Subtract 2, to get charge in range [-2, 3] from index.
  z     Absolute value, we don't really care about sign of charge.
  @     Swap second copy of data table to proper position for next input.
}*    End loop over two inputs.
_2$*  Multiply the two charges.
_4=   We need the LCM. But for the values here, only product 4 is not the LCM.
2*-   So change it to 2.
_@/   Divide LCM by first charge to get first count.
\@/   Divide LCM by second charge to get second count.
@\]2/ Make pairs of name/count for both ions...
{     ... and loop over the pairs.
  ~     Unpack the pair.
  _(    Check if count is > 1.
  {       Handle count > 1.
    1$    Get copy of name to top of stack.
    1>    Slice off first character to check if rest contains upper case.
    _el   Create lower case copy.
    =     If they are different, there are upper case letters.
    {       Handle case where parentheses are needed.
      '(    Opening parentheses.
      @@    Some stack shuffling to get values in place.
      ')    Closing parentheses.
      \     And one more swap to place count after parentheses.
    }|    End parentheses handling.
    0     Push dummy value to match stack layout of other branch.
  }&    End count handling.
  ;     Pop unused count off stack.
}/    End loop over name/count pairs.
]s    Pack stack content into single string, for H2O handling.
"HOHH"  String that contains both HOH and OHH, which need to be H2O.
1$#)  Check if output is in that string.
{     If yes, replace with H2O.
  ;     Drop old value.
  "H2O" And make it H2O instead.
}&    End of H2O handling.
Reto Koradi
fuente
2

Lua , 174 242 bytes

Olvidé los corchetes '-_-, eso me llevó hasta 242. Oh, bueno, al menos fue un desafío bastante divertido.

i,c,a={Ba=2,Ca=2,Cu=2,Mg=2,Zn=2,Pb=2,Fe=3,Al=3,O=2,S=2,SO4=2,CO3=2},io.read(),io.read()
p,d=i[c]~=i[a],{SO4=1,NO3=1,OH=1,CO3=1}
k,m=p and i[c]or'',p and i[a]or''
a=k==m and a or (d[a]and'('..a..')'or a)
print(c..a=='HOH'and'H2O'or c..m..a..k)

Pruébalo en línea!

Versión antigua:

i,c,a={Ba=2,Ca=2,Cu=2,Mg=2,Zn=2,Pb=2,Fe=3,Al=3,O=2,S=2,SO4=2,CO3=2},io.read(),io.read()
p=i[c]~=i[a]
k,m=p and i[c]or'',p and i[a]or''
print(c..a=='HOH'and'H2O'or c..m..a..k)

Abusando de la tendencia de Lua de inicializar todo con un valor nulo, podemos reducir los costos de almacenamiento. Aún así, Lua todavía es un poco torpe :(

El sargento Escondido
fuente
Su salida debe soportar paréntesis. Entonces, Aly SO4debería salir Al2(SO4)3, pero usted sale Al2SO43. Pruébelo en línea
mbomb007
Sí, solo me di cuenta de que unos 5 minutos después de presionar enviar. '-_-. Debería funcionar ahora.
sargento.
Ahora genera parens cuando no es necesario. Pruebe Cay CO3. Además, debe agregar el enlace TIO a su respuesta.
mbomb007
¡Allí! Lo siento, no sabía lo de TIO. Culpa mía.
sargento.
2
Es útil para los usuarios que desean ejecutar su código.
mbomb007
1

Java ( 619 647 667 bytes)

[Solucionado] Actualización: H + OH devuelve HOH aunque lo codifiqué para no ... trabajar en él

[Solucionado] Actualización: a veces aparecen paréntesis cuando no deberían

Código

String f(String[]a){if(Arrays.equals(a,new String[]{"H","OH"})|Arrays.equals(a,new String[]{"OH","H"}))return "H2O";List<String>b=Arrays.asList(new String[]{"H","Na","Ag","K","Li","NH4","Ba","Ca","Cu","Mg","Zn","Pb","Fe","Al","Cl","Br","F","I","OH","NO3","O","S","SO4","CO3"});Integer[]c={1,1,1,1,1,1,2,2,2,2,2,2,3,3,1,1,1,1,1,1,2,2,2,2},d={5,18,19,22,23};List<Integer>j=Arrays.asList(d);int e=b.indexOf(a[0]),f=b.indexOf(a[1]),g=c[e],h=c[f],i;if(f<e){String p=a[0];a[0]=a[1];a[1]=p;i=g;g=h;h=i;i=e;e=f;f=i;}boolean k=j.contains(e),l=j.contains(f),m=g==h,n=g==1,o=h==1;return (k&!m&!o?"("+a[0]+")":a[0])+(m?"":h==1?"":h)+(l&!m&!n?"("+a[1]+")":a[1])+(m?"":g==1?"":g);}

No estaba seguro de cómo hacer esto sin codificar duro cada carga de iones, por lo que terminó siendo largo. Por suerte, todas las cargas son 1, 2 o 3, por lo que es fácil encontrar la cantidad de cada ion.

Expandido

import java.util.Arrays;
import java.util.List;
public class Compound {
    public static void main(String[]a){
        //System.out.println(f(a));
        String[] pos = new String[]{"H","Na","Ag","K","Li","NH4","Ba","Ca","Cu","Mg","Zn","Pb","Fe","Al"};
        String[] neg = new String[]{"Cl","Br","F","I","OH","NO3","O","S","SO4","CO3"};
        for(int i = 0; i < pos.length; i++){
            for(int j = 0; j < neg.length; j++){
                System.out.println(pos[i] + " + " + neg[j] + " = " + f(new String[]{pos[i],neg[j]}));
                System.out.println(neg[j] + " + " + pos[i] + " = " + f(new String[]{neg[j],pos[i]}));
            }
        }
    }
    static String f(String[]a){
        if(Arrays.equals(a,new String[]{"H","OH"})|Arrays.equals(a,new String[]{"OH","H"}))
            return "H2O";
        List<String>b=Arrays.asList(new String[]{"H","Na","Ag","K","Li","NH4","Ba","Ca","Cu","Mg","Zn","Pb","Fe","Al","Cl","Br","F","I","OH","NO3","O","S","SO4","CO3"});
        Integer[]c={1,1,1,1,1,1,2,2,2,2,2,2,3,3,1,1,1,1,1,1,2,2,2,2},d={5,18,19,22,23};
        List<Integer>j=Arrays.asList(d);
        int e=b.indexOf(a[0]),f=b.indexOf(a[1]),g=c[e],h=c[f],i;
        if(f<e){String p=a[0];a[0]=a[1];a[1]=p;i=g;g=h;h=i;i=e;e=f;f=i;}
        boolean k=j.contains(e),l=j.contains(f),m=g==h,n=g==1,o=h==1;
        return (k&!m&!o?"("+a[0]+")":a[0])+(m?"":o?"":h)+(l&!m&!n?"("+a[1]+")":a[1])+(m?"":n?"":g);
    }
}

Pruébalo aquí

Datos

Avísame si alguno de ellos está equivocado

H + Cl = HCl
Cl + H = HCl
H + Br = HBr
Br + H = HBr
H + F = HF
F + H = HF
H + I = HI
I + H = HI
H + OH = H2O
OH + H = H2O
H + NO3 = HNO3
NO3 + H = HNO3
H + O = H2O
O + H = H2O
H + S = H2S
S + H = H2S
H + SO4 = H2SO4
SO4 + H = H2SO4
H + CO3 = H2CO3
CO3 + H = H2CO3
Na + Cl = NaCl
Cl + Na = NaCl
Na + Br = NaBr
Br + Na = NaBr
Na + F = NaF
F + Na = NaF
Na + I = NaI
I + Na = NaI
Na + OH = NaOH
OH + Na = NaOH
Na + NO3 = NaNO3
NO3 + Na = NaNO3
Na + O = Na2O
O + Na = Na2O
Na + S = Na2S
S + Na = Na2S
Na + SO4 = Na2SO4
SO4 + Na = Na2SO4
Na + CO3 = Na2CO3
CO3 + Na = Na2CO3
Ag + Cl = AgCl
Cl + Ag = AgCl
Ag + Br = AgBr
Br + Ag = AgBr
Ag + F = AgF
F + Ag = AgF
Ag + I = AgI
I + Ag = AgI
Ag + OH = AgOH
OH + Ag = AgOH
Ag + NO3 = AgNO3
NO3 + Ag = AgNO3
Ag + O = Ag2O
O + Ag = Ag2O
Ag + S = Ag2S
S + Ag = Ag2S
Ag + SO4 = Ag2SO4
SO4 + Ag = Ag2SO4
Ag + CO3 = Ag2CO3
CO3 + Ag = Ag2CO3
K + Cl = KCl
Cl + K = KCl
K + Br = KBr
Br + K = KBr
K + F = KF
F + K = KF
K + I = KI
I + K = KI
K + OH = KOH
OH + K = KOH
K + NO3 = KNO3
NO3 + K = KNO3
K + O = K2O
O + K = K2O
K + S = K2S
S + K = K2S
K + SO4 = K2SO4
SO4 + K = K2SO4
K + CO3 = K2CO3
CO3 + K = K2CO3
Li + Cl = LiCl
Cl + Li = LiCl
Li + Br = LiBr
Br + Li = LiBr
Li + F = LiF
F + Li = LiF
Li + I = LiI
I + Li = LiI
Li + OH = LiOH
OH + Li = LiOH
Li + NO3 = LiNO3
NO3 + Li = LiNO3
Li + O = Li2O
O + Li = Li2O
Li + S = Li2S
S + Li = Li2S
Li + SO4 = Li2SO4
SO4 + Li = Li2SO4
Li + CO3 = Li2CO3
CO3 + Li = Li2CO3
NH4 + Cl = NH4Cl
Cl + NH4 = NH4Cl
NH4 + Br = NH4Br
Br + NH4 = NH4Br
NH4 + F = NH4F
F + NH4 = NH4F
NH4 + I = NH4I
I + NH4 = NH4I
NH4 + OH = NH4OH
OH + NH4 = NH4OH
NH4 + NO3 = NH4NO3
NO3 + NH4 = NH4NO3
NH4 + O = (NH4)2O
O + NH4 = (NH4)2O
NH4 + S = (NH4)2S
S + NH4 = (NH4)2S
NH4 + SO4 = (NH4)2SO4
SO4 + NH4 = (NH4)2SO4
NH4 + CO3 = (NH4)2CO3
CO3 + NH4 = (NH4)2CO3
Ba + Cl = BaCl2
Cl + Ba = BaCl2
Ba + Br = BaBr2
Br + Ba = BaBr2
Ba + F = BaF2
F + Ba = BaF2
Ba + I = BaI2
I + Ba = BaI2
Ba + OH = Ba(OH)2
OH + Ba = Ba(OH)2
Ba + NO3 = Ba(NO3)2
NO3 + Ba = Ba(NO3)2
Ba + O = BaO
O + Ba = BaO
Ba + S = BaS
S + Ba = BaS
Ba + SO4 = BaSO4
SO4 + Ba = BaSO4
Ba + CO3 = BaCO3
CO3 + Ba = BaCO3
Ca + Cl = CaCl2
Cl + Ca = CaCl2
Ca + Br = CaBr2
Br + Ca = CaBr2
Ca + F = CaF2
F + Ca = CaF2
Ca + I = CaI2
I + Ca = CaI2
Ca + OH = Ca(OH)2
OH + Ca = Ca(OH)2
Ca + NO3 = Ca(NO3)2
NO3 + Ca = Ca(NO3)2
Ca + O = CaO
O + Ca = CaO
Ca + S = CaS
S + Ca = CaS
Ca + SO4 = CaSO4
SO4 + Ca = CaSO4
Ca + CO3 = CaCO3
CO3 + Ca = CaCO3
Cu + Cl = CuCl2
Cl + Cu = CuCl2
Cu + Br = CuBr2
Br + Cu = CuBr2
Cu + F = CuF2
F + Cu = CuF2
Cu + I = CuI2
I + Cu = CuI2
Cu + OH = Cu(OH)2
OH + Cu = Cu(OH)2
Cu + NO3 = Cu(NO3)2
NO3 + Cu = Cu(NO3)2
Cu + O = CuO
O + Cu = CuO
Cu + S = CuS
S + Cu = CuS
Cu + SO4 = CuSO4
SO4 + Cu = CuSO4
Cu + CO3 = CuCO3
CO3 + Cu = CuCO3
Mg + Cl = MgCl2
Cl + Mg = MgCl2
Mg + Br = MgBr2
Br + Mg = MgBr2
Mg + F = MgF2
F + Mg = MgF2
Mg + I = MgI2
I + Mg = MgI2
Mg + OH = Mg(OH)2
OH + Mg = Mg(OH)2
Mg + NO3 = Mg(NO3)2
NO3 + Mg = Mg(NO3)2
Mg + O = MgO
O + Mg = MgO
Mg + S = MgS
S + Mg = MgS
Mg + SO4 = MgSO4
SO4 + Mg = MgSO4
Mg + CO3 = MgCO3
CO3 + Mg = MgCO3
Zn + Cl = ZnCl2
Cl + Zn = ZnCl2
Zn + Br = ZnBr2
Br + Zn = ZnBr2
Zn + F = ZnF2
F + Zn = ZnF2
Zn + I = ZnI2
I + Zn = ZnI2
Zn + OH = Zn(OH)2
OH + Zn = Zn(OH)2
Zn + NO3 = Zn(NO3)2
NO3 + Zn = Zn(NO3)2
Zn + O = ZnO
O + Zn = ZnO
Zn + S = ZnS
S + Zn = ZnS
Zn + SO4 = ZnSO4
SO4 + Zn = ZnSO4
Zn + CO3 = ZnCO3
CO3 + Zn = ZnCO3
Pb + Cl = PbCl2
Cl + Pb = PbCl2
Pb + Br = PbBr2
Br + Pb = PbBr2
Pb + F = PbF2
F + Pb = PbF2
Pb + I = PbI2
I + Pb = PbI2
Pb + OH = Pb(OH)2
OH + Pb = Pb(OH)2
Pb + NO3 = Pb(NO3)2
NO3 + Pb = Pb(NO3)2
Pb + O = PbO
O + Pb = PbO
Pb + S = PbS
S + Pb = PbS
Pb + SO4 = PbSO4
SO4 + Pb = PbSO4
Pb + CO3 = PbCO3
CO3 + Pb = PbCO3
Fe + Cl = FeCl3
Cl + Fe = FeCl3
Fe + Br = FeBr3
Br + Fe = FeBr3
Fe + F = FeF3
F + Fe = FeF3
Fe + I = FeI3
I + Fe = FeI3
Fe + OH = Fe(OH)3
OH + Fe = Fe(OH)3
Fe + NO3 = Fe(NO3)3
NO3 + Fe = Fe(NO3)3
Fe + O = Fe2O3
O + Fe = Fe2O3
Fe + S = Fe2S3
S + Fe = Fe2S3
Fe + SO4 = Fe2(SO4)3
SO4 + Fe = Fe2(SO4)3
Fe + CO3 = Fe2(CO3)3
CO3 + Fe = Fe2(CO3)3
Al + Cl = AlCl3
Cl + Al = AlCl3
Al + Br = AlBr3
Br + Al = AlBr3
Al + F = AlF3
F + Al = AlF3
Al + I = AlI3
I + Al = AlI3
Al + OH = Al(OH)3
OH + Al = Al(OH)3
Al + NO3 = Al(NO3)3
NO3 + Al = Al(NO3)3
Al + O = Al2O3
O + Al = Al2O3
Al + S = Al2S3
S + Al = Al2S3
Al + SO4 = Al2(SO4)3
SO4 + Al = Al2(SO4)3
Al + CO3 = Al2(CO3)3
CO3 + Al = Al2(CO3)3

Nota

Comencé en Pyth, pero luego me molesté con el orden y el paréntesis, esto es lo que tenía si alguien quiere terminarlo.

=G["H" "Na" "Ag" "K" "Li" "NH4" "Ba" "Ca" "Cu" "Mg" "Zn" "Pb" "Fe" "Al" "Cl" "Br" "F" "I" "OH" "NO3" "O" "S" "SO4" "CO3" 1 1 1 1 1 1 2 2 2 2 2 2 3 3 1 1 1 1 1 1 2 2 2 2)J@G+24xG@QZK@G+24xG@Q1@QZ?kqJKK@Q1?kqJKJ
cmxu
fuente
¿Cuál fue el problema con Hy OH?
Beta Decay
Está arreglado, antes de que regresara H + OH = HOH no H2O
cmxu
Quiero decir, ¿qué fue lo que lo hizo devolver HOH en lugar de H20?
Beta Decay
Parece que hay algunos paréntesis innecesarios, al menos la forma en que leo las reglas. Por ejemplo, en H + SO4, creo que el resultado debería ser H2SO4, sin paréntesis.
Reto Koradi
@RetoKoradi Me di cuenta justo antes de leer su comentario, pero ahora se ha solucionado. Gracias.
cmxu
0

JavaScript (ES6), 316 277 bytes

He globalizado las variables py n(al igual que lo hice en CoffeeScript) para facilitar las pruebas. La localización de las variables no haría una diferencia en el recuento de caracteres.

f=(x,y)=>{i='indexOf',d='~NH4KNaAgLiBa~CaCuMgZnPbFeAlSO4CO3ClBrFIOHNO3',k=d[i](x),l=d[i](y),a=k<28?x:y,b=k<28?y:x,r=Math.ceil(k/11)-1,s=b=='F'?0:l<32;if(r==s)r=s=0;a=s&&a=='NH4'?'(NH4)':a;b=r&&/[A-Z]{2}/.test(b)?`(${b})`:b;return'H'==a&&b=='OH'?'H2O':a+(s?s+1:'')+b+(r?r+1:'')}


// Original attempt, 316 bytes
p={H:1,Na:1,Ag:1,K:1,Li:1,NH4:1,Ba:2,Ca:2,Cu:2,Mg:2,Zn:2,Pb:2,Fe:3,Al:3},n={Cl:1,Br:1,F:1,I:1,OH:1,NO3:1,O:2,S:2,SO4:2,CO3:2},f=(x,y)=>{a=p[x]?x:y,b=p[x]?y:x,z=p[a]==2&&n[b]==2,r=+z||n[b],s=+z||p[a];a=--r&&a=='NH4'?'(NH4)':a;b=--s&&/[A-Z]{2}/.test(b)?`(${b})`:b;return'H'==a&&b=='OH'?'H2O':a+(r?r+1:'')+b+(s?s+1:'')}

Variante ES5, 323 284 bytes

No hay muchos cambios aparte de deshacerse de la función de flecha y la cadena de plantilla:

f=function(x,y){i='indexOf',d='~NH4KNaAgLiBa~CaCuMgZnPbFeAlSO4CO3ClBrFIOHNO3',k=d[i](x),l=d[i](y),a=k<28?x:y,b=k<28?y:x,r=Math.ceil(k/11)-1,s=b=='F'?0:l<32;if(r==s)r=s=0;a=s&&a=='NH4'?'(NH4)':a;b=r&&/[A-Z]{2}/.test(b)?'('+b+')':b;return'H'==a&&b=='OH'?'H2O':a+(s?s+1:'')+b+(r?r+1:'')}


// Original attempt, 323 bytes
p={H:1,Na:1,Ag:1,K:1,Li:1,NH4:1,Ba:2,Ca:2,Cu:2,Mg:2,Zn:2,Pb:2,Fe:3,Al:3},n={Cl:1,Br:1,F:1,I:1,OH:1,NO3:1,O:2,S:2,SO4:2,CO3:2},f=function(x,y){a=p[x]?x:y,b=p[x]?y:x,z=p[a]==2&&n[b]==2,r=+z||n[b],s=+z||p[a];a=--r&&a=='NH4'?'(NH4)':a;b=--s&&/[A-Z]{2}/.test(b)?'('+b+')':b;return'H'==a&&b=='OH'?'H2O':a+(r?r+1:'')+b+(s?s+1:'')}

rink.attendant.6
fuente
0

CoffeeScript, 371 333 bytes

Este recuento incluye líneas nuevas (algunas líneas nuevas se pueden reemplazar con punto y coma, pero eso no afectaría el recuento de caracteres)

f=(x,y)->(i='indexOf';d='~NH4KNaAgLiBa~CaCuMgZnPbFeAlSO4CO3ClBrFIOHNO3';k=d[i] x;r=-1+Math.ceil k/11;l=d[i] y;a=if k<28then x else y
b=if k<28then y else x
s=if b=='F'then 0else 32>l
r=s=0if r==s;a='(NH4)'if'NH4'==a&&s;b='('+b+')'if/[A-Z]{2}/.test(b)&&r;if'H'==a&&b=='OH'then'H2O'else a+(if!s then''else 1+s)+b+(if!r then''else 1+r))

# Original attempt, 371 bytes
p={H:1,Na:1,Ag:1,K:1,Li:1,NH4:1,Ba:2,Ca:2,Cu:2,Mg:2,Zn:2,Pb:2,Fe:3,Al:3}
n={Cl:1,Br:1,F:1,I:1,OH:1,NO3:1,O:2,S:2,SO4:2,CO3:2}
f=(x,y)->(a=if p[x]then x else y
b=if p[x]then y else x
z=p[a]==n[b]==2;r=+z||n[b];s=+z||p[a];if--r&&a=='NH4'then a='(NH4)'
if--s&&/[A-Z]{2}/.test(b)then b='('+b+')'
if'H'==a&&b=='OH'then'H2O'else a+(if!r then''else r+1)+b+(if!s then''else s+1))
rink.attendant.6
fuente
0

CJam (137 bytes)

{{"SO4CO3ClBrFINO3OHNaAgKLiNH4BaCaCuMgZnPbFeAl":I\#~}$_s"HOH"="HO"1/@?_{I\#G-_0<B*-B/_W>+z}%_~1$=\1?f/W%[.{:T1>{_{'a<},,1>{'(\')}*T}*}]s}

Este es un bloque anónimo (función) que toma dos iones como cadenas envueltas en una lista y devuelve una cadena.

Demo en línea .

Disección

{                        e# Begin a block
  {                      e#   Sort the input list
    "SO4...Al"           e#     Ions in ascending order of charge
    :I                   e#     Stored as I for future reuse
    \#~                  e#     Index and bit-invert to sort descending
  }$

  _s"HOH"="HO"1/@?       e#   Special case for water: replace ["H" "OH"] with ["H" "O"]

  _{I\#G-_0<B*-B/_W>+z}% e#   Copy the list and hash index in I to find the charges
  _~1$=\1?f/             e#   Replace [2 2] by [1 1]
  W%                     e#   Reverse the charges
  [                      e#   Gather in an array
    .{                   e#   Pairwise for each ion and its opponent's reduced charge...
      :T1>{              e#     If the charge (copied to T) is greater than 1
        _{'a<},,         e#       Count the characters in the ion which are before 'a'
        1>{'(\')}*       e#       If there's more than one, add some parentheses
        T                e#       Append T
      }*
    }
  ]
  s                      e#   Flatten the list to a single string
}
Peter Taylor
fuente
0

Python 3 , 364 bytes

Almacena los iones por el valor absoluto de sus cargas como index+1en una matriz 2-D (los elementos de índice 0 tienen + - 1 carga, etc.). Utiliza string.split () para guardar algunos caracteres allí. Maneja el caso especial de H + OH = H2Oprimero, luego calcula cuántos iones se necesitan de cada tipo como el LCM de sus dos cargas dividido por su carga. Luego agrega paréntesis si es necesario, así como el número real de iones.

from math import*
o=["NH4 NO3 H Na Ag K Li OH I F Br Cl".split(),"CO3 SO4 Ba Ca Cu Mg Zn Pb S O".split(),["Fe","Al"]]
p=["H","OH"]
def c(i):
 for h,k in enumerate(o):
  if i in k:return-~h
def b(x,y):
 if x in p and y in p:return"H20"
 i,j=c(x),c(y);g=gcd(i,j);i//=g;j//=g;return((x,"(%s)"%x)[x[-1]in"34"]+str(j),x)[j==1]+((y,"(%s)"%y)[y[-1]in"34"]+str(i),y)[i==1]

Pruébalo en línea!

Neil A.
fuente