Last active
August 29, 2015 14:04
-
-
Save marzapower/60950151e112d9ca7c6d to your computer and use it in GitHub Desktop.
Swift Ninja Final Challenge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum Suit { | |
case Clubs, Diamonds, Hearts, Spades | |
} | |
enum Rank { | |
case Jack, Queen, King, Ace | |
case Num(Int) | |
} | |
struct Card { | |
let suit: Suit | |
let rank: Rank | |
} | |
/* | |
* Expresses a generic rule for computing card values | |
*/ | |
struct Rule { | |
// Should return true if the rule is appliable | |
let applies : (currentCard:Card, previousCard:Card?) -> Bool | |
// Returns the computed value for the current card | |
let exec : (card:Card) -> Int | |
} | |
/* | |
* Keeps track of the total score of the hand and the last card | |
* that has been evaluated | |
*/ | |
struct Sum { | |
var total : Int | |
var lastCard : Card? | |
} | |
/* | |
* Extracts the integer value of the card's rank | |
*/ | |
func cardValue(card : Card?) -> Int { | |
if card?.rank { | |
switch(card!.rank) { | |
case .Ace : return 1 | |
case .King : return 13 | |
case .Queen : return 12 | |
case .Jack : return 11 | |
case .Num(let value) : return value | |
} | |
} else { | |
return 0 | |
} | |
} | |
/* | |
* This rule expresses rule n. 1 for computing card values | |
*/ | |
let aces = Rule( | |
applies: { currentCard, previousCard in | |
return cardValue(currentCard) == 1 && cardValue(previousCard?) == 5 && previousCard?.suit == Suit.Diamonds | |
}, exec: { card in return 100 }) | |
/* | |
* This rule expresses rule n. 2 for computing card values | |
*/ | |
let oddity = Rule( | |
applies: { currentCard, previousCard in | |
return cardValue(currentCard)%2==1 && previousCard?.suit == Suit.Hearts | |
}, exec: { card in return cardValue(card)*2 }) | |
let rules = [aces, oddity] // More rules could be added ... if necessary | |
/* | |
* Applies a set of rules to the current card using the previous one as the reference | |
*/ | |
func applyRules(rules: [Rule], currentCard: Card, previousCard: Card?) -> Int { | |
return maxElement(rules.map{ rule in rule.applies(currentCard: currentCard, previousCard: previousCard) ? rule.exec(card: currentCard) : 0 }) | |
} | |
/* | |
* Counts the hand applying a global set of rules to its sequence of cards | |
*/ | |
func countHand(cards : [Card]) -> Int { | |
return cards.reduce(Sum(total: 0, lastCard: nil)) { sum, currentCard in | |
Sum(total: sum.total + applyRules(rules, currentCard, sum.lastCard), lastCard: currentCard) | |
}.total | |
} | |
let result = countHand([ | |
Card(suit:Suit.Hearts, rank:Rank.Ace), | |
Card(suit:Suit.Hearts, rank:Rank.Num(10)), | |
Card(suit:Suit.Hearts, rank:Rank.Num(6)), | |
Card(suit:Suit.Diamonds, rank:Rank.Num(5)), | |
Card(suit:Suit.Clubs, rank:Rank.Ace), | |
Card(suit:Suit.Diamonds, rank:Rank.Jack) | |
]) //--> 110 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@icanzlib: I've already set up the Gist to use the Swift language. Any missing code coloring is due to Github :)
@dkra89: thank you for the suggestion. I was using a slightly different version locally and I didn't notice the error. The updated version should be fine!