破解朋友圈一道二进制题目

晚上刷朋友圈看到一道破解二进制的题目,因为最近也在研究编码,索性试试看。先上图:

是不是很有食欲?其实,解题的过程也比较有意思。

先摘出文中字符串:

var source = '111001011000010110110110 111001011010111010011110 111001101000100010010001 111001001011100110011111 111001001011100010001101 111001111001111110100101 111010011000000110010011'

 

1、首先,二进制是8位1个比特,所以先将以上字符串按8位分割,可以用正则解决。

var arr = source.replace(/\s/g, '').match(/\d{8}/g)

 

其中,arr[0], arr[1], arr[2], arr[3]分别以1110, 10, 10, 1110开头。熟悉unicode和utf-8就清楚这种顺序是utf-8。结合维基百科utf-8上的表格可以看到,UTF-8是以1-4个字节来编码的,如果首字节以0开头,就是一个字节;如果首字节以110开头,就是二个字节;1110开头,3个字节;11110开头,4个字节。后续字节都以10开头。将x代码的编码组合一起所代表的数字16进制,就对应了该字符在unicode中的码点,即unicode码。在JS中,可以直接用unicode码取得对应的字符(包括中文),即String.fromCharCode(unicode码)。但JS中的unicode码不必一定是16进制表示,将二进制字符串转成10进制的数字即可作为unicode码,不必转成16进制。

2、按上述规则,将arr中的字符串按1-4个字节分组合并,转成字符串。最终JS代码如下:

function binaryToUnicode(source) {
  var start = true;
  var total = 0;
  var group;
  return source
    .replace(/\s/g, '')
    .match(/\d{8}/g)
    .reduce((calc, c) => {
      if (start) {
        if (c.substr(0, 1) === '0') {
          calc.push(c.substr(1))
        } else if (c.substr(0, 5) === '11110') {
          group = c.substr(5)
          start = false
          total = 3
        } else if (c.substr(0, 4) === '1110') {
          group = c.substr(4)
          start = false
          total = 2
        } else if (c.substr(0, 5) === '110') {
          group = c.substr(3)
          start = false
          total = 2
        }
      } else if (total > 0) {
        group += c.substr(2)
        total--
        if (total === 0) {
          calc.push(group)
          group = ''
          start = true
        }
      }

      return calc
    }, [])
    .map(i => String.fromCharCode(parseInt(i, 2)))

    .join('')
}

binaryToUnicode(source);

 

拿到题目答案:其实我也不知道