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
Ồ Đó là niềm vui. Tôi đã phác thảo một ý tưởng trả lời khi thử thách này lần đầu tiên xuất hiện, nhưng nó dài hơn 150 byte và tôi không muốn nỗ lực để chơi nó. Tôi đã chạy qua ý tưởng này trong cuốn sổ tay của mình ngày hôm qua và quyết định tôi sẽ không ngừng nghĩ về nó cho đến khi tôi hoàn toàn đánh golf nó. Cuối cùng tôi đã viết ra hai thuật toán hoàn toàn mới, thuật toán đầu tiên kết thúc ngắn hơn vài byte sau khi đánh gôn khoảng 25 byte với hàng tấn hack.
Làm thế nào nó hoạt động
Đầu tiên chúng ta đặt biến avà bthành 0. alà mảng nhị phân 4 bit trong đó các cặp khung mà chúng ta hiện đang ở bên trong và blà mảng nhị phân 16 bit trong đó các cặp khung được liên kết với nhau.
Tiếp theo, chúng ta lặp qua từng nhân vật ctrong x, và mỗi char dtrong '0123'. Đầu tiên chúng tôi xác định loại khung clà với e=c.charCodeAt()/26-1|0. Mã char thập phân của từng loại khung như sau:
() => 40,41
<> => 60,62
[] => 91,93
{} => 123,125
Bằng cách chia cho 26, trừ 1 và sàn, chúng tôi ánh xạ các giá trị này thành 0, 1, 2 và 3 tương ứng.
Tiếp theo chúng tôi kiểm tra xem con số này có bằng giá trị hiện tại của không d. Nếu đúng như vậy, chúng ta đang nhập hoặc thoát khỏi dloại khung thứ, vì vậy chúng ta lật dbit thứ avới a^=1<<d. Nếu không, nhưng chúng ta nằm trong dloại khung thứ, chúng ta cần lật ebit thứ trong phần d4 bit của b. Điều này được thực hiện như vậy:
b^=(a>>d&1)<<d*4+e
(a>>d&1)Trả về dbit thứ trong a. Nếu chúng ta ở trong dloại khung thứ, điều này trả về 1; mặt khác, nó trả về 0. Tiếp theo, chúng ta thay đổi kết quả này theo d*4+ebit và XOR btheo kết quả. Nếu chúng ta ở trong dkiểu khung thứ, thì XOR này là d*4+ebit thứ của b; mặt khác, nó không làm gì cả
Khi kết thúc tất cả các vòng lặp, bsẽ chứa một số bit 1 bằng hai lần giá trị trả về mong muốn. Nhưng chúng ta vẫn cần tính xem có bao nhiêu bit. Đó là nơi chức năng phụ fxuất hiện:
f=y=>y&&y%2+f(y>>1)
Nếu ylà 0, điều này chỉ đơn giản trả về 0. Nếu không, nó sẽ lấy bit cuối cùng yvới y%2, sau đó thêm kết quả của việc chạy tất cả trừ bit cuối cùng ythông qua hàm một lần nữa. Ví dụ:
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
Chúng tôi chạy bqua chức năng này và chia kết quả cho 2, và đó là câu trả lời của chúng tôi.