Luke
Luke

Reputation: 3551

What is the most efficient way to check for a sequence of numbers in a JavaScript array?

Background

For a technical interview I was tasked with implementing a missing algorithm in JavaScript. The interviewer supplied me with some code and 18 failing unit tests that once the algorithm was successfully implemented would pass. I'm sure there is a more efficient way to have solved this problem as I tried a few different approaches during my allotted time. This way is the first way that I got to work, which for the technical test was enough but I'd like to know a better way of solving the problem.

Problem

Work out if the cards in a poker hand form a straight. (I've already ordered the hand in ascending order.)

My Solution

PokerHand.prototype._check_straight_function = function(arr) {
    var isStraight = false;
    for (var j = i = 4; i >= 0 && j > 1; i--)
        if (arr[i].value() - 1 == arr[--j].value()) {
            isStraight = true;
        } else {
            isStraight = false;
        }
    };
    return isStraight;
};

Other approaches

Things I didn't get working that I think might work faster, I'd really appreciate if someone could talk me through a working version of the below approach(es) and help me understand which is the fastest to evaluate.

Upvotes: 5

Views: 1690

Answers (6)

Nageshwar Reddy Pandem
Nageshwar Reddy Pandem

Reputation: 1047

here is another way

var isOrdered = true;
[5, 6, 8, 9].sort(function(a, b) {
  (b - a != 1) ? isOrdered = false: true;
});
alert(isOrdered);

DEMO

Upvotes: 1

NessBird
NessBird

Reputation: 845

Well, this is maybe a tiny bit tidier. I don't see a Ninja way ;( As far as comparing the solutions -- I'm an employer, and for my part, I'd prefer the answer which was clear and elegant over one which was a few nanoseconds faster :)

for (var i = 0; i < 5; i++) {
  if (a[i].value() != i + a[0].value())
    return false;
}
return true;

Upvotes: 1

chiliNUT
chiliNUT

Reputation: 19592

Just throwing it out there, I think this one does it with the least amount of lines (3), whether or not that is "better" is subjective as it is probably less clear

    var last = arr.pop().value(), popped;
    while ((popped = arr.pop().value()) === --last);
    return popped === undefined;

Upvotes: 2

bestprogrammerintheworld
bestprogrammerintheworld

Reputation: 5520

There's no need to assign a variable isStraight at all.

PokerHand.prototype._check_straight_function = function(arr) {
    for (var i = i = 4; i++) {        
        if (arr[i].value() - 1 != arr[i-1].value()) {
            return false;
        }
    };

    return true;
};

Upvotes: 2

user2864740
user2864740

Reputation: 62013

The [original] code is incorrect because it will assign isStraight (or clear it) only for the given pair being checked. Thus the "last pair" incorrectly determines the result.

In my book the "better way", is to keep it clean:

for (var i = 0; i < 4; i++) {
    var a = arr[i];   // arr[0..3]
    var b = arr[i+1]; // arr[1..4]
    if (!(a.value() + 1 == b.value())) {
        return false; // Not sequential
    }
};
return true;

If a zip higher-order function is available this could be reduced as a variation of

arr.zip(function (a, b) { return [a.value(), b.value()] })
   .every(function (x) { return x[0] + 1 === x[1] })

but zip is not standard.

Upvotes: 1

stinepike
stinepike

Reputation: 54742

here is a similar code with some minor optimization ( in java,, check the algorithm)

    boolean isStraight = true;
    for (int i = 0; i < 4; i++) {
        if (arr[i] + 1 != arr[i+1]) {
            isStraight = false;
            break;
        }
    };

Upvotes: 1

Related Questions