about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--swift/life/.gitignore8
-rw-r--r--swift/life/Package.swift14
-rw-r--r--swift/life/Sources/main.swift53
3 files changed, 75 insertions, 0 deletions
diff --git a/swift/life/.gitignore b/swift/life/.gitignore
new file mode 100644
index 0000000..0023a53
--- /dev/null
+++ b/swift/life/.gitignore
@@ -0,0 +1,8 @@
+.DS_Store
+/.build
+/Packages
+xcuserdata/
+DerivedData/
+.swiftpm/configuration/registries.json
+.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
+.netrc
diff --git a/swift/life/Package.swift b/swift/life/Package.swift
new file mode 100644
index 0000000..e1f6d6e
--- /dev/null
+++ b/swift/life/Package.swift
@@ -0,0 +1,14 @@
+// swift-tools-version: 5.10
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+    name: "life",
+    targets: [
+        // Targets are the basic building blocks of a package, defining a module or a test suite.
+        // Targets can depend on other targets in this package and products from dependencies.
+        .executableTarget(
+            name: "life"),
+    ]
+)
diff --git a/swift/life/Sources/main.swift b/swift/life/Sources/main.swift
new file mode 100644
index 0000000..4b3e7a6
--- /dev/null
+++ b/swift/life/Sources/main.swift
@@ -0,0 +1,53 @@
+import Foundation
+
+let rows = 10
+let cols = 10
+var board = Array(repeating: Array(repeating: 0, count: cols), count: rows)
+
+func printBoard(_ board: [[Int]]) {
+    board.forEach { row in
+        row.forEach { cell in
+            print(cell == 1 ? "@" : ".", terminator: "")
+        }
+        print()
+    }
+    print("\n")
+}
+
+func countLiveNeighbors(_ board: [[Int]], x: Int, y: Int) -> Int {
+    let directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
+    return directions.reduce(0) { count, dir in
+        let newX = x + dir.0
+        let newY = y + dir.1
+        if newX >= 0 && newX < rows && newY >= 0 && newY < cols {
+            return count + board[newX][newY]
+        }
+        return count
+    }
+}
+
+func nextGeneration(_ currentBoard: [[Int]]) -> [[Int]] {
+    return currentBoard.enumerated().map { (x, row) in
+        return row.enumerated().map { (y, cell) in
+            let liveNeighbors = countLiveNeighbors(currentBoard, x: x, y: y)
+            if cell == 1 && (liveNeighbors < 2 || liveNeighbors > 3) {
+                return 0
+            } else if cell == 0 && liveNeighbors == 3 {
+                return 1
+            }
+            return cell
+        }
+    }
+}
+
+board[1][2] = 1
+board[2][3] = 1
+board[3][1] = 1
+board[3][2] = 1
+board[3][3] = 1
+
+for _ in 0..<10 {
+    printBoard(board)
+    board = nextGeneration(board)
+    sleep(1) // FIXME: figure out how to sleep for periods shorter than a full second
+}