2

I've a strange thing to do but I don't know how to start

I start with this vars

var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1];

So to start all the 3 array have the same length and the very first operation is to see if there is a duplicate value in sky array, in this case the 0 is duplicated and only in this case is at the end, but all of time the sky array is sorted. So I've to remove all the duplicate (in this case 0) from sky and remove the corresponding items from base and sum the corresponding items on ite. So if there's duplicate on position 4,5 I've to manipulate this conditions. But let see the new 3 array:

var new_base = [1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var new_sky = [0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var new_ite = [139,38,13,15,6,4,6,3,2,1,2,1,1,1];

If you see the new_ite have 139 instead the 64,52,23, that is the sum of 64+52+23, because the first 3 items on sky are the same (0) so I remove two corresponding value from base and sky too and I sum the corresponding value into the new_ite array.

There's a fast way to do that? I thought a for loops but I stuck at the very first for (i = 0; i < sky.length; i++) lol, cuz I've no idea on how to manipulate those 3 array in that way

J

Jorman Franzini
  • 289
  • 2
  • 13
  • Does time matter on this? Will it be used on HUGE arrays? Are there memory constraints(Can we duplicate the array to quick sort it?)? – Grallen Jan 05 '17 at 19:24
  • 1
    Do you have to work with these arrays provided? Or can you change how these arrays are stored and represented? If these arrays are really related to each other in the way that you are describing it might make more sense to have a single array of objects and each object would have a base value, sky value, and ite value. – TJ Rockefeller Jan 05 '17 at 19:36
  • Is the array always presorted? – Grallen Jan 05 '17 at 19:49
  • @Grallen arr sky and base are always sorted and performance is important for me, but huge array no, maybe 100 or 200 items max. for tj-rockefeller I can duplicate, those array are related each other but is populated in 3 different actions and part of code. – Jorman Franzini Jan 05 '17 at 20:08

5 Answers5

2

When removing elements from an array during a loop, the trick is to start at the end and move to the front. It makes many things easier.

for( var i = sky.length-1; i>=0; i--) {
    if (sky[i] == prev) {
        // Remove previous index from base, sky
        // See http://stackoverflow.com/questions/5767325/how-to-remove-a-particular-element-from-an-array-in-javascript
        base.splice(i+1, 1);
        sky.splice(i+1, 1);

        // Do sum, then remove
        ite[i] += ite[i+1];
        ite.splice(i+1, 1);
    }
    prev = sky[i];
}

I won't speak to whether this is the "fastest", but it does work, and it's "fast" in terms of requiring little programmer time to write and understand. (Which is often the most important kind of fast.)

alttag
  • 1,029
  • 2
  • 10
  • 26
0

atltag's answer is fastest. Please see:

https://repl.it/FBpo/5

Grallen
  • 1,459
  • 1
  • 13
  • 16
  • Tnx for this, but why start with the new array? – Jorman Franzini Jan 05 '17 at 20:19
  • I figured the new arrays were copies to protect the original data. What I did here was destructive to the arrays; – Grallen Jan 05 '17 at 20:33
  • You said speed is important(like you might be running this many times per second). I think it's faster to build new arrays than to split multiple times. I'm going to test then update my answer. – Grallen Jan 05 '17 at 20:35
  • Not many time for second but I've a small ammount of time to do all! Btw, your script start with the solution array, not with the starting one – Jorman Franzini Jan 05 '17 at 20:42
  • New fast answer posted. – Grallen Jan 05 '17 at 21:14
  • Tnx for your reply, if I'm not wrong your solution is good but not the fastest, see this speed test https://repl.it/FBnH/1 your is on option3, right now the alttag is the fastest one. If I'm not wrong – Jorman Franzini Jan 05 '17 at 21:29
  • The speed test is not entirely fair, as my solution edits in place, rather than creating new variables (which isn't correct for when the test runs option 3), and also means there are no new arrays created on successive runs of my solution. – alttag Jan 05 '17 at 22:08
  • One simple place for speedup is avoiding having to dereference `.length` each iteration. Going backward avoids this. – alttag Jan 05 '17 at 22:10
  • Yes his does seem faster. I'm going to verify my logic. I may have made a mistake. My initial tests of split vs building a new array showed a big advantage to building a new array. I'll verify and then edit my answer. – Grallen Jan 05 '17 at 22:11
  • All I meant is that the speed test is borked, and goosed in my favor (as no changes to the array occur on successive runs), not that my solution was necessarily faster. The test would likely give different results if the modified-in-place arrays were reset before each run. – alttag Jan 05 '17 at 22:23
  • I believe your answer is faster. I think I created a fair test and I think my code is optimal. See the link in my answer. – Grallen Jan 05 '17 at 22:54
0

I would suggest this solution where j is used as index for the new arrays, and i for the original arrays:

var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1];

var new_base = [], new_sky = [], new_ite = [];

var j = -1;
sky.forEach(function (sk, i) {
    if (!i || sk !== sky[i-1]) {
        new_ite[++j] = 0;
        new_base[j] = base[i];
        new_sky[j] = sk;
    }
    new_ite[j] += ite[i];
});

console.log('new_base = ' + new_base);
console.log('new_sky = ' + new_sky);
console.log('new_ite = ' + new_ite);
trincot
  • 211,288
  • 25
  • 175
  • 211
0

You can use Array#reduce to create new arrays from the originals according to the rules:

var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1];

var result = sky.reduce(function(r, n, i) {
  var last = r.sky.length - 1;
  
  if(n === r.sky[last]) {
    r.ite[last] += ite[i];
  } else {
    r.base.push(base[i]);
    r.sky.push(n);
    r.ite.push(ite[i]);
  }
  
  return r;
}, { base: [], sky: [], ite: [] });

console.log('new base:', result.base.join(','));
console.log('new sky:', result.sky.join(','));
console.log('new ite:', result.ite.join(','));
Ori Drori
  • 145,770
  • 24
  • 170
  • 162
0

Just with a single .reduce() in O(n) time you can do as follows; (I have used array destructuring at the assignment part. One might choose to use three .push()s though)

var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330],
     sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17],
     ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1],
 results = sky.reduce((r,c,i) => c === r[1][r[1].length-1] ? (r[2][r[2].length-1] += ite[i],r)
                                                           : ([r[0][r[0].length],r[1][r[1].length],r[2][r[2].length]] = [base[i],c,ite[i]],r),[[],[],[]]);
console.log(JSON.stringify(results));
Redu
  • 19,106
  • 4
  • 44
  • 59
  • 1
    Tnx, I always love your solutions :D – Jorman Franzini Jan 06 '17 at 17:05
  • All of the solutions thus far have been O(n). – alttag Jan 06 '17 at 19:14
  • @alttag Honestly, i wasn't checking the other answers.. But looking into your answer... So you believe three cascaded `.splice(x,1)`s, yet alone one, is O(1) operation..? – Redu Jan 06 '17 at 19:23
  • You got me; I was ignoring the cost of `splice()`. Still, it would depend greatly on the internals of the particular Javascript engine. [This answer](http://stackoverflow.com/a/11535121/1327983) suggests `splice()` is O(n), but a comment on it suggests O(1). Deleting is certainly O(1), the O(n) complexity would come in index reassignment, albeit with a very low constant modifier in practice. If the goal were low O(), one could set values to null instead of deleting/reassigning, then recreate, thus O(2n) = O(n), but that sounds slower. I like the elegance of your answer, btw. – alttag Jan 06 '17 at 19:41