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
Uau. Foi divertido. Esbocei uma ideia de resposta quando esse desafio foi lançado, mas ele tinha mais de 150 bytes e não queria me esforçar para jogá-lo. Encontrei essa idéia no meu notebook ontem e decidi que não iria parar de pensar nela até que eu tivesse jogado o golfe completamente. Acabei escrevendo dois algoritmos inteiramente novos, o primeiro dos quais acabou vários bytes mais curto depois de jogar cerca de 25 bytes com toneladas de hackers de bits.
Como funciona
Primeiro, definimos variáveis ae bcomo 0. aé uma matriz binária de 4 bits cujos pares de colchetes estamos atualmente no interior e bé uma matriz binária de 16 bits cujos pares de colchetes estão vinculados.
Em seguida, vamos percorrer cada personagem cem x, e cada caractere dem '0123'. Primeiro, determinar que tipo de suporte cé com e=c.charCodeAt()/26-1|0. Os códigos de caracteres decimais de cada tipo de colchete são os seguintes:
() => 40,41
<> => 60,62
[] => 91,93
{} => 123,125
Dividindo por 26, subtraindo 1 e revestimento, nós os mapeamos para 0, 1, 2 e 3, respectivamente.
Em seguida, verificamos se esse número é igual ao valor atual de d. Se for, estamos entrando ou saindo do dtipo de parêntese, então trocamos o dth acom a^=1<<d. Se não é, mas nós estão dentro do dsuporte tipo th, precisamos virar o eth pouco na dseção de 4 bits th b. Isso é feito da seguinte maneira:
b^=(a>>d&1)<<d*4+e
(a>>d&1)Retorna o dth bit a. Se estivermos dentro do dtipo de colchete, isso retornará 1; caso contrário, ele retornará 0. Em seguida, mudamos isso para a esquerda por d*4+ebits e XOR bpelo resultado. Se estivermos dentro do dtipo de colchete, este XOR será o d*4+eth bit b; caso contrário, não faz nada.
No final de todo o loop, bconterá um número de 1 bits igual ao dobro do valor de retorno desejado. Mas ainda precisamos descobrir quantos bits são esses. É aí que fentra a sub-função :
f=y=>y&&y%2+f(y>>1)
Se yfor 0, isso simplesmente retorna 0. Caso contrário, ele leva o último bit de ycom y%2e adiciona o resultado da execução de todos, exceto o último bit, yatravés da função novamente. Por exemplo:
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
Executamos bessa função e dividimos o resultado por 2, e aqui está a nossa resposta.