<< problem 240 - Top Dice | Squares under a hyperbola - problem 247 >> |

# Problem 243: Resilience

(see projecteuler.net/problem=243)

A positive fraction whose numerator is less than its denominator is called a proper fraction.

For any denominator, d, there will be d-1 proper fractions; for example, with d=12:

1/12 , 2/12 , 3/12 , 4/12 , 5/12 , 6/12 , 7/12 , 8/12 , 9/12 , 10/12 , 11/12 .

We shall call a fraction that cannot be cancelled down a resilient fraction.

Furthermore we shall define the resilience of a denominator, R(d), to be the ratio of its proper fractions that are resilient;

for example, R(12) = 4/11 .

In fact, d = 12 is the smallest denominator having a resilience R(d) < 4/10 .

Find the smallest denominator d, having a resilience R(d) < 15499/94744 .

# My Algorithm

If a fraction is *not* a proper fraction then gcd(numerator, denominator) > 1, that means both can be divided by the same integer.

The Euler totient function phi(x) returns how many numbers 0 < y < x are relatively prime to x.

phi(12) = 4 because 12 is relatively prime to 1, 5, 7 and 11.

And indeed, 1/12, 5/12, 7/12 and 11/12 are the only proper fraction where the denominator is 12.

Therefore the program should find a denominator d such that

dfrac{phi(d)}{d-1} < dfrac{15499}{94744}

The code of my `phi()`

function is shared with problem 214 (and was originally written for problem 70).

I had to change it's parameter type from `unsigned int`

to `unsigned long long`

but everything else is identical to problem 214.

Unfortunately it's much too slow to check every single number, beginning with 12 (hint: the correct solution is a nine-digit number).

But I did exactly that "to get a feeling" - and obviously stopped after a few hundred numbers.

It turns out that phi(x)/(x-1) is low when x is the product of the first n prime numbers: x_n = 2 * 3 * 5 * 7 * ....

My current implementation multiplies all prime numbers until phi(x_n)/(x_n-1) is smaller than 15499/94744 (x_n is my variable `current`

).

Then it reverts the last step (now phi(x_{n-1})/(x_{n-1}-1) is bigger than 15499/94744). `current`

is updated to hold x_{n-1}.

And finally all multiples of x_{n-1} (→ `current`

) are compared against the ratio until it's below 15499/94744.

I consider the last step to be a "lucky guess". Yes, it produces the correct result but my mathematical knowledge isn't sufficient to know why.

# My code

… was written in C++11 and can be compiled with G++, Clang++, Visual C++. You can download it, too.

#include <iostream>
#include <vector>
std::vector<unsigned int> primes;
// return phi(x) if x/phi(x) <= minQuotient (else the result is undefined but > minQuotient)

unsigned long long phi(unsigned long long x)
{
// totient function can be computed by finding all prime factors p
// and subtracting them from x
auto result = x;
auto reduced = x;
for (auto p : primes)
{
// prime factors have to be p <= sqrt
if (p*p > reduced)
break;
// not a prime factor ...
if (reduced % p != 0)
continue;
// prime factors may occur multiple times, remove them all
do
{
reduced /= p;
} while (reduced % p == 0);
// but subtract from result only once
result -= result / p;
}
// we only checked prime factors <= sqrt(x)
// there might exist one (!) prime factor > sqrt(x)
// e.g. 3 is a prime factor of 6, and 3 > sqrt(6)
if (reduced > 1)
result -= result / reduced;
return result;
}
// return true if a1/b1 < a2/b2

bool isLess(unsigned long long a1, unsigned long long b1, unsigned long long a2, unsigned long long b2)
{
// a1/b1 < a2/b2 is the same as
// a1*b2 < a2*b1 if all numbers are positive
return a1*b2 < a2*b1;
}
int main()
{
unsigned int numerator = 15499;
unsigned int denominator = 94744;
unsigned long long current = 1;
for (unsigned int i = 2; ; i++)
{
bool isPrime = true;
// test against all prime numbers we have so far (in ascending order)
for (auto p : primes)
{
// next prime is too large to be a divisor ?
if (p*p > i)
break;
// divisible ? => not prime
if (i % p == 0)
{
isPrime = false;
break;
}
}
if (!isPrime)
continue;
// yes, we have a prime number
primes.push_back(i);
// multiply prime numbers until the ratio becomes too small
current *= i;
if (isLess(phi(current), current - 1, numerator, denominator))
break;
}
// undo last prime
current /= primes.back();
// simple iterative scan
for (unsigned int i = 1; ; i++)
{
auto next = current * i;
// below threshold ?
if (isLess(phi(next), next - 1, numerator, denominator))
{
std::cout << next << std::endl;
break;
}
}
return 0;
}

This solution contains 19 empty lines, 21 comments and 2 preprocessor commands.

# Interactive test

*This feature is not available for the current problem.*

# Benchmark

The correct solution to the original Project Euler problem was found in less than 0.01 seconds on a Intel® Core™ i7-2600K CPU @ 3.40GHz.

(compiled for x86_64 / Linux, GCC flags: `-O3 -march=native -fno-exceptions -fno-rtti -std=c++11 -DORIGINAL`

)

See here for a comparison of all solutions.

**Note:** interactive tests run on a weaker (=slower) computer. Some interactive tests are compiled without `-DORIGINAL`

.

# Changelog

June 19, 2017 submitted solution

June 19, 2017 added comments

# Difficulty

Project Euler ranks this problem at **35%** (out of 100%).

# Links

projecteuler.net/thread=243 - **the** best forum on the subject (*note:* you have to submit the correct solution first)

Code in various languages:

Java: github.com/nayuki/Project-Euler-solutions/blob/master/java/p243.java (written by Nayuki)

# Heatmap

green problems solve the original Project Euler problem and have a perfect score of 100% at Hackerrank, too.

yellow problems score less than 100% at Hackerrank (but still solve the original problem).

gray problems are already solved but I haven't published my solution yet.

blue problems are solved and there wasn't a Hackerrank version of it at the time I solved it or I didn't care about it because it differed too much.

red problems are solved but exceed the time limit of one minute or the memory limit of 256 MByte.

*Please click on a problem's number to open my solution to that problem:*

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |

26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |

51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |

76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 |

101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 |

126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 |

151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 |

176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 |

201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 |

226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 |

251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 |

276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 |

301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 |

326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 |

351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 |

376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 |

401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 |

426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 |

451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 |

476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 |

501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 |

526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 |

I scored 13,183 points (out of 15300 possible points, top rank was 17 out of ≈60000 in August 2017) at Hackerrank's Project Euler+.

Look at my progress and performance pages to get more details.

My username at Project Euler is

**stephanbrumme**while it's stbrumme at Hackerrank.

# Copyright

I hope you enjoy my code and learn something - or give me feedback how I can improve my solutions.

All of my solutions can be used for any purpose and I am in no way liable for any damages caused.

You can even remove my name and claim it's yours. But then you shall burn in hell.

The problems and most of the problems' images were created by Project Euler.

Thanks for all their endless effort.

<< problem 240 - Top Dice | Squares under a hyperbola - problem 247 >> |