import Foundation let rows: Int = 10 let cols: Int = 10 func printBoard(_ board: [[Int]]) { board.forEach { row in row.forEach { cell in print(cell == 1 ? "@" : ".", terminator: "") } print() } print("\n") } // Are these comments enough for a blog post? func countLiveNeighbors(_ board: [[Int]], x: Int, y: Int) -> Int { // All of the possible directions to check for live neighbors let directions: [(Int, Int)] = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)] // Iterate over the directions and count live neighbors return directions.reduce(0) { count, dir in // Calculate the coordinates of the neighbor cell let newX: Int = x + dir.0 let newY: Int = y + dir.1 // Check if the neighbor cell is within the bounds of the board if newX >= 0 && newX < rows && newY >= 0 && newY < cols { // If the neighbor cell is within bounds, add its value to the count return count + board[newX][newY] } // If the neighbor cell is out of bounds, ignore it and continue with the next direction return count } } func nextGeneration(_ currentBoard: [[Int]]) -> [[Int]] { // Iterate over each cell in the current board return currentBoard.enumerated().map { (x: Int, row: [Int]) in return row.enumerated().map { (y: Int, cell: Int) in // Count the number of live neighbors for the current cell let liveNeighbors: Int = countLiveNeighbors(currentBoard, x: x, y: y) // Determine the next state of the cell if cell == 1 && (liveNeighbors < 2 || liveNeighbors > 3) { // Determine death return 0 } else if cell == 0 && liveNeighbors == 3 { // Determine life return 1 } // Do nothing return cell } } } func simulate(board: [[Int]], generations: Int) { var currentBoard: [[Int]] = board for _ in 0..<generations { printBoard(currentBoard) currentBoard = nextGeneration(currentBoard) sleep(1) // FIXME: figure out how to sleep for periods shorter than a full second } } var glider: [[Int]] = Array(repeating: Array(repeating: 0, count: cols), count: rows) glider[1][2] = 1 glider[2][3] = 1 glider[3][1] = 1 glider[3][2] = 1 glider[3][3] = 1 simulate(board: glider, generations: 10) var flasher: [[Int]] = Array(repeating: Array(repeating: 0, count: cols), count: rows) flasher[4][5] = 1 flasher[5][5] = 1 flasher[6][5] = 1 simulate(board: flasher, generations: 4) var beacon: [[Int]] = Array(repeating: Array(repeating: 0, count: cols), count: rows) beacon[2][2] = 1 beacon[2][3] = 1 beacon[3][2] = 1 beacon[4][5] = 1 beacon[5][4] = 1 beacon[5][5] = 1 simulate(board: beacon, generations: 4) var toad: [[Int]] = Array(repeating: Array(repeating: 0, count: cols), count: rows) toad[3][4] = 1 toad[3][5] = 1 toad[3][6] = 1 toad[4][3] = 1 toad[4][4] = 1 toad[4][5] = 1 simulate(board: toad, generations: 5) var rpentomino: [[Int]] = Array(repeating: Array(repeating: 0, count: cols), count: rows) rpentomino[3][4] = 1 rpentomino[3][5] = 1 rpentomino[4][3] = 1 rpentomino[4][4] = 1 rpentomino[5][4] = 1 simulate(board: rpentomino, generations: 22) func randomBoard() -> [[Int]] { return (0..<rows).map { _ in return (0..<cols).map { _ in return Int.random(in: 0...1) } } } simulate(board: randomBoard(), generations: 10)