Javascript (ES7), 121 117 bytes
x=>(a=b=0,[for(c of x)for(d of'1234')(e=c.charCodeAt()/26|0)==d?a^=1<<d:b^=(a>>d&1)<<d*4+e],f=y=>y&&y%2+f(y>>1))(b)/2
Guau. Eso fue divertido. Esbocé una idea de respuesta cuando apareció este desafío por primera vez, pero tenía más de 150 bytes de longitud y no quería esforzarme por jugarlo. Me encontré con esta idea en mi cuaderno ayer y decidí que no dejaría de pensar en ello hasta que lo hubiera jugado por completo. Terminé escribiendo dos algoritmos completamente nuevos, el primero de los cuales terminó varios bytes más cortos después de jugar alrededor de 25 bytes con toneladas de pirateo de bits.
Cómo funciona
Primero establecemos variables a
y b
to 0
. a
es una matriz binaria de 4 bits de los pares de paréntesis en los que estamos actualmente, y b
es una matriz binaria de 16 bits cuyos pares de paréntesis están unidos entre sí.
A continuación, recorrer cada carácter c
en x
, y cada carbón d
en '0123'
. Primero determinamos con qué tipo de soporte c
está e=c.charCodeAt()/26-1|0
. Los códigos de caracteres decimales de cada tipo de paréntesis son los siguientes:
() => 40,41
<> => 60,62
[] => 91,93
{} => 123,125
Al dividir por 26, restar 1 y piso, los asignamos a 0, 1, 2 y 3, respectivamente.
Luego verificamos si este número es igual al valor actual de d
. Si es así, estamos entrando o saliendo del d
tipo de soporte th, por lo que cambiamos el d
bit th a
con a^=1<<d
. Si no lo es, sino que están dentro del d
tipo de soporte XX, tenemos que darle la vuelta al e
ésimo bit en la d
sección de 4 bits º de b
. Esto se hace así:
b^=(a>>d&1)<<d*4+e
(a>>d&1)
Devuelve el d
bit de entrada a
. Si estamos dentro del d
tipo de soporte, esto devuelve 1; de lo contrario, devuelve 0. A continuación, desplazamos esto a la izquierda por d*4+e
bits, y XOR b
por el resultado. Si estamos dentro del d
tipo de corchete, este XOR es el d*4+e
bit de b
; de lo contrario, no hace nada.
Al final de todo el bucle, b
contendrá un número de 1 bits igual al doble del valor de retorno deseado. Pero aún necesitamos averiguar cuántos bits es esto. Ahí es donde f
entra la subfunción :
f=y=>y&&y%2+f(y>>1)
Si y
es 0, esto simplemente devuelve 0. De lo contrario, toma el último bit de y
with y%2
, luego agrega el resultado de ejecutar todo excepto el último bit a y
través de la función nuevamente. Por ejemplo:
f(y) => y && y%2 + f(y>>1)
f(0b1001101) => 1 + f(0b100110) = 4
f(0b100110) => 0 + f(0b10011) = 3
f(0b10011) => 1 + f(0b1001) = 3
f(0b1001) => 1 + f(0b100) = 2
f(0b100) => 0 + f(0b10) = 1
f(0b10) => 0 + f(0b1) = 1
f(0b1) => 1 + f(0b0) = 1
f(0b0) => 0 = 0
Realizamos b
esta función y dividimos el resultado entre 2, y ahí está nuestra respuesta.