Не можете понять этот код?

79
6

Может ли кто-нибудь помочь мне в понимании следующего кода: -


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. оператор comma (,), используемый в типе возвращаемых данных функции
3. Использование оператора [] после строки.

4. И вообще весь код.

спросил(а) 2017-01-02T19:51:00+03:00 3 года, 2 месяца назад
1
Решение
51

Я посмотрел ссылку, которую вы предоставили. После тщательного наблюдения кода я пришел к следующему выводу.


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;

Позвольте мне дать вам некоторые основы.


    В С++

cout<<"abcde"[2];


даст вам выход

c

теперь, если вы внимательно посмотрите код в ссылке, которую вы предоставили
что-то вроде этого:


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

- это не что иное, как


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

Теперь пришло время объяснить, как этот код вычисляет количество отверстий.
Значение ASCII TAB равно 9, бинарный эквивалент которого равен 1001.
Значение ASCII SPACE равно 32, бинарный эквивалент которого равен 100000.


поэтому бит мудрый и TAB с 3 приведет к


            1001 & 0011 = 0001    which is 1

бит мудрый и SPACE с 3 приведет к


            100000 & 000011 = 000000   which is 0

заменяя TAB на 1 и SPACE на 0, значит, это завершается записью


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

n% 10 - младшая десятичная цифра n. Мы используем это как индекс в строковый литерал, который содержит информацию о количестве отверстий в этой младшей десятичной цифре младшего разряда, а затем добавляем его к результату r.

ответил(а) 2017-01-02T23:42:00+03:00 3 года, 2 месяца назад
114

Это какой-то обфускация C-конкурса? Или код гольфа?

Во-первых, странная декларация. Он просто объединяет две несвязанные декларации на одной строке. Так же, как


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 % 10 - младшая десятичная цифра n. Мы используем это как индекс в строковый литерал (который является всего лишь массивом char s), затем извлекаем два младших бита символьного кода ASCII и отбрасываем остальное. Я уверен, что в исходной программе, с которой вы скопировали этот код, символы в этом литерале не были пробелами, а скорее определенными непечатаемыми символами, выбранными таким образом, что два младших бита их кодов ASCII дали точно количество "отверстий" в соответствующей цифре. Символ 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;
};

ответил(а) 2017-01-02T20:10:00+03:00 3 года, 2 месяца назад
37

Использование специальных символов в браузерах может быть проблемой, из Ascii Table мы можем использовать все символы, которые в восьмеричных концах от 0 до 2 или 4-6, используя эти 2 бита, чтобы узнать, сколько отверстий имеет номер (% 3 совпадает с % 0b11, a и с последними 2 битами).


Одно решение с символами 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;
}

Я не знаю, какие символы он пытался использовать, но не работал на веб-сайте проблемы.

ответил(а) 2017-01-02T20:46:00+03:00 3 года, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема