旋转整数以获得最大尾随二进制零
Rotate integer for maximum trailing binary zeros
给定 16 位数据,我需要(使用 C++11)找到使尾随零数最大化的旋转。
例如(为清楚起见,使用 8 位),
10110001 -> 11011000 so rot=1
10000011 -> 11100000 so rot=2
etc.
显然 'brute force' 它很容易。但我怀疑有一个优雅的解决方案。
我认为代码中的一切都清楚了。类推左移。您可以在 cpp.sh
上进行测试
#include <iostream>
#include <string>
#include <bitset>
const int count_bits = 8;
int num_right_rotation(std::string number)
{
int max = 0;
int rotation = 0;
std::bitset<count_bits> one (number);
for(int i=0; i<count_bits; i++)
{
int max_temp = 0;
for(int j=0; j<count_bits; j++)
{
if(!one[j]) max_temp++;
else break;
}
if(max_temp > max)
{
max = max_temp;
rotation = i;
}
one = (one>>1) | (one<<count_bits-1);
}
return rotation;
}
int main()
{
std::cout << num_right_rotation ("10110001") << std::endl;
std::cout << num_right_rotation ("10000011") << std::endl;
return 0;
}
以下函数产生左旋转距离(因为您可能想在之后使用 std::rotate)。想法:遍历这些位,当您偶然发现一个 0 时,从那里开始计算零。用取模绕到最后继续数:
#include <algorithm>
#include <iostream>
#include <string>
int rotation(std::string bits)
{
int max_pos = 0;
int max_count = 0;
for (int i = 0; i < bits.size();)
{
if (bits[i] == '0')
{
int count = 1;
for (; bits[(i + count) % bits.size()] == '0' && count < bits.size();
++count);
if (count > max_count)
{
max_pos = i;
max_count = count;
}
i += count;
}
else
{
++i;
}
}
return (max_pos + max_count) % bits.size();
}
int main()
{
std::cout << rotation ("10110001") << std::endl;
std::cout << rotation ("10000011") << std::endl;
return 0;
}
这是我正在考虑的 'elegant solution' 想法:
假设我们正在测试 x = 1110 0000.
减去 1 得到 11011 1111。
而 x^(x-1) = 0011 0000.
即我们总是会得到这种形式的数字,具体取决于尾随零的数量。
最尾随的零将产生最大的数字。
所以 Pythonesque 伪代码可能看起来像:
iWinner = [x ^ (x-1) where x=rot(X,i) for i in range(16)].indexWithMaxValue()
在 C:
uint16_t x = 42;
uint16_t xWinner=0;
for(uint16_t i=0,yMax=0; i<16; i++) {
x = x << 1 + x >> 15; // rotate 1 left
uint16_t y = x ^ (x-1);
if( y > yMax ) {
yMax = y;
xWinner = x;
}
}
不过,我看不到任何利用 C++ 进一步清理它的方法。
给定 16 位数据,我需要(使用 C++11)找到使尾随零数最大化的旋转。
例如(为清楚起见,使用 8 位),
10110001 -> 11011000 so rot=1
10000011 -> 11100000 so rot=2
etc.
显然 'brute force' 它很容易。但我怀疑有一个优雅的解决方案。
我认为代码中的一切都清楚了。类推左移。您可以在 cpp.sh
上进行测试#include <iostream>
#include <string>
#include <bitset>
const int count_bits = 8;
int num_right_rotation(std::string number)
{
int max = 0;
int rotation = 0;
std::bitset<count_bits> one (number);
for(int i=0; i<count_bits; i++)
{
int max_temp = 0;
for(int j=0; j<count_bits; j++)
{
if(!one[j]) max_temp++;
else break;
}
if(max_temp > max)
{
max = max_temp;
rotation = i;
}
one = (one>>1) | (one<<count_bits-1);
}
return rotation;
}
int main()
{
std::cout << num_right_rotation ("10110001") << std::endl;
std::cout << num_right_rotation ("10000011") << std::endl;
return 0;
}
以下函数产生左旋转距离(因为您可能想在之后使用 std::rotate)。想法:遍历这些位,当您偶然发现一个 0 时,从那里开始计算零。用取模绕到最后继续数:
#include <algorithm>
#include <iostream>
#include <string>
int rotation(std::string bits)
{
int max_pos = 0;
int max_count = 0;
for (int i = 0; i < bits.size();)
{
if (bits[i] == '0')
{
int count = 1;
for (; bits[(i + count) % bits.size()] == '0' && count < bits.size();
++count);
if (count > max_count)
{
max_pos = i;
max_count = count;
}
i += count;
}
else
{
++i;
}
}
return (max_pos + max_count) % bits.size();
}
int main()
{
std::cout << rotation ("10110001") << std::endl;
std::cout << rotation ("10000011") << std::endl;
return 0;
}
这是我正在考虑的 'elegant solution' 想法:
假设我们正在测试 x = 1110 0000.
减去 1 得到 11011 1111。
而 x^(x-1) = 0011 0000.
即我们总是会得到这种形式的数字,具体取决于尾随零的数量。
最尾随的零将产生最大的数字。
所以 Pythonesque 伪代码可能看起来像:
iWinner = [x ^ (x-1) where x=rot(X,i) for i in range(16)].indexWithMaxValue()
在 C:
uint16_t x = 42;
uint16_t xWinner=0;
for(uint16_t i=0,yMax=0; i<16; i++) {
x = x << 1 + x >> 15; // rotate 1 left
uint16_t y = x ^ (x-1);
if( y > yMax ) {
yMax = y;
xWinner = x;
}
}
不过,我看不到任何利用 C++ 进一步清理它的方法。