看不懂这段代码?

Can't understand this code?

任何人都可以帮助我理解以下代码:-

int r, countIt(int n) {
    while (r += "            2  "[n % 10] & 3, n /= 10);
    return r;
}

我在 codefights.com、https://codefights.com/challenge/v5Zg8trjoun3PTxrZ/solutions/Aj3ppbhSShixt4nBi

的挑战之一中找到了这段代码

这是计算数字中孔数的解决方案。
例如

1111 = 0  
0000 = 4  
1234 = 0  
8888 = 8   

我无法理解以下内容:
1.这段代码的逻辑
2. return函数数据类型
中使用的逗号(,)运算符 3. string.
后使用[]运算符 4. 实际上是整个代码。

这是某种 obfuscated C contest submission? Or code golf 吗?


首先,奇怪的声明。它只是将两个不相关的声明组合在一行中。正如

int x, y;

等同于

int x;
int y;

你的代码是否等同于

int r;
int countIt(int n) {...}

这是一个鲜为人知的,谢天谢地,很少有人使用 C 语法的怪癖,你可以做到这一点。


这样写循环会更清晰:

do {
  r += "            2  "[n % 10] & 3;
  n /= 10;
} while (n);

它基本上遍历 n 的十进制表示中的数字。


现在是r += " 2 "[n % 10] & 3;的部分。 n % 10n的低位十进制数。我们将其用作字符串文字(只是 chars 的数组)的索引,然后提取字符 ASCII 码的两个低位并丢弃其余部分。我很确定,在您从中复制此代码的原始程序中,该文字中的字符不是空格,而是某些选择的不可打印字符,其 ASCII 代码的两个低位恰好给出了相应数字中 "holes" 的数量。 2 字符是一个转移注意力的字符 - 它位于位置 12,但实际上只使用了字符 0 到 9。

也就是说,这部分可以这样写更清楚:

static const int numHoles[10] = {1, 0, 0, 0, 1, 0, 1, 0, 2, 1};
int digit = n % 10;
r += numHoles[digit];

放在一起,我们有:

int countIt(int n) {
  // number of holes in digit      0  1  2  3  4  5  6  7  8  9
  static const int numHoles[10] = {1, 0, 0, 0, 1, 0, 1, 0, 2, 1};
  int r = 0;
  do {
    int digit = n % 10;
    r += numHoles[digit];
    n /= 10;
  } while (n);
  return r;
};

在浏览器中使用特殊字符可能是个问题,从 Ascii Table 我们可以使用八进制以 0 到 2 或 4 到 6 结尾的所有字符,使用这 2 位来知道数字有多少个孔有(% 3% 0b11 相同,最后 2 位为 and)。

一个使用 ascii 字符的解决方案是:

int countIt(int n) {
    int r;
    while (r += "1000101021"[n % 10] & 3, n /= 10);
    return r;
}

我可以用这样的东西代替“0”到“2”:

int countIt(int n) {
    int r;
    while (r += "! X0) I@*9"[n % 10] & 3, n /= 10);
    return r;
}

我不知道他尝试使用什么字符,但在挑战网站上没有用。

我查了你提供的link。仔细观察代码后,我得出以下结论。

int r, countIt(int n) {.....}

相当于写成

int r;
int countIt(int n){.....}

现在

while (r += "            2  "[n % 10] & 3, n /= 10);

相当于:

do{
    r += "           2  "[n % 10] & 3;
    n/=10;
}while(n);

现在是代码的逻辑部分

r += "           2  "[n % 10] & 3;

让我给你一些基础知识。

  1. 在 C++ 中

cout<<"abcde"[2];

会给你输出

c

现在,如果您仔细观察您提供的 link 中的代码 它是这样的:

r += "           2  "[n % 10] & 3;

不过是

r += "TAB,SPACE,SPACE,SPACE,SPACE,SPACE,TAB,SPACE,2,TAB"[n % 10] & 3;

现在是解释这段代码如何计算孔数的时候了。 TAB 的 ASCII 值为 9,其二进制等效值为 1001。 SPACE 的 ASCII 值为 32 其二进制等价物为 100000.

所以按位和 TAB 与 3 将得到结果

            1001 & 0011 = 0001    which is 1

按位与 SPACE 与 3 将得到

            100000 & 000011 = 000000   which is 0

将 TAB 替换为 1,将 SPACEs 替换为 0,因此得出的结论是

do{
    r += "1000001021"[n % 10] & 3;
    n/=10;
}while(n);

n % 10是n的低位十进制数。我们将其用作字符串文字的索引,其中包含有关该低位十进制数字中有多少个空洞的信息,然后将其添加到结果 r 中。