Записанные цифры до цифр - понимание короткого запутанного кода
Может кто-нибудь помочь мне понять этот код?
long long n,u,m,b;main(e,r){for(;n++||(e=getchar()|32)>=0;b=
"ynwtsflrabg"[n%=11]-e?b:b*8+n)for(r=b%64-25;e<47&&b;b/=8)for
(n=19;n;"1+DIY/.K430x9G(kC["[n]-42&255^b||(m+=n>15?n:n>9?m%
u*~-u:~r?n+!r*16:n*16,b=0))u=1ll<<6177%n--*4;printf("%llx",m);}
Я нашел некоторые объяснения, но они очень краткие. Что я знаю до сих пор: этот код выводит десятичное число для заданного ввода записанных чисел. Он ищет некоторые комбинации символов, которые образуют числа, и сохраняет эти символы в восьмеричном представлении вместо шестнадцатеричного. Он присваивает некоторые значения найденным комбинациям. Затем он добавляет эти значения к результату (для слов типа "пять", "тринадцать" и т. Д.) Или каким-то образом сдвигает цифры (для слов типа "тысяча" и т. Д.). Это все, что я понял из найденных объяснений: https://www.ioccc.org/2012/kang/hint.html, http://j.mearie.org/post/7462182919/spelt-number-to-decimal.
Я пытался понять это выражение кода по выражению, но я только пришел к бесконечному циклу, где я не понимаю, для чего нужна одна переменная, поскольку она изменяется только позже, но тогда она зависит от следующей переменной, то есть также изменен позже в циклах. Я просто не знаю с чего начать.
Я попытался прокомментировать каждый кусок кода + убрать некоторые запутывания и неясности:
long long n, u, m, b; // = 0
int main(int e, int r) {
/* loop1:*/ for(;
/* --condition: */
/* if not:*/ n++ || // n++ == 0 <=> n == 0 // Set n += 1
/* then:*/
/* if not:*/ (e = getchar() | 32) >= 0; // Set e <- input char
// `| 32` transforms upper case to lower case
// getchar < 0 <=> EOF
/* then break*/
/* --increment: */
b =
/* if:*/ "ynwtsflrabg"[n %= 11] - e ? // Set n %= 11
/* then b=*/ b :
/* else b=*/ b * 8 + n)
/* loop2:*/ for(r = (b % 64) - 25; // Set r
/* --condition: */
/* if not:*/ (e < 47) && b;
/* break*/
/* --increment: */
b /= 8) // Set b
/* loop3:*/ for(n = 19; // Set n
/* --condition: */
/* if not:*/ n; // <=> n != 0
/* then break */
/* --increment: */
/* if not:*/ ("1+DIY/.K430x9G(kC["[n] - 42) & 255 ^ b ||
/* <=> {7, 1, 26, 31, 47, 5, 4, 33, 10, 9, 6, 78,
15, 29, 254, 65, 25, 49, 214}[n] == b */
/* then:*/ (m += // Set m
/* if:*/ n > 15 ?
/* then m+=*/ n :
/* else if:*/ n > 9 ?
/* then m+=*/ m % u * ~-u :
// <=> m % u * (u - 1)
/* else if:*/ ~(int)r ?
/* then m+=*/ n + !(int)r * 16 :
/* else m+=*/ n * 16,
b = 0)) // Set b
/* --body: */ u = 1ll << (6177 % n-- * 4); // Set u, n
// <=> u = pow(2, 6177 % n-- * 4)
printf("%llx\n", m);
}
Большая часть этого переписанного кода может выглядеть даже страшнее, чем оригинал, но мне просто нужно было пройти шаг за шагом, так что, возможно, это поможет кому-то еще.
Кажется, что вывод генерируется в последнем цикле, в m += ...
, Но я не могу понять условие выше этого: "1+DIY/.K430x9G(kC["[n] - 42) & 255 ^ b
, Это переводится как: {7, 1, 26, 31, 47, 5, 4, 33, 10, 9, 6, 78, 15, 29, 254, 65, 25, 49, 214}[n] == b
, где моя {...}
нотация ведет себя как строковый литерал, содержащий символы, соответствующие этим числам - которые на данный момент кажутся мне бессмысленными.
редактировать
Кто-то проголосовал за закрытие этого вопроса за неясность. Чтобы было понятно, что мне нужно:
Я был бы признателен за любые подсказки или идеи по любому из методов, используемых в этом коде. Как например:
- Автор кода использовал преднамеренное запутывание:
i["foo"]
вместо"foo"[i]
, - Автор сократил
(u - 1)
выражение как~-u
Мои основные проблемы с деталями:
"1+DIY/.K430x9G(kC["[n]-42&255^b
- Почему эти персонажи?m+=n>15?n:n>9?m%u*~-u:~r?n+!r*16:n*16,b=0)
- Почему эти условия наn
?e<47
- Зачем47
-/
персонаж?