Here's a question that I'm hoping will improve my programming chops. I have this loop that is calculating a future sum based on annual payments, increased by interest and devalued by inflation (it's derived from the PV function in Excel):
var pmt = 66,449.75 // annual payment
var ip = 0.03 // interest rate
var fv = 0 // future value, not require here
var k = 1 // interest is applied at beginning / end of period
var n = 25 // number of periods (years in this case)
var ri = 0.025 // rate of inflation
var pv = 0;
for (var i = n - 1; i >= 0; i -= 1) {
pv = (pv + (pmt * k - fv) * Math.pow(1 + ri, i)) / (1 + ip);
}
Is it possible to use Math.pow() to reproduce what this loop is doing?
To simplify, I rename some expressions
a = pmt * k - fv;
b = 1 + ri;
c = 1 + ip;
x = pv;
So your code becomes
for (var i = n - 1; i >= 0; --i) {
x = x / c + a * Math.pow(b, i) / c;
}
Then
x_0
x_1 = x_0 / c + a b^{n-1} / c
x_2 = x_1 / c + a b^{n-2} / c = x_0 / c^2 + a b^{n-1} / c^2 + a b^{n-2} / c
...
x_i = x_{i-1} / c + a b^{n-i} / c = x_0 / c^i + \sum_{k=1}^i a b^{n-k} / c^{i-k+1}
...
x_n = x_0 / c^n + \sum_{k=1}^n a * b^{n-k} / c^{n-k+1}
According to WolframAlpha,
x_n = x_0 / c^n + a (b^n-c^n) / (c^n (b-c))
Therefore, instead of your loop you can use
var foo = Math.pow(1 + ip, n); // c^n
pv = pv / foo + (pmt*k-fv) * (Math.pow(1+ri,n) - foo) / foo / (ri-ip);
Related
This is sort of a silly question that's been bugging me.
I have a list of 100k numbers that I am calculating some statistics for. Specifically, I am computing the mean, minimum, maximum, and sum of these numbers. I'm doing it using a fold. In JavaScript:
// define folding functions:
let mean = (a, b, index, array) => a + b / array.length
let max = (a, b) => Math.max(a, b)
let min = (a, b) => Math.min(a, b)
let sum = (a, b) => a + b
let fold = initial => f => data =>
Math.round(data.reduce(f, initial))
// functions we can consume:
let averageDistance = fold(0)(mean)
let maxDistance = fold(-Infinity)(max)
let minDistance = fold(Infinity)(min)
let totalDistance = fold(0)(sum)
// compute stats:
let data = [1, 2, 3, ...]
let a = averageDistance(data)
let b = maxDistance(data)
let c = minDistance(data)
let d = totalDistance(data)
The time complexity of this is clearly O(n) for each statistic averageDistance, maxDistance, etc. Computed over all 4 statistics, the complexity is O(4n).
Now, I can instead compute all 4 statistics in a single loop, using either a transducer (a similar optimization to Haskell's fusion), or by inlining eveything into a for loop:
let a = 0
let b = -Infinity
let c = Infinity
let d = 0
for (let i = 0; i < data.length; i++) {
a = mean(a, averageDistance(data[i]), i, data)
b = max(b, maxDistance(data[i]))
c = min(c, minDistance(data[i]))
d = sum(d, totalDistance(data[i]))
}
This solution only does a single loop, so intuitively it does it in O(n) time (an improvement over 4n from before).
But it still does the same amount of work as before: (100k integers)*(4 statistics) = 400k computations.
Is one solution really faster than another? Is the difference in space complexity (not in time)? If no to both of these, why bother with transducers or fusion at all?
This function:
Stats_A(array[1...n])
sum = 0
for i = 1 to n do
sum = sum + array[i]
avg = 0
for i = 1 to n do
avg = avg + array[i]
avg = avg / n
min = array[1]
for i = 1 to n do
if array[i] < min then
min = array[i]
max = array[1]
for i = 1 to n do
if array[i] > max then
max = array[i]
return (sum, avg, min, max)
And this function:
Stats_B(array[1...n])
sum = 0
min = max = array[1]
for i = 1 to n do
sum = sum + array[i]
if array[i] < min then
min = array[i]
else if array[i] > max then
max = array[i]
return (sum, sum / n, min, max)
Both have the same linear time complexity O(n). We can assign costs to basic operations and work out more details expressions for the time complexities of these functions, and then we will find that Stats_A does more work than Stats_B, but not asymptotically more work. We can let:
memory accesses (read/write) take time a
+, -, *, / take time b, c, d, e, respectively
comparisons (<, >, =) take time f
Now we can compute the more detailed runtime expressions:
This function:
Stats_A(array[1...n])
sum = 0 // a
for i = 1 to n do // a + n * (f + b + a)
sum = sum + array[i] // n * (2 * b + 3 * a)
// = (2 + 4 * n) * a
// + ( 3 * n) * b
// + ( 1 * n) * f
avg = 0 // a
for i = 1 to n do // a + n * (f + b + a)
avg = avg + array[i] // n * (2 * b + 3 * a)
avg = avg / n // 3 * a + e
// = (5 + 4 * n) * a
// + ( 3 * n) * b
// + ( 1 * n) * f
// + (1 ) * e
min = array[1] // 2 * a + b
for i = 1 to n do // a + n * (f + b + a)
if array[i] < min then // n * (2 * a + b + f)
min = array[i] // n * (2 * a + b)
// = (3 + 5 * n) * a
// + (1 + 3 * n) * b
// + ( 2 * n) * f
max = array[1] // 2 * a + b
for i = 1 to n do // a + n * (f + b + a)
if array[i] > max then // n * (2 * a + b + f)
max = array[i] // n * (2 * a + b)
// = (3 + 5 * n) * a
+ (1 + 3 * n) * b
+ ( 2 * n) * f
return (sum, avg, min, max) // = (5 ) * a
// total: (13 + 18 * n) * a
// + ( 2 + 12 * n) * b
// + ( 1 ) * e
// + ( 6 * n) * f
// = n * (18a + 12b + 6f) + (13a + 2b + e)
And this function:
Stats_B(array[1...n])
sum = 0 // a
min = max = array[1] // 3a + b
for i = 1 to n do // a + n * (f + b + a)
sum = sum + array[i] // n * (3 * a + 2 * b)
if array[i] < min then // n * (b + 2 * a + f)
min = array[i] // n * (b + 2 * a)
else if array[i] > max then // n * (b + 2 * a + f)
max = array[i] // n * (b + 2 * a)
return (sum, sum / n, min, max) // 5a + e
// total: ( 9 + 12 * n) * a
+ ( 1 + 7 * n) * b
+ ( 1 ) * e
+ ( 3 * n) * f
= n * (12a + 7b + 3f) + (9a + b + e)
The first function takes strictly longer than the second function; in the limit, the ratio of their runtimes approaches the quotient of their slopes:
(18a + 12b + 6f) / (12a + 7b + 3f)
We can observe that the denominator is strictly less than 2/3 of the numerator; therefore, the ratio is strictly greater than 3/2. We would expect, for any given input, Stats_A to take an amount approaching 50% longer than Stats_B as the input size increases without bound.
I'm experimenting with canvas and I'm trying to modify this piece of code, but unfortunately I don't understand some parts of it.
My question is - how to customize the above code to be defined for example by
f(z) = c^e(-z)
(the formula is taken from a book with fractal examples)?
I know that I need to change this part of code:
function computeRow(task) {
var iter = 0;
var c_i = task.i;
var max_iter = task.max_iter;
var escape = task.escape * task.escape;
task.values = [];
for (var i = 0; i < task.width; i++) {
var c_r = task.r_min + (task.r_max - task.r_min) * i / task.width;
var z_r = 0, z_i = 0;
for (iter = 0; z_r*z_r + z_i*z_i < escape && iter < max_iter; iter++) {
// z -> z^2 + c
var tmp = z_r*z_r - z_i*z_i + c_r;
z_i = 2 * z_r * z_i + c_i;
z_r = tmp;
}
if (iter == max_iter) {
iter = -1;
}
task.values.push(iter);
}
return task;
}
But can't what z_i, z_r, c_i, c_r really means and how I could bind them to the above formula.
Any help would be greatly appreciated.
Complex number have a two part: real, imaginary.
So z = a + b*i, where a is real part, and b*i is imaginary.
In provided sample for z=z^2+c, where z=z_r+z_i*i
NOTE: i*i = -1
So z^2 = (z_r+z_i*i)*(z_r+z_i*i) = z_r*z_r+2*z_r*z_i*i + z_i*i*z_i*i = z_r*z_r+2*z_r*z_i*i - z_i*z_i
now add c: z_r*z_r+2*z_r*z_i*i - z_i*z_i + c_r + c_i*i group it
z_r*z_r+2*z_r*z_i*i - z_i*z_i + c_r + c_i*i = (z_r*z_r - z_i*z_i + c_r) + (2*z_r*z_i + c_i)*i
So we get tmp var from code - is real part of new z
tmp = z_r*z_r - z_i*z_i + c_r
and imaginary part
2*z_r*z_i + c_i
Since z = z_r + z_i * i, we need assign
z_r = z_r*z_r - z_i*z_i + c_r
z_i = 2*z_r*z_i + c_i
UPDATE: for f(z) = e^z - c
first, few complex form: x = a+b*i = |x|(cos(p)+i*sin(p)) = |x|*e^(i*p)
where |x| = sqrt(a*a + b*b) and p = b/a
in our case: p=z_i/z_r, |z| = sqrt(z_r*z_r+z_i*z_i)
e^z = e^(z_r+z_i*i) = e^z_r * (e^z_i*i) = e^z_r * (cos(p)+i*sin(p)) = (e^z_r * cos(p)) + i * (e^z_r * sin(p))
subtract c:
(e^z_r * cos(p)) + i * (e^z_r * sin(p)) - c_r - c_i*i = (e^z_r * cos(p) - c_r) + i * (e^z_r * sin(p) - c_i)
so new z
z_r = (e^z_r * cos(p) - c_r) = (e^z_r * cos(z_i/z_r) - c_r)
z_i = (e^z_r * sin(p) - c_i) = (e^z_r * sin(z_i/z_r) - c_i)
I have the following code:
var marketReturns = [1];
var marketReturnsVol = [1];
var marketVolatility = [1];
var yearlyReturns = [];
var yearlyReturns2 = [];
for (y = 0; y < 50000; y++) {
for (x = 1; x <= 251; x++) {
do {
var rand1 = Math.random();
var rand2 = Math.random();
var x1 = 2.0 * rand1 - 1.0;
var x2 = 2.0 * rand2 - 1.0;
var w = Math.pow(x1, 2) + Math.pow(x2, 2);
} while (w === 0 || w > 1);
multiplier = Math.sqrt((-2 * Math.log(w)) / w);
var volVol = 1 + (((x2 * multiplier) / 100) * 5.98); // real ^VIX is 5.98.
marketVolatility[x] = volVol * marketVolatility[x - 1];
var y1 = 1 + (((x1 * multiplier) / 100) * 1.07); // 1.07 is the daily vol of ^GSPC
var y12 = 1 + (((x1 * multiplier) / 100) * 1.07 * marketVolatility[x]) + 0.00038; // 1.07 is the daily vol of ^GSPC
marketReturns[x] = y1 * marketReturns[x - 1];
marketReturnsVol[x] = y12 * marketReturnsVol[x - 1];
}
yearlyReturns[y] = marketReturns[251];
yearlyReturns2[y] = marketReturnsVol[251];
}
yearlyReturns.sort(function (a, b) {
return (a - b);
})
yearlyReturns2.sort(function (a, b) {
return (a - b);
})
for (x = 0; x < yearlyReturns.length; x++) {
document.write(yearlyReturns2[x] + ", ");
}
So essentially I am calculating marketReturns, which is marketReturns[x-1] * daily change. I want however to make this into subarrays where I can preserve all the individual marketReturns for each iteration of y instead of just preserving the last day like I am in yearlyReturns[y].
I thought I could do it as such:
marketReturns[y][x] = y1 * marketReturns[y][x - 1];
marketReturnsVol[y][x] = y12 * marketReturnsVol[y][x - 1];
But this doesn't work. Is there any way for me to start writing the marketReturns figures into subarrays? Thanks.
You can mimic the multidimensional array using nested array/nested object in javascript:
e.g.
var arr = [];
//Initialize a 10x10 "multidimensional" array
for(var i = 0; i < 10; i++) {
arr[i] = [];
for(var j = 0; j < 10; j++) {
arr[i][j] = 0;
}
}
//Store
arr[5][5] = 10;
I want to convert the RGB Color to an indexed color, here is my code, it works. But although some colors are converted to blue or red, but others that look like blue or red got converted to gray. How to fix this? You can check my snippet, click the color from big table and see the results down there.
var palette = [0, 0xff0000, 0xff00, 0xffff00, 0xff, 0xff00ff, 0xffff, 0x808080]
function rgb(c) {
return [c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff]
}
// http://alienryderflex.com/hsp.html
function rgb2lum(r, g, b) {
return Math.sqrt(Pr * r * r + Pg * g * g + Pb * b * b)
}
var Pr = .2126,
Pg = .7152,
Pb = .0722;
var rd = 255,
gd = 255,
bd = 255,
maxDist = Math.sqrt(Pr * rd * rd + Pg * gd * gd + Pb * bd * bd);
function colorDist(a, b) {
a = rgb(a), b = rgb(b)
var rd = b[0] - a[0],
gd = b[1] - a[1],
bd = b[2] - a[2]
return Math.sqrt(Pr * rd * rd + Pg * gd * gd + Pb * bd * bd) / maxDist
}
function randomColor() {
var r = Math.floor(Math.random() * 256)
var g = Math.floor(Math.random() * 256)
var b = Math.floor(Math.random() * 256)
var c = (r + (g << 8) + (b << 16))
return c
}
function hex(c) {
c = c.toString(16)
while (c.length < 6) c = '0' + c
return '#' + c
}
function f(a) {
var id = -1,
val = 2
for (var i = 0; i < palette.length; i++) {
var c = palette[i],
d = colorDist(a, c)
if (d < val) id = i, val = d
}
out.innerHTML += ('<span style="border:1px solid black"><span style=background:' + hex(a) + '>      </span><span style=background:' + hex(palette[id]) + '>      </span></span>, ')
}
var W = 60,
H = 10
var s = '<table border=0 cellspacing=0 style=cursor:pointer>'
for (var y = 0; y < H; y++) {
s += '<tr>'
for (var x = 0; x < W; x++) {
var c = randomColor()
s += '<td style="background:' + hex(c) + '" onclick=f(' + c + ')> </td>'
}
s += '</tr>'
}
s += '</table>'
s += 'palette:<table border=1><tr>'
for (var x = 0; x < palette.length; x++) {
s += '<td style="background:' + hex(palette[x]) + '" onclick=f(' + palette[x] + ')> </td>'
}
s += '</tr></table>'
out.innerHTML = s
<span id=out></span>
It looks like you have your rgb arrays reversed.
function rgb(c) {
return [c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff]
}
rgb() produces an array of [b,g,r] and your HSP math assumes the returned array is [r,g,b]:
function colorDist(a, b) {
a = rgb(a), b = rgb(b) // <--- produces [b,g,r] arrays
var rd = b[0] - a[0], // <--- red is index 0
gd = b[1] - a[1],
bd = b[2] - a[2]
return Math.sqrt(Pr * rd * rd + Pg * gd * gd + Pb * bd * bd) / maxDist
}
This would seem to throw off the intended brightness calculations.
I'm trying to solve the Project Euler Problem 9 :
A Pythagorean triplet is a set of three natural numbers, a < b < c,
for which, a2 + b2 = c2
For example, 32 + 42 = 9 + 16 = 25 = 52.
There exists exactly one Pythagorean triplet for which a + b + c =
1000. Find the product abc.
I looked on Wikipedia for the formula to find Pythagorean triples and tried to translate it into code. The problem is that the code is outputting the wrong answer, but I think that the code is correct.
var a, b, c;
var pos1, pos2, pos3;
var ans1, ans2, ans3;
for(var n=2; n<=20000; n++) {
a = 2 * n + 1;
b = 2 * n * (n +1);
c = 2 * n * (n +1) + 1;
if(a<b<c) {
if(a^2 + b^2 === c^2) {
pos1 = a;
pos2 = b;
pos3 = c;
}
if(a + b + c ===1000) {
ans1 = a;
ans2 = b;
ans3 = c;
}
}
}
console.log(ans1 + " " + ans2 + " " + ans3);
This is a solution
var a;
var c;
for (var b = 1; b < 1000; b += 1) {
a = (500000 - 1000 * b) / (1000 - b);
if (Math.floor(a) === a) {
c = 1000 - a - b;
break;
}
}
console.log(a, b, c);
Result is 375 200 425
on jsfiddle
Pythagoras
a2 + b2 = c2
Also we have
a + b + c = 1000
algebra, rearrange c to left
c = 1000 - (a + b)
insert c back in pythagoras
a2 + b2 = (1000 - (a + b))2
multiply out
a2 + b2 = 1000000 - 2000 * (a + b) + (a + b)2
multiply out
a2 + b2 = 1000000 - 2000 * (a + b) + a2 + 2 * a * b + b2
rearrange a2 + b2 to simplify
0 = 1000000 - 2000 * (a + b) + 2 * a * b
rearrange unknowns to left
2000 * (a + b) - 2 * a * b = 1000000
simplify, / 2
1000 * (a + b) - a * b = 500000
factorsize
a(1000 - b) + 1000 * b = 500000
rearrange
a(1000 - b) = 500000 - 1000 * b
a = (500000 - 1000 * b) / (1000 - b)
now input b, calculate a and test if a is an integer as required by Pythagorean Triples
TGarr, here is an explanation to Xotic750's answer.
I don't really understand how you created the algorithm. Why is a = to (500000 - 1000 * b) / (1000 - b) ...
He started with a^2 + b^2 = c^2, and a + b + c = 1000, and combined them because the problem on projecteuler states that there is only 1 set of numbers where both of these statments will be true. Here's how he combined them. He solved the second equation for c to be c = 1000 - (a + b). Then he plugged that into the first equation so that it became a^2 + b^2 = (1000 - (a + b))^2. He continued until he was able to solve the entire equation for a. Once he was able to do that, he was able to make a single for loop that increases b, which is much simpler and more elegant than many other options.
why is the if statement's conditions set to Math.floor(a) === a?
This just means "is a, rounded down to its nearest integer, the same as a?" In other words, is a an integer? (copy his code, and add console.log ( a ); above the if statement. That might help you understand that bit of code) Since he was able to solve the equation for a, all he had to do was plug in different numbers for b, and as soon as the outcome was an integer, he'd have the answer. Or at least he'd know what a and b c = 1000 - a - b; tells him what c is, and that's all she wrote.
Here is another solution with less code:
for(var a = 1; a < 500; a++){
for(var b = a; b < 1000; b++){
var c = Math.sqrt(a * a + b * b);
if(c > b && Number.isInteger(c) && a + b + c == 1000){
console.log(a * b * c);
}
}
}
The result is: 31875000 :)
You can't calculate powers like that.
Use Math.pow(a,2) to calculate a^2
var a, b, c;
var pos1, pos2, pos3;
var ans1, ans2, ans3;
for(var n=2; n<=20000; n++) {
a = 2 * n + 1;
b = 2 * n * (n +1);
c = 2 * n * (n +1) + 1;
if(a<b<c) {
if(Math.pow(a,2) + Math.pow(b,2) === Math.pow(c,2)) {
pos1 = a;
pos2 = b;
pos3 = c;
}
if(a + b + c ===1000) {
ans1 = a;
ans2 = b;
ans3 = c;
}
}
}
console.log(ans1 + " " + ans2 + " " + ans3);
eq 1 : a2 + b2 = c2
eq 2 : a + b + c = 1000
From eq 1 and eq 2 we can have
eq 3 : c = 1000 - a - b
Substitute the value of c from eq 3 into eq 1 we get :
eq 4 : a2 + b2 = (1000 - a - b)2
R.H.S of eq 4 is a trinomial squared. We know that square of a trinomial of such kind is
(a - b - c)2 = a2 + b2 + c2 – 2ab + 2bc – 2ca
We get :
a2 + b2 = 10002 + a2 + b2 – 2*1000*a + 2*a*b – 2*b*1000
Now we simplify to get a to the L.H.S
a = (10002 - 2*1000*b)/(2*1000*b)
Now I can use this to find out value of a where it is an integer and then use Math.sqrt( aa + bb ) to calculate the value of c. Then I can check if a+b+c==1000 holds to be true.
My solution:
public class ProjectEuler9 {
public static void main(String[] args) {
long start = System.nanoTime();
double a;
for(int b=1; b<1000; b++){
a = ( (Math.pow(1000, 2) - 2000*b ) / (2000- 2*b) );
if(Math.floor(a) == a) {
// a is an integer
double c = Math.sqrt((a*a + b*b));
System.out.println("a : " + a + " b :" + b + " c : " + c);
long product = (long) (a*b*c);
System.out.println("product abc : " + product);
break;
} else {
//a is not an integer.
}
}
long stop = System.nanoTime();
System.out.println("\nTime: " + (stop - start) / 1000 + " ns");
}
}
Output :
a : 375.0 b :200 c : 425.0
product abc : 31875000
Time: 3714 ns