fileprivate let tileBaseH = Array(""" ┏━━┳━━┓ ┃ ┃ ┃ ┗━━┻━━┛ """) fileprivate let tileBaseV = Array(""" ┏━━┓ ┃ ┃ ┣━━┫ ┃ ┃ ┗━━┛ """) struct Domino: Hashable { static let horizontalTileWidth = 7 static func all(up to: Int) -> Set { return Set((0...to).flatMap { l in return (0...to).map { r in return Domino(l, r) } }) } let leading: Int let trailing: Int let isDouble: Bool let value: Int init(double: Int) { self.init(double, double) } init(_ l: Int, _ r: Int) { leading = min(l, r); trailing = max(l, r) isDouble = (l == r) if isDouble && l == 0 { value = 30 } else { value = l + r } } func connectsTo(_ number: Int) -> Bool { return leading == number || trailing == number } func numberOpposite(_ number: Int) -> Int { assert(number == leading || number == trailing) return (number == leading) ? trailing : leading } func tile(_ vertical: Bool? = nil, leading: Int? = nil) -> String { let v = vertical ?? isDouble let l = leading ?? self.leading assert(l == self.leading || l == self.trailing) let lead = l let trail = (l == self.leading) ? self.trailing : self.leading var characters: Array if v { characters = tileBaseV characters[6] = "\(lead / 10)".first! characters[7] = "\(lead % 10)".first! characters[16] = "\(trail / 10)".first! characters[17] = "\(trail % 10)".first! } else { characters = tileBaseH characters[9] = "\(lead / 10)".first! characters[10] = "\(lead % 10)".first! characters[12] = "\(trail / 10)".first! characters[13] = "\(trail % 10)".first! } return String(characters) } }