Reputation: 1574
I have a very specific case that I need to meet, but I am having trouble writing it (more information below).
***Check comments in countHand(_:)
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
}
extension Rank: Equatable {
static func == (lhs: Rank, rhs: Rank)
-> Bool {
switch (lhs, rhs) {
case (.Jack, .Jack), (.Queen, .Queen), (.King, .King), (.Ace, .Ace):
return true
case let (.Num(n1), .Num(n2)) where n1 == n2:
return true
default:
return false
}
}
}
extension Suit: Equatable {
static func == (lhs: Suit, rhs: Suit)
-> Bool {
switch (lhs, rhs) {
case (.Diamonds, .Diamonds), (.Hearts, .Hearts), (.Spades, .Spades), (.Clubs, .Clubs):
return true
default:
return false
}
}
}
//Main Function
func countHand(_ cards: [Card]) -> Int {
var count = 0
zip(cards, cards[1...]).forEach { card, nextCard in
let bothCards = (card, nextCard)
switch bothCards {
case let (c1, c2) where c1.rank == .Num(5) && c1.suit == .Diamonds && c2.rank == .Ace:
count += 100
case let (c1, c2) where c1.suit == .Hearts && ![.Jack, .Queen, .King, .Ace].contains(c2.rank): //I checked the contents of the array as a workaround to determine that the rank is a numeric value
//Also, if c2.rank is Rank.Num(let n) where n == 3 || n == 5 || n == 7 || n == 9
count += n * 2
default:
break
}
}
return count
}
The card values are as follows:
Any Ace preceded by 5 of Diamonds is worth 100 points.
Any odd numeric card (3, 5, 7, 9) of any suit's worth the double of its rank value in points when immediately preceded in the hand by any card of the Hearts. Examples:
The hand 3♥, 7♣ has total value of 14.
The hand 3♣, 7♥ has total value of 0.
What I would like to do is – in regards to my second case statement – I only want it to be called if the first card, c1
, and the second card, c2
, meet these criterion:
c1.suit
is .Hearts
c2.rank
is numeric (.Num(n)
) and n
is 3, 5, 7, or 9
If both of these criterion are met, I would like to increase the value of count
to n * 2
I've searched in depth to try to find a case that is similar to mine online, but unfortunately, there are none – that I could find – that matched the level of specificity that I am looking for.
I have tried to put add it to the where
predicate by doing things like where ... && c2.rank = .Num(let n)
the wrote an if
statement within the case to only change the value of count
if it is 3, 5, 7, or 9, but this yielded all kinds of errors and I don't feel that this is the best way to implement it though. This is my main problem that I am inquiring about to get fixed. If I can do this though, I am quite sure I can take out my workaround of where ... && ![.Jack, .Queen, .King, .Ace].contains(c2.rank)
.
Thanks everyone in advance for all suggestions, solutions, feedback, etc., I really appreciate the help!
Upvotes: 2
Views: 3387
Reputation: 539815
You cannot do pattern matching in the where-clause, but you could switch on both properties of both cards instead:
switch (card.suit, card.rank, nextCard.suit, nextCard.rank) {
case (.Diamonds, .Num(5), _, .Ace):
count += 100
case (.Hearts, _, _, .Num(let n)) where n >= 3 && n % 2 != 0:
// Or: ... where [3, 5, 7, 9].contains(n):
count += n * 2
default:
break
}
Remark: According to the current Swift API Design Guidelines, enum properties should be lowercase:
Names of types and protocols are
UpperCamelCase
. Everything else islowerCamelCase
.
Upvotes: 3