2018-09-30 23:01:58 +01:00
---
id: 5900f53a1000cf542c51004c
title: 'Problem 461: Almost Pi'
2020-11-27 19:02:05 +01:00
challengeType: 5
2019-08-05 09:17:33 -07:00
forumTopicId: 302136
2021-01-13 03:31:00 +01:00
dashedName: problem-461-almost-pi
2018-09-30 23:01:58 +01:00
---
2020-11-27 19:02:05 +01:00
# --description--
2021-03-10 07:14:27 -08:00
Let `f(k, n)` = $e^\frac{k}{n} - 1$, for all non-negative integers `k` .
2020-11-27 19:02:05 +01:00
2021-03-10 07:14:27 -08:00
Remarkably, `f(6, 200) + f(75, 200) + f(89, 200) + f(226, 200)` = 3.1415926… ≈ π.
2020-11-27 19:02:05 +01:00
2021-03-10 07:14:27 -08:00
In fact, it is the best approximation of π of the form `f(a, 200) + f(b, 200) + f(c, 200) + f(d, 200)` .
2020-11-27 19:02:05 +01:00
2021-03-10 07:14:27 -08:00
Let `almostPi(n)` = a< sup > 2</ sup > + b< sup > 2</ sup > + c< sup > 2</ sup > + d< sup > 2</ sup > for a, b, c, d that minimize the error: $\lvert f(a,n) + f(b,n) + f(c,n) + f(d,n) - \Pi\rvert$
2020-11-27 19:02:05 +01:00
2021-03-10 07:14:27 -08:00
You are given `almostPi(200)` = 6< sup > 2</ sup > + 75< sup > 2</ sup > + 89< sup > 2</ sup > + 226< sup > 2</ sup > = 64658.
2018-09-30 23:01:58 +01:00
2021-03-10 07:14:27 -08:00
# --hints--
2018-09-30 23:01:58 +01:00
2021-03-10 07:14:27 -08:00
`almostPi` should be a function.
2018-09-30 23:01:58 +01:00
2021-03-10 07:14:27 -08:00
```js
assert(typeof almostPi === 'function')
```
`almostPi` should return a number.
2018-09-30 23:01:58 +01:00
2021-03-10 07:14:27 -08:00
```js
assert.strictEqual(typeof almostPi(10), 'number');
```
`almostPi(29)` should return `1208` .
2018-09-30 23:01:58 +01:00
2020-11-27 19:02:05 +01:00
```js
2021-03-10 07:14:27 -08:00
assert.strictEqual(almostPi(29), 1208);
```
`almostPi(50)` should return `4152` .
```js
assert.strictEqual(almostPi(50), 4152);
```
`almostPi(200)` should return `64658` .
```js
assert.strictEqual(almostPi(200), 64658);
2018-09-30 23:01:58 +01:00
```
2020-11-27 19:02:05 +01:00
# --seed--
2018-09-30 23:01:58 +01:00
2020-11-27 19:02:05 +01:00
## --seed-contents--
2018-09-30 23:01:58 +01:00
```js
2021-03-10 07:14:27 -08:00
function almostPi(n) {
2018-09-30 23:01:58 +01:00
return true;
}
```
2020-11-27 19:02:05 +01:00
# --solutions--
2018-09-30 23:01:58 +01:00
```js
2021-03-10 07:14:27 -08:00
function almostPi(n) {
// Find all possible values where f(k, n) < = PI
const f = [];
let max = 0;
while (1) {
let current = Math.exp(max / n) - 1;
if (current > Math.PI) break;
f.push(current);
++max;
}
// Get all pairs where f[i] + f[j] < = PI
const pairs = [];
for (let i = 0; i < max ; + + i ) {
for (let j = 0; j < max ; + + j ) {
if (f[i] + f[j] > Math.PI) break;
pairs.push(f[i] + f[j]);
}
}
// Sort all values
pairs.sort((a, b) => a - b);
// Optimal Value for (a + b)
let left = 0;
// Optimal Value for (c + d)
let right = 0;
// minimum error with Math.abs(a + b - Math.PI)
let minError = Math.PI;
// Binary Search for the best match
for (let i = 0; i < pairs.length ; + + i ) {
let current = pairs[i];
let need = Math.PI - current;
if (need < current ) break ;
let match;
for (let i = 1; i < pairs.length ; + + i ) {
if (pairs[i] > need) {
match = i;
break;
}
}
let error = Math.abs(need - pairs[match]);
if (error < minError )
{
minError = error;
left = i;
right = match;
}
--match;
error = Math.abs(need - pairs[match]);
if (error < minError ) {
minError = error;
left = i;
right = match;
}
}
let a, b, c, d;
OuterLoop1:
for (a = 0; a < max ; + + a ) {
for (b = a; b < max ; + + b ) {
if (pairs[left] == f[a] + f[b]) {
break OuterLoop1;
}
}
}
OuterLoop2:
for (c = 0; c < max ; + + c ) {
for (d = c; d < max ; + + d ) {
if (pairs[right] == f[c] + f[d]) {
break OuterLoop2;
}
}
}
return a*a + b*b + c*c + d*d;
}
2018-09-30 23:01:58 +01:00
```