JavaScript (ES7), 121 117 байт
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
Ого. Це було весело. Коли я вперше з’явився цей виклик, я накреслив ідею відповіді, але це було понад 150 байт, і я не хотів докладати зусиль, щоб пограти у нього. Я вчора зіткнувся з цією ідеєю у своєму зошиті і вирішив, що не переставатиму думати про це, поки повністю не заграю в неї. Я закінчив виписати два абсолютно нових алгоритми, перший з яких закінчився на кілька байт коротше після гри в гольф близько 25 байтів з тоннами злому.
Як це працює
Спочатку встановлюємо змінні a
і b
на 0
. a
це 4-розрядний двійковий масив, з парних дужок яких ми зараз перебуваємо, і b
є 16-бітовим двійковим масивом, який дужки пари пов'язані між собою.
Потім ми виконуємо цикл по кожному символу c
в x
, і кожен напівкоксу d
в '0123'
. Спочатку визначимо, який тип дужки c
має e=c.charCodeAt()/26-1|0
. Десяткові знаки коду кожного типу дужок такі:
() => 40,41
<> => 60,62
[] => 91,93
{} => 123,125
Ділення на 26, віднімання 1 і підлоги, ми відображаємо їх відповідно 0, 1, 2 і 3.
Далі ми перевіряємо, чи дорівнює це число поточному значенню d
. Якщо так, то ми або вхід або вихід з d
го типу кронштейна, тому ми перевертати d
й біт в a
с a^=1<<d
. Якщо це не так, але ми перебуваємо всередині d
типу дужки, нам потрібно перевернути цей e
біт у d
4-бітному розділі b
. Це робиться так:
b^=(a>>d&1)<<d*4+e
(a>>d&1)
Повертає d
біт у a
. Якщо ми знаходимось у d
типі дужок, це повертає 1; в іншому випадку вона повертається 0. Далі, ми пересуваємо цю ліву на d*4+e
біти, а XOR b
за результатом. Якщо ми знаходимось у d
типі дужок, цей XOR - це d*4+e
біт b
; інакше нічого не робить.
Наприкінці всього циклу b
буде міститися число 1-бітів, що дорівнює подвоєному бажаному поверненому значенню. Але нам ще потрібно розібратися, скільки це біт. Ось де підфункція f
надходить:
f=y=>y&&y%2+f(y>>1)
Якщо y
0, це просто повертає 0. В іншому випадку він бере останній біт y
з y%2
, а потім додає результат y
повторного запуску всіх, крім останнього біта . Наприклад:
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
Ми виконуємо b
цю функцію і ділимо результат на 2, і є наша відповідь.