Skip to footer navigation.

« Oatmeal

Posts tagged swift

Follow this tag's bespoke rss feed or return to the list of all tags.

Something something something, week notes

I’ve finished my little exploratory jaunt through the writings of Sally Rooney this week. I’ve left aside one of her novels for some other time, Beautiful World, Where Are You. Some authors have clear habits, or projects.” Rooney strikes me as such an author. Naming either seems a bit trickier, though. Something something something, what do normative friendships between people entail, something something something how is morality constructed by other peoples’ perceptions, something something something.

Now I’m reading The Ministry of Time by Kaliane Bradley. I was kinda hesitant to reading this one purely because of the word ministry” being in the title. The last book I read that had a title including that word was a miserable slog that I found terribly disagreeable. This book is neither a slog nor terribly disagreeable.

I spent some time this week writing swift using swiftUI. Compared to using webby things, the entire ecosystem of dev tools around swift and apple is oppressive and exhausting, but I’m worried that the accessibility feature I live and die by on macOS is being eroded away, dripping out of the operating system, so, I figured I’d try my hand at re-implementing it from scratch. Dear reader, it is not going great for me, but I’ve got enough working that I know it is possible if I keep plugging away. Onward.

Evidently my children don’t like the edges of brownies. They each prefer gooey centers. I, as a parent, have failed…gross.

Dithering the Shire

In my last post I said that

I’ve had a few ideas for other personal experiments I wanna build on those walks, but haven’t actually wanted to do much programming — maybe this fall or winter will be a good time for that?

Welp, it wasn’t even an idea when I wrote that, but I made another implementation of pico cam, this time using swift for iOS. I won’t release it to the App Store because I don’t wanna give Apple that money, but it is available on GitHub, so if you know how, it is pretty workable!

It was a fun project and I learned a bit a more about SwiftUI. I haven’t touched SwiftUI pretty much since it was first released. Being thoroughly web-dev-brained, it is pretty approachable, as long as you don’t stray from the happy path. When I worked somewhere that did a lot of app development, the first iterations of an app tended to have wicked rough UI, which lead to some really bad UX — we usually had to do a lot of design clean up. SwiftUI seems to directly address that; as long as you stay within the rails offered by SwiftUI you get a lot of good UI, with mostly solid UX, for free.”

This project rekindled my belief that someone could relatively quickly churn out very small, focused apps that help to address a single, or small set of well-defined needs. I forget who said it, but I recently saw someone on the fediverse talk about hobbit-core apps — I think maybe this is that? I think that it would be dreamy to work on tooling like that — where, rather than having to be concerned with growth and adoption, and what a feature roadmap with a hilariously long tail (8 years!?), I could help address the known needs of a known group of folks with small, easy to release applications.

The story of life

Or at least the story of life as I implemented it in swift recently as a little learning project because I haven’t written any swift since walking away from mobile dev a few years ago (no regrets)!


First there was the universe! Well, first there was some requisite boilerplate, but then there was the universe! A 2 dimensional grid, an array of 10 columns and 10 rows.

import Foundation

let rows: Int = 10
let cols: Int = 10

Into that great void will be brought life.

The universe and life hold to simple truths:

  • The universe is a 2 dimensional array of equally sized cells
  • The universe’s state exists as discrete snapshots from time
  • Every 1 snapshot is 1 generation
  • Every cell has exactly 2 states, living and dead
  • A cell must be in exactly 1 state at a time, either living or dead
  • A cell’s neighbors are considered to be all adjacent cells
  • Any cell with less than 2 live neighbors dies
  • Any cell with 2 or 3 live neighbors continues to the next generation
  • Any cell with more than 3 live neighbor dies
  • Any dead cell with 3 neighbors becomes a living cell
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
        }
    }
}

A clock to tick and a weaver to draw our life on to the cosmos for us to behold.

func printBoard(_ board: [[Int]]) {
    board.forEach { row in
        row.forEach { cell in
            print(cell == 1 ? "@" : ".", terminator: "")
        }
        print()
    }
    print("\n")
}

With our mechanisms for life and death and viewing in place we gaze into the cosmos and we say to Chronos: begin.”

func simulate(board: [[Int]], generations: Int) {
    var currentBoard: [[Int]] = board
    for _ in 0..<generations {
        printBoard(currentBoard)
        currentBoard = nextGeneration(currentBoard)
        sleep(1)
    }
}

func randomBoard() -> [[Int]] {
    return (0..<rows).map { _ in
        return (0..<cols).map { _ in
            return Int.random(in: 0...1)
        }
    }
}

simulate(board: randomBoard(), generations: 10)

…and it works!

But, of course, don’t miss the most elegant implementation of life ever there was.


Here is the full implementation for any of ya’ll sickos who want your own copy. No license. No promises. No documentation. No rulers. Go nuts.