Skip to content

Instantly share code, notes, and snippets.

@eliperkins
Last active February 4, 2018 16:48
Show Gist options
  • Save eliperkins/3f33a403e7a1c1c38c659783771c06a4 to your computer and use it in GitHub Desktop.
Save eliperkins/3f33a403e7a1c1c38c659783771c06a4 to your computer and use it in GitHub Desktop.
Generate Super Bowl Squares in a Xcode Playground
//: Playground - noun: a place where people can play
//: Super Bowl Squares - noun: free money
import Foundation
import PlaygroundSupport
enum Player: String {
case eli = "Eli"
case brian = "Brian"
case brendan = "Brendan"
case pat = "Pat"
static let allPlayers: Array<Player> = [.eli, .brendan, .brian, .pat]
static func randomPlayer() -> Player {
return allPlayers[Int(arc4random_uniform(UInt32(allPlayers.count)))]
}
}
extension Collection where Index == Int {
func random() -> Element {
return self[Int(arc4random_uniform(UInt32(count)))]
}
}
struct Square {
let patsScore: Int
let eaglesScore: Int
let player: Player
}
extension Square: Equatable, Hashable {
static func ==(lhs: Square, rhs: Square) -> Bool {
return lhs.patsScore == rhs.patsScore && lhs.eaglesScore == rhs.eaglesScore && lhs.player == rhs.player
}
var hashValue: Int {
return patsScore ^ eaglesScore ^ player.hashValue
}
}
extension Square: CustomDebugStringConvertible {
var debugDescription: String {
return "\(player.rawValue): Pats \(patsScore) - Eagles \(eaglesScore)"
}
}
extension Square: Codable {
enum CodingKeys: String, CodingKey {
case pats
case eagles
case player
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(patsScore, forKey: .pats)
try container.encode(eaglesScore, forKey: .eagles)
try container.encode(player.rawValue, forKey: .player)
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.patsScore = try values.decode(Int.self, forKey: .pats)
self.eaglesScore = try values.decode(Int.self, forKey: .eagles)
self.player = Player(rawValue: try values.decode(String.self, forKey: .player)) ?? .eli
}
}
func randomPlayer(from players: Array<Player>, with squareCounts: NSCountedSet, maxSquares: Int) -> Player {
while (true) {
let player = players.random()
if squareCounts.count(for: player) < maxSquares {
return player
}
}
}
typealias Board = Array<Array<Square>>
func generateBoard(with players: [Player]) -> Board {
let squareSize = (0...9).count
let totalSquares = squareSize * squareSize
let (baseSquares, remainder) = totalSquares.quotientAndRemainder(dividingBy: players.count)
let squaresPerPerson = remainder == 0 ? baseSquares : baseSquares + 1
let squareCounts = NSCountedSet(capacity: players.count)
return (0...9).map({ pats in
return (0...9).map({ eagles in
let player = randomPlayer(from: players, with: squareCounts, maxSquares: squaresPerPerson)
squareCounts.add(player)
return Square(patsScore: pats, eaglesScore: eagles, player: player)
})
})
}
func print(_ board: Board) {
let maxNameLength = Player.allPlayers.map({ $0.rawValue.count }).max() ?? 5
let header = (0...9).map(String.init)
.map({ $0.padding(toLength: maxNameLength, withPad: " ", startingAt: 0) })
.joined(separator: "|")
print(" |\(header)")
board.enumerated().forEach { (rowIndex, row) in
let rowString = row.map({
$0.player.rawValue.padding(toLength: maxNameLength, withPad: " ", startingAt: 0)
}).joined(separator: "|")
print("\(rowIndex) |\(rowString)")
}
}
func printPlayerSquares(for board: Board) {
let allSquares = board.reduce([], +)
let grouped = Dictionary(grouping: allSquares, by: { $0.player })
grouped.forEach { (player, squares) in
let squaresString = squares.map({ "\($0.patsScore), \($0.eaglesScore)" }).joined(separator: "\n")
print("\(player.rawValue): \n\(squaresString)")
}
}
func squareFor(score score: (Int, Int), from board: Board) -> Square {
let pats = score.0 % 10
let eagles = score.1 % 10
return board[pats][eagles]
}
let fileURL = URL(fileURLWithPath: "board.json", isDirectory: false, relativeTo: playgroundSharedDataDirectory)
func save(_ board: Board) {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
guard let data = try? encoder.encode(board) else { fatalError() }
do {
try data.write(to: fileURL)
} catch {
fatalError()
}
}
func loadBoard() -> Board {
guard let data = try? Data(contentsOf: fileURL) else { fatalError() }
let decoder = JSONDecoder()
guard let board = try? decoder.decode(Board.self, from: data) else { fatalError() }
return board
}
//let board = generateBoard(with: Player.allPlayers)
//save(board)
let board = loadBoard()
let firstQuarter = squareFor(score: (0, 0), from: board)
let halftime = squareFor(score: (0, 0), from: board)
let thirdQuarter = squareFor(score: (0, 0), from: board)
let final = squareFor(score: (0, 0), from: board)
print(board)
printPlayerSquares(for: board)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment