2017-01-02 7 views
4

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

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

+2

Это всего лишь две декларации, объединенные вместе. Точно так же, как 'int x, y;' эквивалентно 'int x; int y; ', код, который вы показываете, эквивалентен' int r; int countIt (int n) {...} '. Определение слияния переменных и определение функции, как это, только путают; не делайте этого в своем коде, как бы круто это ни выглядело. –

+1

Ничего себе, это довольно умно. Ужасно, но смешно. :) –

+0

Спасибо @IgorTandetnik. И эта строка? –

ответ

1

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

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 

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

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.

так немного мудрая Anding TAB с 3 приведет к

  1001 & 0011 = 0001 which is 1 

битового мудрое Anding пространство с 3 приведет к

  100000 & 000011 = 000000 which is 0 

заменяющих язычков с 1 и пространством с 0, следовательно, это делает вывод, как написание

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

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

+0

Еще одна вещь. Переменная r является глобальной или локальной? –

+0

yep его глобальная переменная. – BlessonThomas

9

Это что-то вроде obfuscated C contest? Или 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 % 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; 
}; 
+0

Я действительно посмотрел на ссылку, которую он дал, и кажется, что он смотрит, что у t есть пробелы, так как он терпит неудачу в большинстве тестов. –

+1

@TomTanner Вероятно, работал на автору автора orignal, но эти непечатаемые символы не пробивались, когда копируются/вставляются в браузер. Слишком умно пополам. –

+0

Они не просто пространства, он просто выглядит. – James

0

Использование специальных символов в браузерах могут быть проблемы , от Ascii Table мы можем использовать все символы, которые в восьмеричных концах от 0 до 2 или от 4 до 6, используя эти 2 бита, чтобы узнать, сколько отверстий имеет число (% 3 - это то же самое, что и % 0b11, an и с последними 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) [email protected]*9"[n % 10] & 3, n /= 10); 
    return r; 
} 

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

Смежные вопросы