Skip to content

Instantly share code, notes, and snippets.

@rayfix
Created Jun 14, 2020
Embed
What would you like to do?
SetCard abstraction
func combinations<S1: Sequence, S2: Sequence>(_ sequence1: S1, _ sequence2: S2) -> AnySequence<(S1.Element, S2.Element)> {
AnySequence(
sequence1.lazy.flatMap { element1 in
sequence2.lazy.map { element2 in
(element1, element2)
}
}
)
}
func combinations<S1: Sequence, S2: Sequence, S3: Sequence>(_ sequence1: S1, _ sequence2: S2, _ sequence3: S3) -> AnySequence<(S1.Element, S2.Element, S3.Element)> {
AnySequence (
combinations(combinations(sequence1, sequence2), sequence3).lazy.map { ($0.0.0, $0.0.1, $0.1)}
)
}
/// Produce all of the combinations of elements in each sequence.
/// - Note:
/// - Complexity: O(1)
/// - Parameters:
/// - sequence1: Input sequence.
/// - sequence2: Input sequence.
/// - sequence3: Input sequence.
/// - sequence4: Input sequence.
/// - Returns: All of the combinations.
func combinations<S1: Sequence, S2: Sequence, S3: Sequence, S4: Sequence>(_ sequence1: S1, _ sequence2: S2, _ sequence3: S3, _ sequence4: S4) -> AnySequence<(S1.Element, S2.Element, S3.Element, S4.Element)> {
AnySequence (
combinations(combinations(sequence1, sequence2, sequence3), sequence4).lazy.map { ($0.0.0, $0.0.1, $0.0.2, $0.1)}
)
}
struct SetCard: Hashable {
enum Number: CaseIterable, Hashable {
case one, two, three
}
enum Shape: CaseIterable, Hashable {
case diamond, squiggle, oval
}
enum Shading: CaseIterable, Hashable {
case solid, stripped, open
}
enum Color: CaseIterable, Hashable {
case red, green, purple
}
var number: Number
var shape: Shape
var shading: Shading
var color: Color
}
extension SetCard {
static func makeDeck() -> [SetCard] {
combinations(Number.allCases, Shape.allCases,
Shading.allCases, Color.allCases).map(Self.init)
}
}
extension SetCard {
private static func pickAttribute<A: CaseIterable & Hashable>(_ a: A, _ b: A) -> A {
a == b ? a : A.allCases.filter { $0 != a && $0 != b }.first!
}
static func complete(_ a: SetCard, _ b: SetCard) -> SetCard {
SetCard(number: pickAttribute(a.number, b.number),
shape: pickAttribute(a.shape, b.shape),
shading: pickAttribute(a.shading, b.shading),
color: pickAttribute(a.color, b.color))
}
}
extension Collection where Element == SetCard {
private func attributeIsSet<A: Hashable>(accessor: (SetCard) -> A) -> Bool {
let attributes = self.reduce(into: Set<A>()) { $0.insert(accessor($1)) }
return attributes.count == 1 || attributes.count == 3
}
func isSet() -> Bool {
attributeIsSet(accessor: \.number) &&
attributeIsSet(accessor: \.shape) &&
attributeIsSet(accessor: \.shading) &&
attributeIsSet(accessor: \.color)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment