华容道高性能计算引擎
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

61 lines
2.1 KiB

#include "common_code.h"
using klotski::CommonCode;
inline uint8_t binary_count(uint32_t bin) { // get number of non-zero bits
bin -= (bin >> 1) & 0x55555555;
bin = (bin & 0x33333333) + ((bin >> 2) & 0x33333333);
bin = ((bin >> 4) + bin) & 0x0F0F0F0F;
bin += bin >> 8;
bin += bin >> 16;
return bin & 0b111111;
}
/// NOTE: input should not be zero
inline uint32_t last_zero_num(uint32_t bin) { // get last zero number
bin ^= (bin - 1);
return binary_count(bin >> 1);
}
CommonCode CommonCode::from_string(const std::string &common_code) {
return CommonCode(common_code); // load from string
}
std::string CommonCode::to_string(bool shorten) const { // convert uint64_t code to string
char result[10]; // max length 9-bits
sprintf(result, "%09lX", code);
if (shorten) { // remove `0` after common code
if (code == 0x000000000) {
return "0"; // special case -> only one `0`
}
result[9 - last_zero_num(code) / 4] = '\0'; // truncate string
}
return result; // char* -> std::string
}
CommonCode::CommonCode(const std::string &common_code) { // convert from 1 ~ 9 bits string
/// check string length
if (common_code.length() > 9 || common_code.empty()) { // check string length
throw std::invalid_argument("common code format error");
}
/// check every characters
uint64_t result = 0;
for (auto const &bit : common_code) {
result <<= 4;
if (bit >= '0' && bit <= '9') { // 0 ~ 9
result |= (bit - 48);
} else if (bit >= 'A' && bit <= 'Z') { // A ~ Z
result |= (bit - 55);
} else if (bit >= 'a' && bit <= 'z') { // a ~ z
result |= (bit - 87);
} else {
throw std::invalid_argument("common code format error"); // unknown characters
}
}
result <<= (9 - common_code.length()) * 4; // low-bits fill with zero
/// check whether common code is valid
if (!CommonCode::check(result)) { // check converted common code
throw std::invalid_argument("invalid common code");
}
code = result;
}