JavaScript (ES7), 121 117 byte
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
Wow. È stato divertente. Ho delineato un'idea di risposta quando è stata lanciata questa sfida, ma era lunga più di 150 byte e non volevo sforzarmi di giocarci a golf. Ieri ho incontrato questa idea sul mio taccuino e ho deciso che non avrei smesso di pensarci fino a quando non avessi completamente giocato a golf. Ho finito per scrivere due algoritmi completamente nuovi, il primo dei quali è risultato più corto di alcuni byte dopo aver golfato di circa 25 byte con tonnellate di bit-hacking.
Come funziona
Innanzitutto impostiamo le variabili a
e b
to 0
. a
è un array binario a 4 bit di quali coppie di parentesi ci troviamo attualmente, ed b
è un array binario a 16 bit di cui coppie di parentesi sono collegate tra loro.
Successivamente, passiamo in rassegna ciascun personaggio c
in x
, e ogni carattere d
in '0123'
. Innanzitutto determiniamo con quale tipo di parentesi si c
trova e=c.charCodeAt()/26-1|0
. I codici dei caratteri decimali di ciascun tipo di parentesi sono i seguenti:
() => 40,41
<> => 60,62
[] => 91,93
{} => 123,125
Dividendo per 26, sottraendo 1 e pavimentando, li mappiamo su 0, 1, 2 e 3, rispettivamente.
Quindi controlliamo se questo numero è uguale al valore corrente di d
. In tal caso, stiamo entrando o uscendo dal d
tipo di parentesi th, quindi inseriamo il d
bit th a
con a^=1<<d
. Se non lo è, ma ci sono all'interno del d
tipo di staffa °, abbiamo bisogno di capovolgere e
l'esimo bit nella d
esimo sezione di 4 bit di b
. Questo è fatto così:
b^=(a>>d&1)<<d*4+e
(a>>d&1)
Restituisce il d
th bit in a
. Se siamo all'interno del d
tipo di parentesi quinta, questo restituisce 1; in caso contrario, restituisce 0. Successivamente, spostiamo questo a sinistra di d*4+e
bit e XOR in b
base al risultato. Se siamo all'interno del d
tipo di parentesi th, questo XOR rappresenta il d*4+e
th bit di b
; altrimenti, non fa nulla.
Alla fine di tutto il loop, b
conterrà un numero di 1 bit pari al doppio del valore di ritorno desiderato. Ma dobbiamo ancora capire quanti bit sono. Ecco dove f
entra in gioco la sub-funzione :
f=y=>y&&y%2+f(y>>1)
Se y
è 0, questo restituisce semplicemente 0. Altrimenti, prende l'ultimo bit di y
with y%2
, quindi aggiunge il risultato dell'esecuzione di tutto tranne l'ultimo bit y
attraverso la funzione. Per esempio:
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
Eseguiamo b
questa funzione e dividiamo il risultato per 2, e c'è la nostra risposta.