Skip to content

Instantly share code, notes, and snippets.

@gregomni
Created July 15, 2023 22:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregomni/5a82662cff008a212a3dcd7ba2bf7564 to your computer and use it in GitHub Desktop.
Save gregomni/5a82662cff008a212a3dcd7ba2bf7564 to your computer and use it in GitHub Desktop.
Banana-only Scrabble, naive and slow (for now)
//
// main.swift
// banana
//
// Created by Greg Titus on 7/15/23.
//
import Foundation
enum Letter: Character, Hashable {
case empty = "."
case b = "B"
case a = "A"
case n = "N"
static let banana: [Letter] = [.b, .a, .n, .a, .n, .a]
}
struct Position {
let row: Int
let column: Int
var up: Position { Position(row: row-1, column: column) }
var down: Position { Position(row: row+1, column: column) }
var left: Position { Position(row: row, column: column-1) }
var right: Position { Position(row: row, column: column+1) }
}
struct Board: Hashable {
static let size = 15
var array: [Letter]
init() {
self.array = Array(repeating: .empty, count: Self.size * Self.size)
}
subscript(_ p: Position) -> Letter {
get { array[p.row * Self.size + p.column] }
set { array[p.row * Self.size + p.column] = newValue }
}
mutating func addBanana(_ p: Position, vertical: Bool) {
var p = p
for tile in Letter.banana {
self[p] = tile
p = vertical ? p.down : p.right
}
}
func byAdding(_ p: Position, vertical: Bool) -> Board {
var result = self
result.addBanana(p, vertical: vertical)
return result
}
func canAddBanana(_ at: Position, vertical: Bool, index: Int) -> Bool {
guard self[at] == Letter.banana[index] else { return false }
var laidTile = false
if vertical {
guard at.row - index >= 0 else { return false }
guard at.row + (5-index) < Board.size else { return false}
var p = Position(row: at.row - index, column: at.column)
guard p.row == 0 || self[p.up] == .empty else { return false }
for tile in Letter.banana {
if self[p] == tile {
} else if self[p] == .empty {
if p.column > 0 && self[p.left] != .empty { return false }
if p.column < 14 && self[p.right] != .empty { return false }
laidTile = true
} else {
return false
}
p = p.down
}
guard p.row == 15 || self[p] == .empty else { return false }
} else {
guard at.column - index >= 0 else { return false }
guard at.column + (5-index) < Board.size else { return false}
var p = Position(row: at.row, column: at.column - index)
guard p.column == 0 || self[p.left] == .empty else { return false }
for tile in Letter.banana {
if self[p] == tile {
} else if self[p] == .empty {
if p.row > 0 && self[p.up] != .empty { return false }
if p.row < 14 && self[p.down] != .empty { return false }
laidTile = true
} else {
return false
}
p = p.right
}
guard p.column == 15 || self[p] == .empty else { return false }
}
return laidTile
}
func nextMoves(vertical: Bool) -> [Board] {
var result: [Board] = []
func addIfPossible(_ p: Position, vertical: Bool, index: Int) {
if canAddBanana(p, vertical: vertical, index: index) {
let p = vertical ? Position(row: p.row-index, column: p.column) : Position(row: p.row, column: p.column-index)
result.append(self.byAdding(p, vertical: vertical))
}
}
for row in 0..<15 {
for column in 0..<15 {
let p = Position(row: row, column: column)
switch self[p] {
case .b:
addIfPossible(p, vertical: vertical, index: 0)
case .a:
addIfPossible(p, vertical: vertical, index: 1)
addIfPossible(p, vertical: vertical, index: 3)
addIfPossible(p, vertical: vertical, index: 5)
case .n:
addIfPossible(p, vertical: vertical, index: 2)
addIfPossible(p, vertical: vertical, index: 4)
case .empty:
break
}
}
}
return result
}
func nextMoves() -> [Board] {
return nextMoves(vertical: true) + nextMoves(vertical: false)
}
func description() -> String {
var result = ""
for row in 0..<15 {
for column in 0..<15 {
result.append(self[Position(row: row, column: column)].rawValue)
}
result.append("\n")
}
return result
}
}
var start = Board()
start.addBanana(Position(row: 7, column: 7), vertical: false)
var possibilities: [Set<Board>] = []
possibilities.append([start])
print("move 1: \(possibilities[0].count) moves")
for move in 1..<16 {
var new = Set<Board>()
for board in possibilities[move-1] {
new.formUnion(board.nextMoves())
}
possibilities.append(new)
print("move \(move+1): \(possibilities[move].count) moves")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment