All pastes #900641 Raw Edit

Miscellany

public javascript v1 · immutable
·published 2008-02-12 01:35 UTC
rendered paste body
(function() {    // Return the greatest element of an array.    function max(arr) {        var maximum = arr[0];        for (var i in arr) {            if (arr[i] > maximum)                maximum = arr[i];        }        return maximum;    }    // Return true if all elements in arr are true, false otherwise.    function all(arr) {        for (var i in arr) {            if (!arr[i])                return false;        }        return true;    }    function sum(arr) {        var n = 0;        for (var i in arr) {            n += arr[i];        }        return n;    }    // Return all combinations of the elements in arr    function powerset(arr) {        var set = [];        for (var i = 0, pow = Math.pow(2, arr.length); i < pow; ++i) {            var subset = [];            for (var j = 0; j < arr.length; ++j) {                if (1<<j & i) {                    subset.push(arr[j]);                }            }            set.push(subset);        }        return set;    }    var ranks = [        'ace',        'two',        'three',        'four',        'five',        'six',        'seven',        'eight',        'nine',        'ten',        'jack',        'queen',        'king'    ];    var suits = [        'clubs',        'diamond',        'heart',        'spade'    ];    // If a global object called Cribbage already exists, save it    // to window._Cribbage.    if (window.Cribbage) window._Cribbage = window.Cribbage;    var Cribbage = window.Cribbage = {        Card: function(rank, suit) {            this.rank = rank;            this.suit = suit;            this.pos = ranks.indexOf(this.rank);            this.value = this.pos < 9 ? this.pos+1 : 10;        },                Hand: function(hand, starterCard, isCrib) {            this.hand = hand;            this.starterCard = starterCard;            this.isCrib = Boolean(isCrib);            if (this.starterCard) {                this.cards = this.hand.concat(this.starterCard);            }            else {                this.cards = this.hand;            }        }    };    Cribbage.Card.prototype.isValid = function() {        return (ranks.indexOf(this.rank) > -1) &&               (suits.indexOf(this.suit) > -1);    };    Cribbage.Card.prototype.toString = function() {        return "<Card: " + this.rank + " of " + this.suit + ">";    }    // Count points from all individual methods    Cribbage.Hand.prototype.count = function() {        return this.countPairs() +               this.countFifteens() +               this.countJack() +               this.countFlush() +               this.countStraight();    };    // 2 points for every pair (same rank)    Cribbage.Hand.prototype.countPairs = function() {        var pset = powerset(this.cards);        var n = 0;                for (var i in pset) {            var set = pset[i];            if (set.length == 2 && set[0].rank == set[1].rank)                n += 2        }        return n;    };    // 2 points for all combinations that add up to 15    Cribbage.Hand.prototype.countFifteens = function() {        var pset = powerset(this.cards);        var n = 0;        for (var i in pset) {            var set = pset[i];            if (sum(set.map(function(card) { return card.value })) == 15)                n += 2;        }        return n    };    // 1 point if a jack in your hand has the same suit as the starter card.    Cribbage.Hand.prototype.countJack = function() {        for (i in this.hand) {            if (this.hand[i].rank == 'jack' && this.hand[i].suit == this.starterCard.suit)                return 1;        }        return 0;    };    // 1 point per card in a flush.  All the cards in the hand need to be of the same suit.    // If the hand is a crib, the starter card must also have the same suit.    Cribbage.Hand.prototype.countFlush = function() {        function _countFlush(cards) {            var suits = cards.map(function(card) { return card.suit == cards[0].suit; });            if (all(suits))                return cards.length;            else                return 0;        }        if (this.isCrib) {            return _countFlush(this.cards);        }        else {            return max([_countFlush(this.hand), _countFlush(this.cards)]);        }    };    // 1 point per card in a straight.  Only straights of 3 cards and more are considered    // and the longest straights are the ones counted (i.e.: if you have a straight Ace,    // Two, Three, Four, this counts for four points)    Cribbage.Hand.prototype.countStraight = function() {        function _isStraight(arr) {            var arr2 = arr.sort()            for (var i = 0, length = arr2.length; i < length; ++i) {                if (arr2[i] - i != arr2[0])                    return false;            }            return true;        }        function _keepLongest(arr) {            var longest = max(arr.map(function (x) { return x.length; }));            if (longest < 3)                return [[]];            return arr.filter(function(x) { return x.length == longest; });        }        var pset = powerset(this.cards.map(function(card) { return card.pos; }));        var straights = pset.filter(_isStraight);        straights = _keepLongest(straights);        var n = 0;        for (var i = 0, length = straights.length; i < length; ++i) {            n += straights[i].length;        }        return n;    }    // If $C and $H already exist, we back them up under the    // names $_C and $_H.    if (window.$C) window.$_C = window.$C;    if (window.$H) window.$_H = window.$H;    // Utility function to make creating a card more succinct.    // e.g.: $C('AS') == new Cribbage.Card('ace', 'spade')    window.$C = function(desc) {        var rank = {            'A': 'ace',            '2': 'two',            '3': 'three',            '4': 'four',            '5': 'five',            '6': 'six',            '7': 'seven',            '8': 'eight',            '9': 'nine',            'T': 'ten',            'J': 'jack',            'Q': 'queen',            'K': 'king'        }[desc[0]];        var suit = {            'C': 'clubs',            'D': 'diamond',            'H': 'heart',            'S': 'spade'        }[desc[1]];        var card = new Cribbage.Card(rank, suit);        return card.isValid() ? card : null;    };    // Utility function to make creating a hand more succinct.    // e.g.: $H([$C('AS')], $C('JC')) == new Cribbage.Hand([$C('AS')], $C('JC'))    window.$H = function(hand, starterCard, isCrib) {        return new Cribbage.Hand(hand, starterCard, isCrib);    };})();