Комментарии 19
Дано: knightNr — номер клетки доски, где стоит конь (от 0 до 63).
Надо: movesCount — количество полей, куда он может пойти (от 2 до 8).
Почему бы не завести массив из 64 элементов по ~3 бита, чтобы извлекать из него цифры непосредственно? Или даже из 16 элементов, если учитывать симметрии доски?
Более того, близость коня к краю доски отсекает некоторые из его 8ми ходов, и, наверно, можно написать несложную функцию из if-ов для решения этой задачи.
Самый быстрый способ
POPCNT?
Обстоятельно о подсчёте единичных битов. Добавляйте в закладки!
POPCNT?
Такая штука не на всех процессорах есть :-)
Процессор без SSE4.2 в 2019 году?
Можно при отсутствии этого флага выводить ругательное сообщение с предложением таки поагредить систему. Или перейти к варианту Б.
Можно при отсутствии этого флага выводить ругательное сообщение с предложением таки поагредить систему. Или перейти к варианту Б.
Приведённый алгоритм хорош для малозаполненных битбордов. Наличие в нём цикла и проверки условия не слишком дружественно к предсказателю ветвлений в процессоре. Поэтому, если важна скорость, обычно используют или ассемблерные вставки с POPCNT, или алгоритм без циклов. Пример из моей шахматной программы:
int CountBits(U64 b)
{
if (b == 0)
return 0;
static const U64 mask_1 = LL(0x5555555555555555); // 0101 0101 0101 0101 ...
static const U64 mask_2 = LL(0x3333333333333333); // 0011 0011 0011 0011 ...
static const U64 mask_4 = LL(0x0f0f0f0f0f0f0f0f); // 0000 1111 0000 1111 ...
static const U64 mask_8 = LL(0x00ff00ff00ff00ff); // 0000 0000 1111 1111 ...
U64 x = (b & mask_1) + ((b >> 1) & mask_1);
x = (x & mask_2) + ((x >> 2) & mask_2);
x = (x & mask_4) + ((x >> 4) & mask_4);
x = (x & mask_8) + ((x >> 8) & mask_8);
U32 y = U32(x) + U32(x >> 32);
return (y + (y >> 16)) & 0x3f;
}
Спасибо, очень красивое, элегантное решение!
А есть какой-то резон кроме эстетического делать статические переменные в функции?
Вы на какой архитектуре профилировали своё решение?
обычно используют или ассемблерные вставки с POPCNT, или алгоритм без циклов.
Или даже метод из стандартной библиотеки. И в реализации этого метода на java 8 лишь 17 арифметических и битовых операций, а не 21, как у вас.
код java.lang.Long#bitCount(Long)
public static int bitCount(long i) {
i = i - ((i >>> 1) & 0x5555555555555555L);
i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L);
i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
i = i + (i >>> 8);
i = i + (i >>> 16);
i = i + (i >>> 32);
return (int)i & 0x7f;
}
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Ход конём по битам. Шахматный Bitboard