EulerUtility.cpp (9668B)
1 #include <fstream> 2 #include <numeric> 3 #include <regex> 4 #include <sstream> 5 #include <unordered_set> 6 7 #include "EulerUtility.h" 8 9 int EulerUtility::multiply(int x, int y) 10 { 11 return x * y; 12 } 13 14 int EulerUtility::sumOfDivisors(int n) 15 { 16 int prod = 1; 17 18 for(int k = 2; k * k <= n; ++k) 19 { 20 int p = 1; 21 22 while(n % k == 0) 23 { 24 p = p * k + 1; 25 n /= k; 26 } 27 28 prod *= p; 29 } 30 31 if(n > 1) 32 prod *= 1 + n; 33 34 return prod; 35 } 36 37 std::vector<int> EulerUtility::getPrimesUnderCeiling(int ceiling) 38 { 39 std::vector<int> primes; 40 41 primes.push_back(2); 42 primes.push_back(3); 43 44 bool is_prime; 45 46 for(int i = 5; i < ceiling; i += 2) 47 { 48 is_prime = true; 49 50 for(int j = 3; j * j <= i && is_prime; j += 2) 51 if(i % j == 0) is_prime = false; 52 53 if(is_prime) 54 primes.push_back(i); 55 } 56 57 return primes; 58 } 59 60 std::vector<int> EulerUtility::getPrimesUnderCeilingIndexed(int ceiling) 61 { 62 std::vector<int> primes = { -1, -1, 2, 3, -1 }; 63 64 bool is_prime; 65 66 for(int i = 5; i < ceiling; i += 2) 67 { 68 is_prime = true; 69 70 for(int j = 3; j * j <= i && is_prime; j += 2) 71 if(i % j == 0) is_prime = false; 72 73 if(is_prime) 74 { 75 primes.push_back(i); 76 primes.push_back(-1); 77 } 78 else 79 { 80 primes.push_back(-1); 81 primes.push_back(-1); 82 } 83 } 84 85 return primes; 86 } 87 88 std::vector<int> EulerUtility::tokenizer(std::string s, char delim) 89 { 90 std::istringstream split(s); 91 std::vector<int> tokens; 92 for (std::string each; std::getline(split, each, delim); tokens.push_back(atoi(each.c_str()))); 93 94 return tokens; 95 } 96 97 std::vector<std::string> EulerUtility::strTokenizer(std::string s, char delim) 98 { 99 std::istringstream split(s); 100 std::vector<std::string> tokens; 101 for (std::string each; std::getline(split, each, delim); tokens.push_back(each)); 102 103 return tokens; 104 } 105 106 std::vector<int> EulerUtility::factorialDigits(int n) 107 { 108 std::vector<int> digits(1, 1); 109 110 for (int i = 1; i <= n; ++i) 111 { 112 for (unsigned j = 0; j < digits.size(); ++j) 113 digits[j] *=i; 114 115 for (unsigned j = 0; j < digits.size(); ++j) 116 { 117 if (digits[j] >= 10) 118 { 119 int carry = (digits[j] - (digits[j] % 10)) / 10; 120 digits[j] = digits[j] % 10; 121 122 if (j == digits.size() - 1) 123 digits.push_back(carry); 124 else 125 digits[j + 1] += carry; 126 } 127 } 128 } 129 130 return digits; 131 } 132 133 std::vector<int> EulerUtility::powerDigits(int n, int p) 134 { 135 std::vector<int> digits = intToDigits(n); 136 std::reverse(digits.begin(), digits.end()); 137 138 for (int i = 1; i < p; ++i) 139 { 140 for (unsigned j = 0; j < digits.size(); ++j) 141 digits[j] *=n; 142 143 for (unsigned j = 0; j < digits.size(); ++j) 144 { 145 if (digits[j] >= 10) 146 { 147 int carry = (digits[j] - (digits[j] % 10)) / 10; 148 digits[j] = digits[j] % 10; 149 150 if (j == digits.size() - 1) 151 digits.push_back(carry); 152 else 153 digits[j + 1] += carry; 154 } 155 } 156 } 157 158 return digits; 159 } 160 161 cpp_int EulerUtility::bigFactorial(cpp_int n) 162 { 163 if (n == 0) 164 return 1; 165 return n * bigFactorial(n - 1); 166 } 167 168 int EulerUtility::factorial(int n) 169 { 170 if (n == 0) 171 return 1; 172 return n * factorial(n - 1); 173 } 174 175 cpp_int EulerUtility::choose(int n, int k) 176 { 177 return EulerUtility::bigFactorial(n) / (EulerUtility::bigFactorial(k) * EulerUtility::bigFactorial(n - k)); 178 } 179 180 bool EulerUtility::isPerfectSquare(llui n) 181 { 182 llui tst = (llui)(sqrt(n) + 0.5); 183 return tst*tst == n; 184 } 185 186 bool EulerUtility::isPerfectCube(llui n) 187 { 188 llui tst = (llui)std::floor(std::pow(n, 1/3.) + 0.5); 189 return n == tst * tst * tst; 190 } 191 192 std::vector<int> EulerUtility::intToDigits(int n) 193 { 194 std::vector<int> digitArray; 195 196 while (n != 0) 197 { 198 digitArray.push_back(n % 10); 199 n /= 10; 200 } 201 202 std::reverse(digitArray.begin(), digitArray.end()); 203 204 return digitArray; 205 } 206 207 std::vector<int> EulerUtility::lluiToDigits(llui n) 208 { 209 std::vector<int> digitArray; 210 211 while (n != 0) 212 { 213 digitArray.push_back(n % 10); 214 n /= 10; 215 } 216 217 std::reverse(digitArray.begin(), digitArray.end()); 218 219 return digitArray; 220 } 221 222 std::vector<int> EulerUtility::BigIntToDigits(cpp_int n) 223 { 224 std::vector<int> digitArray; 225 export_bits(n, std::back_inserter(digitArray), 32); 226 227 std::reverse(digitArray.begin(), digitArray.end()); 228 229 return digitArray; 230 } 231 232 int EulerUtility::digitsToInteger(std::vector<int> d) 233 { 234 std::stringstream ss; 235 236 for (int i : d) 237 ss << i; 238 239 int integer; 240 ss >> integer; 241 242 return integer; 243 } 244 245 llui EulerUtility::digitsTollui(std::string s) 246 { 247 std::stringstream ss; 248 249 for (char c : s) 250 ss << c; 251 252 llui digits; 253 ss >> digits; 254 255 return digits; 256 } 257 258 bool EulerUtility::hasUniqueDigits(int n, bool allowZero) 259 { 260 std::vector<int> digits = EulerUtility::intToDigits(n); 261 262 std::unordered_set<int> uniqueDigits; 263 264 for (int digit : digits) 265 { 266 if (digit == 0 && !allowZero) 267 return false; 268 269 uniqueDigits.insert(digit); 270 } 271 272 return digits.size() == uniqueDigits.size(); 273 } 274 275 /* 276 * calculates (a * b) % c taking into account that a * b might overflow 277 */ 278 ll mulmod(ll a, ll b, ll mod) 279 { 280 ll x = 0,y = a % mod; 281 while (b > 0) 282 { 283 if (b % 2 == 1) 284 x = (x + y) % mod; 285 286 y = (y * 2) % mod; 287 b /= 2; 288 } 289 290 return x % mod; 291 } 292 293 /* 294 * modular exponentiation 295 */ 296 ll modulo(ll base, ll exponent, ll mod) 297 { 298 ll x = 1; 299 ll y = base; 300 301 while (exponent > 0) 302 { 303 if (exponent % 2 == 1) 304 x = (x * y) % mod; 305 306 y = (y * y) % mod; 307 exponent = exponent / 2; 308 } 309 310 return x % mod; 311 } 312 313 /* 314 * Miller-Rabin primality test, iteration signifies the accuracy 315 */ 316 bool EulerUtility::isPrime(ll p, int iteration) 317 { 318 if ((p < 2) || (p != 2 && p % 2 == 0)) 319 return false; 320 321 ll s = p - 1; 322 323 while (s % 2 == 0) 324 s /= 2; 325 326 for (int i = 0; i < iteration; i++) 327 { 328 ll a = rand() % (p - 1) + 1, temp = s; 329 ll mod = modulo(a, temp, p); 330 331 while (temp != p - 1 && mod != 1 && mod != p - 1) 332 { 333 mod = mulmod(mod, mod, p); 334 temp *= 2; 335 } 336 337 if (mod != p - 1 && temp % 2 == 0) 338 return false; 339 } 340 341 return true; 342 } 343 344 bool EulerUtility::isTriangle(int n) 345 { 346 return std::floor(sqrt(2 * n + 0.25) - 0.5) == sqrt(2 * n + 0.25) - 0.5; 347 } 348 349 bool EulerUtility::isPentagonal(llui n) 350 { 351 return isPerfectSquare((24 * n) + 1) && ((llui)sqrt((24 * n) + 1) + 1) % 6 == 0; 352 } 353 354 std::vector<std::string> EulerUtility::openWordFile(std::string filename) 355 { 356 std::ifstream file; 357 std::vector<std::string> names; 358 std::string name; 359 file.open(filename); 360 361 while(getline(file, name, ',')) 362 names.push_back(name.substr(1, name.size() - 2)); 363 364 return names; 365 } 366 367 cpp_int EulerUtility::power(cpp_int i, int p) 368 { 369 if (p <= 0) 370 return 1; 371 372 return i * power(i, p - 1); 373 } 374 375 int EulerUtility::digitalRoot(int n) 376 { 377 std::vector<int> digits = intToDigits(n); 378 int digitSum = std::accumulate(digits.begin(), digits.end(), 0); 379 380 if (digitSum > 9) 381 return digitalRoot(digitSum); 382 383 return digitSum; 384 } 385 386 int EulerUtility::digitalRoot(cpp_int n) 387 { 388 std::vector<int> digits = BigIntToDigits(n); 389 int digitSum = std::accumulate(digits.begin(), digits.end(), 0); 390 391 if (digitSum > 9) 392 return digitalRoot(digitSum); 393 394 return digitSum; 395 } 396 397 std::vector<int> EulerUtility::intersect(std::vector<int>& a, std::vector<int>& b) 398 { 399 std::vector<int> v(a.size() + b.size()); 400 v.resize(std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), v.begin()) - v.begin()); 401 return v; 402 } 403 404 std::vector<int> EulerUtility::getFigurates(int sides, int floor, int ceiling) 405 { 406 std::vector<int> figurates; 407 408 if (sides < 3) 409 return figurates; 410 411 for (int i = 0; i < ceiling; ++i) 412 { 413 int figurate = (sides & 1) ? (i * ((i * (sides - 2)) + 4 - sides)) / 2 : i * ((((sides / 2) - 1) * i) - ((sides / 2) - 2)); 414 415 if (figurate >= floor && figurate < ceiling) 416 figurates.push_back(figurate); 417 418 if (figurate > ceiling) 419 return figurates; 420 } 421 422 return figurates; 423 } 424 425 llui EulerUtility::gcd(llui a, llui b) 426 { 427 while (b != 0) 428 { 429 llui t = b; 430 b = a % b; 431 a = t; 432 } 433 return a; 434 } 435 436 llui EulerUtility::phi(int n, std::vector<int> &primes, std::vector<int> &primesIndexed) 437 { 438 // Base case 439 if (n < 2) 440 return 0; 441 442 // Lehmer's conjecture 443 if (primesIndexed[n] != -1) 444 return n - 1; 445 446 // Even number? 447 if ((n & 1) == 0) 448 { 449 int m = n >> 1; 450 return !(m & 1) ? EulerUtility::phi(m, primes, primesIndexed) << 1 : EulerUtility::phi(m, primes, primesIndexed); 451 } 452 453 // For all primes ... 454 for (std::vector<int>::iterator p = primes.begin(); p != primes.end() && *p <= n; ++p) 455 { 456 int m = *p; 457 if (n % m) continue; 458 459 // phi is multiplicative 460 int o = n / m; 461 int d = EulerUtility::gcd(m, o); 462 return (d == 1) ? EulerUtility::phi(m, primes, primesIndexed) * EulerUtility::phi(o, primes, primesIndexed) : EulerUtility::phi(m, primes, primesIndexed) * EulerUtility::phi(o, primes, primesIndexed) * d / EulerUtility::phi(d, primes, primesIndexed); 463 } 464 465 return 0; 466 }