Skip to content

Instantly share code, notes, and snippets.

@marzapower
Last active August 29, 2015 14:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marzapower/60950151e112d9ca7c6d to your computer and use it in GitHub Desktop.
Save marzapower/60950151e112d9ca7c6d to your computer and use it in GitHub Desktop.
Swift Ninja Final Challenge
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
@marzapower
Copy link
Author

@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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment