Reputation: 3551
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.
Work out if the cards in a poker hand form a straight. (I've already ordered the hand in ascending order.)
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;
};
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.
arr.pop().value - 1 == arr.pop().value()
filter
the array to create a new array that contains only values where the next index (arr[++i])
is the current index + 1 and then see if the new array is the same length.for loop
with a break / continue
to short circuit as soon as the straight ends. Upvotes: 5
Views: 1690
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);
Upvotes: 1
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
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
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
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
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