nissy.cpp (6077B)
1 /* 2 C++20 interface for nissy. 3 4 TODO: add more documentation (here and in README.md) 5 */ 6 7 #include "./nissy.h" 8 9 #include <fstream> 10 11 extern "C" { 12 long long nissy_compose(const char *, const char *, char *); 13 long long nissy_inverse(const char *, char *); 14 long long nissy_applymoves(const char *, const char *, char *); 15 long long nissy_applytrans(const char *, const char *, char *); 16 long long nissy_convert(const char *, const char *, const char *, 17 unsigned, char *); 18 long long nissy_getcube(long long, long long, long long, long long, 19 const char *, char *); 20 long long nissy_solverinfo(const char *, char *); 21 long long nissy_gendata(const char *, unsigned long long, 22 unsigned char *); 23 long long nissy_checkdata(unsigned long long, const unsigned char *); 24 long long nissy_solve(const char *, const char *, unsigned, unsigned, 25 unsigned, unsigned, unsigned, unsigned, unsigned long long, 26 const unsigned char *, unsigned, char *, long long *); 27 long long nissy_countmoves(const char *); 28 long long nissy_setlogger(void (*)(const char *, void *), void *); 29 } 30 31 namespace nissy { 32 33 /* Definition of constants with const qualifier */ 34 const nissflag nissflag::NORMAL{1}; 35 const nissflag nissflag::INVERSE{2}; 36 const nissflag nissflag::MIXED{4}; 37 const nissflag nissflag::LINEAR{3}; 38 const nissflag nissflag::ALL{7}; 39 40 const error error::OK{0}; 41 const error error::UNSOLVABLE{-1}; 42 const error error::INVALID_CUBE{-10}; 43 const error error::UNSOLVABLE_CUBE{-11}; 44 const error error::INVALID_MOVES{-20}; 45 const error error::INVALID_TRANS{-30}; 46 const error error::INVALID_FORMAT{-40}; 47 const error error::INVALID_SOLVER{-50}; 48 const error error::NULL_POINTER{-60}; 49 const error error::BUFFER_SIZE{-61}; 50 const error error::DATA{-70}; 51 const error error::OPTIONS{-80}; 52 const error error::UNKNOWN{-999}; 53 54 namespace size { 55 constexpr size_t B32 = 22; 56 constexpr size_t H48 = 88; 57 constexpr size_t CUBE_MAX = H48; 58 constexpr size_t TRANSFORMATION = 12; 59 constexpr size_t DATAID = 255; 60 } 61 62 bool error::ok() const { return value >= 0; } 63 64 cube::cube() {} 65 66 error cube::move(const std::string& moves) 67 { 68 char result[size::B32]; 69 long long err = nissy_applymoves( 70 m_b32.c_str(), moves.c_str(), result); 71 if (err < 0) 72 return error{err}; 73 m_b32 = result; 74 return error::OK; 75 } 76 77 error cube::transform(const std::string& trans) 78 { 79 char result[size::B32]; 80 long long err = nissy_applytrans( 81 m_b32.c_str(), trans.c_str(), result); 82 if (err < 0) 83 return error{err}; 84 m_b32 = result; 85 return error::OK; 86 } 87 88 void cube::invert() 89 { 90 char result[size::B32]; 91 nissy_inverse(m_b32.c_str(), result); 92 m_b32 = result; 93 } 94 95 void cube::compose(const cube& other) 96 { 97 char result[size::B32]; 98 nissy_compose( 99 m_b32.c_str(), other.to_string().c_str(), result); 100 m_b32 = result; 101 } 102 103 std::string cube::to_string() const { return m_b32; } 104 105 std::variant<std::string, error> 106 cube::to_string(const std::string& format) const 107 { 108 char result[size::CUBE_MAX]; 109 auto err = nissy_convert("B32", format.c_str(), 110 m_b32.c_str(), size::CUBE_MAX, result); 111 if (err < 0) 112 return error{err}; 113 else 114 return result; 115 } 116 117 std::variant<cube, error> 118 cube::from_string(const std::string& str) 119 { 120 return from_string(str, "B32"); 121 } 122 123 std::variant<cube, error> 124 cube::from_string(const std::string& str, const std::string& format) 125 { 126 char result[size::B32]; 127 cube c; 128 auto err = nissy_convert(format.c_str(), 129 "B32", c.m_b32.c_str(), size::B32, result); 130 if (err < 0) 131 return error{err}; 132 c.m_b32 = result; 133 return c; 134 } 135 136 std::variant<cube, error> 137 cube::get(long long ep, long long eo, long long cp, long long co) 138 { 139 return get(ep, eo, cp, co, "fix"); 140 } 141 142 std::variant<cube, error> 143 cube::get(long long ep, long long eo, long long cp, long long co, 144 const std::string& options) 145 { 146 char result[size::B32]; 147 cube c; 148 auto err = nissy_getcube( 149 ep, eo, cp, co, options.c_str(), result); 150 if (err < 0) 151 return error{err}; 152 c.m_b32 = result; 153 return c; 154 } 155 156 error solver::generate_data() 157 { 158 data.resize(size); 159 auto err = nissy_gendata(name.c_str(), 160 size, reinterpret_cast<unsigned char *>(data.data())); 161 return error{err}; 162 } 163 164 void solver::read_data(std::ifstream& ifs) 165 { 166 data.resize(size); 167 ifs.read(reinterpret_cast<char *>(data.data()), size); 168 } 169 170 error solver::check_data() 171 { 172 auto err_value = nissy_checkdata(data.size(), 173 reinterpret_cast<const unsigned char *>(data.data())); 174 error err{err_value}; 175 data_checked = err.ok(); 176 return err; 177 } 178 179 void solver::unload_data() 180 { 181 data.resize(0); 182 } 183 184 solver::solve_result 185 solver::solve(const cube& cube, nissflag niss, unsigned minmoves, 186 unsigned maxmoves, unsigned maxsols, unsigned optimal, 187 unsigned threads) 188 { 189 solver::solve_result result; 190 191 if (maxsols == 0) { 192 result.solutions = {}; 193 result.err = error::OK; 194 return result; 195 } 196 197 const size_t len = 3 * (maxmoves+1) * maxsols; 198 std::vector<char> csols(len); 199 200 auto err = nissy_solve(cube.to_string().c_str(), 201 name.c_str(), niss.value, minmoves, maxmoves, maxsols, 202 optimal, threads, data.size(), 203 reinterpret_cast<const unsigned char *>(data.data()), len, 204 csols.data(), result.stats.data()); 205 result.err = error{err}; 206 207 if (err < 0) 208 return result; 209 210 std::string_view strsols(csols.data()); 211 for (auto r : strsols | std::views::split('\n')) 212 if (r.begin() != r.end()) 213 result.solutions.push_back( 214 std::string{r.begin(), r.end()}); 215 216 return result; 217 } 218 219 std::variant<solver, error> solver::get(const std::string& name) 220 { 221 char dataid[size::DATAID]; 222 auto err = nissy_solverinfo(name.c_str(), dataid); 223 if (err < 0) 224 return error{err}; 225 solver s(name); 226 s.size = (unsigned)err; 227 s.id = std::string{dataid}; 228 return s; 229 } 230 231 solver::solver(const std::string& str) : name{str} {} 232 233 error count_moves(const std::string& moves) 234 { 235 auto err = nissy_countmoves(moves.c_str()); 236 return error{err}; 237 } 238 239 void set_logger(void (*log)(const char *, void *), void *data) 240 { 241 nissy_setlogger(log, data); 242 } 243 }