Skip to content

Commit b95d9b6

Browse files
Richard TurtonRichard Turton
authored andcommitted
Initial commit - at blog post three
0 parents  commit b95d9b6

File tree

7 files changed

+408
-0
lines changed

7 files changed

+408
-0
lines changed

.gitignore

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Xcode
2+
#
3+
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4+
5+
## Build generated
6+
build/
7+
DerivedData/
8+
9+
## Various settings
10+
*.pbxuser
11+
!default.pbxuser
12+
*.mode1v3
13+
!default.mode1v3
14+
*.mode2v3
15+
!default.mode2v3
16+
*.perspectivev3
17+
!default.perspectivev3
18+
xcuserdata/
19+
20+
## Other
21+
*.moved-aside
22+
*.xcuserstate
23+
24+
## Obj-C/Swift specific
25+
*.hmap
26+
*.ipa
27+
*.dSYM.zip
28+
*.dSYM
29+
30+
## Playgrounds
31+
timeline.xctimeline
32+
playground.xcworkspace
33+
34+
# Swift Package Manager
35+
#
36+
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37+
# Packages/
38+
.build/
39+
40+
# CocoaPods
41+
#
42+
# We recommend against adding the Pods directory to your .gitignore. However
43+
# you should judge for yourself, the pros and cons are mentioned at:
44+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45+
#
46+
# Pods/
47+
48+
# Carthage
49+
#
50+
# Add this line if you want to avoid checking in source code from Carthage dependencies.
51+
# Carthage/Checkouts
52+
53+
Carthage/Build
54+
55+
# fastlane
56+
#
57+
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58+
# screenshots whenever they are needed.
59+
# For more information about the recommended setup visit:
60+
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
61+
62+
fastlane/report.xml
63+
fastlane/Preview.html
64+
fastlane/screenshots
65+
fastlane/test_output

Pentominoes.playground/Contents.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//: Playground - noun: a place where people can play
2+
3+
import UIKit
4+
5+
6+
7+
let board = Board(size: .FiveByTwelve)
8+
9+
let tile = Tile(shape: .O)
10+
11+
for boardSquare in board.squares() {
12+
if board.canPositionTile(tile, atSquare: boardSquare) {
13+
print("Can position at \(boardSquare)")
14+
}
15+
}
16+
17+
tile.rotate(true)
18+
print("Rotated")
19+
20+
for boardSquare in board.squares() {
21+
if board.canPositionTile(tile, atSquare: boardSquare) {
22+
print("Can position at \(boardSquare)")
23+
}
24+
}
25+
26+
27+
28+
29+
30+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
public class Board: PlayingGrid {
2+
3+
private (set) public var rows: [[Bool]]
4+
5+
public struct Size {
6+
let height: Int
7+
let width: Int
8+
9+
public static let SixByTen = Size(height: 6, width: 10)
10+
public static let FiveByTwelve = Size(height: 5, width: 12)
11+
public static let FourByFifteen = Size(height: 4, width: 15)
12+
public static let ThreeByTwenty = Size(height: 3, width: 20)
13+
}
14+
15+
public init(size: Size) {
16+
// Extend by four "occupied" positions in every direction
17+
let paddingHorizontal = [Bool].init(count: 4, repeatedValue: true)
18+
let paddingVertical = [Bool].init(count: 8 + size.width, repeatedValue: true)
19+
let fullPaddingVertical = [[Bool]].init(count: 4, repeatedValue: paddingVertical)
20+
let emptyRow = [Bool].init(count: size.width, repeatedValue: false)
21+
rows = fullPaddingVertical
22+
for _ in 0..<size.height {
23+
rows += [paddingHorizontal + emptyRow + paddingHorizontal]
24+
}
25+
rows += fullPaddingVertical
26+
}
27+
}
28+
29+
extension Board {
30+
public func canPositionTile(tile: Tile, atSquare: Square) -> Bool {
31+
32+
for tileSquare in tile.squares() {
33+
let boardSquare = tileSquare.offsetBy(atSquare)
34+
if !squareWithinBoard(boardSquare) {
35+
return false
36+
}
37+
if tileSquare.occupied == true && squareOccupied(boardSquare) {
38+
return false
39+
}
40+
}
41+
return true
42+
}
43+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
public protocol PlayingGrid : CustomStringConvertible, CustomPlaygroundQuickLookable {
2+
var rows: [[Bool]] { get }
3+
subscript(row: Int) -> [Bool] { get }
4+
}
5+
6+
extension Bool {
7+
var gridCharacter: String {
8+
return self ? "#" : "_"
9+
}
10+
}
11+
12+
extension PlayingGrid where Self: protocol<CustomStringConvertible, CustomPlaygroundQuickLookable> {
13+
public var description: String {
14+
let descriptions : [String] = rows.map { row in
15+
row.reduce("") { string, gridValue in
16+
string + gridValue.gridCharacter
17+
}
18+
}
19+
return descriptions.joinWithSeparator("\n")
20+
}
21+
public func customPlaygroundQuickLook() -> PlaygroundQuickLook {
22+
return PlaygroundQuickLook(reflecting: description)
23+
}
24+
}
25+
26+
27+
public struct Square {
28+
let row: Int
29+
let column: Int
30+
let occupied: Bool?
31+
32+
public init(row: Int, column: Int, occupied: Bool? = nil) {
33+
self.row = row
34+
self.column = column
35+
self.occupied = occupied
36+
}
37+
38+
func offsetBy(square: Square) -> Square {
39+
return Square(row: self.row + square.row, column: self.column + square.column)
40+
41+
}
42+
}
43+
44+
public class GridSquareGenerator: GeneratorType {
45+
var currentRow: Int = 0
46+
var currentColumn: Int = -1
47+
48+
let grid: PlayingGrid
49+
50+
public init(grid: PlayingGrid) {
51+
self.grid = grid
52+
}
53+
54+
public func next() -> Square? {
55+
guard currentRow < grid.rows.count else { return nil }
56+
57+
currentColumn += 1
58+
59+
if currentColumn == grid[currentRow].count {
60+
currentColumn = 0
61+
currentRow += 1
62+
}
63+
if currentRow < grid.rows.count {
64+
return Square(row: currentRow, column: currentColumn, occupied: grid[currentRow][currentColumn])
65+
} else {
66+
return nil
67+
}
68+
}
69+
}
70+
71+
public class GridSquareSequence: SequenceType {
72+
let grid: PlayingGrid
73+
74+
public init(grid: PlayingGrid) {
75+
self.grid = grid
76+
}
77+
78+
public func generate() -> GridSquareGenerator {
79+
return GridSquareGenerator(grid: grid)
80+
}
81+
}
82+
83+
extension PlayingGrid {
84+
public func squares() -> GridSquareSequence {
85+
return GridSquareSequence(grid: self)
86+
}
87+
}
88+
89+
90+
extension PlayingGrid {
91+
public subscript(row: Int) -> [Bool] {
92+
get {
93+
return rows[row]
94+
}
95+
}
96+
97+
public func squareWithinBoard(square: Square) -> Bool {
98+
return square.row < rows.count && square.column < rows[square.row].count
99+
}
100+
101+
public func squareOccupied(square: Square) -> Bool {
102+
return self[square.row][square.column]
103+
}
104+
}
105+
106+
107+

0 commit comments

Comments
 (0)