Day 23
This commit is contained in:
parent
67d4d86e81
commit
ba6cee935a
2 changed files with 369 additions and 0 deletions
|
@ -7,6 +7,8 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
26132D372774C886004F0228 /* day23.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26132D2B2774C871004F0228 /* day23.swift */; };
|
||||||
|
26132D382774C886004F0228 /* common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 269BE5CB2762A08800871C85 /* common.swift */; };
|
||||||
2615545A276A6C2C00374D18 /* day14.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26155459276A6C2C00374D18 /* day14.swift */; };
|
2615545A276A6C2C00374D18 /* day14.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26155459276A6C2C00374D18 /* day14.swift */; };
|
||||||
2615545B276A6C3200374D18 /* common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 269BE5CB2762A08800871C85 /* common.swift */; };
|
2615545B276A6C3200374D18 /* common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 269BE5CB2762A08800871C85 /* common.swift */; };
|
||||||
26155468276A6D0A00374D18 /* day15.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26155467276A6D0A00374D18 /* day15.swift */; };
|
26155468276A6D0A00374D18 /* day15.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26155467276A6D0A00374D18 /* day15.swift */; };
|
||||||
|
@ -44,6 +46,15 @@
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
26132D2E2774C87D004F0228 /* CopyFiles */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = /usr/share/man/man1/;
|
||||||
|
dstSubfolderSpec = 0;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 1;
|
||||||
|
};
|
||||||
26155450276A6C1C00374D18 /* CopyFiles */ = {
|
26155450276A6C1C00374D18 /* CopyFiles */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -200,6 +211,8 @@
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
26132D2B2774C871004F0228 /* day23.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = day23.swift; sourceTree = "<group>"; };
|
||||||
|
26132D302774C87D004F0228 /* Day23 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Day23; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
26155452276A6C1C00374D18 /* Day14 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Day14; sourceTree = BUILT_PRODUCTS_DIR; };
|
26155452276A6C1C00374D18 /* Day14 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Day14; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
26155459276A6C2C00374D18 /* day14.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = day14.swift; sourceTree = "<group>"; };
|
26155459276A6C2C00374D18 /* day14.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = day14.swift; sourceTree = "<group>"; };
|
||||||
26155460276A6CF700374D18 /* Day15 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Day15; sourceTree = BUILT_PRODUCTS_DIR; };
|
26155460276A6CF700374D18 /* Day15 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Day15; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
@ -238,6 +251,13 @@
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
26132D2D2774C87D004F0228 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
2615544F276A6C1C00374D18 /* Frameworks */ = {
|
2615544F276A6C1C00374D18 /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -363,6 +383,7 @@
|
||||||
263BA594275E974800839C92 = {
|
263BA594275E974800839C92 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
26132D2B2774C871004F0228 /* day23.swift */,
|
||||||
2680ECFB27732A9400CAB23C /* day22.swift */,
|
2680ECFB27732A9400CAB23C /* day22.swift */,
|
||||||
2680ECE22771D82400CAB23C /* day21.swift */,
|
2680ECE22771D82400CAB23C /* day21.swift */,
|
||||||
2680ECDF2770A2FC00CAB23C /* day20.swift */,
|
2680ECDF2770A2FC00CAB23C /* day20.swift */,
|
||||||
|
@ -405,6 +426,7 @@
|
||||||
2680ECD82770A2E900CAB23C /* Day20 */,
|
2680ECD82770A2E900CAB23C /* Day20 */,
|
||||||
2680ECE72771D82F00CAB23C /* Day21 */,
|
2680ECE72771D82F00CAB23C /* Day21 */,
|
||||||
2680ECF427732A8300CAB23C /* Day22 */,
|
2680ECF427732A8300CAB23C /* Day22 */,
|
||||||
|
26132D302774C87D004F0228 /* Day23 */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -412,6 +434,23 @@
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
26132D2F2774C87D004F0228 /* Day23 */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 26132D342774C87D004F0228 /* Build configuration list for PBXNativeTarget "Day23" */;
|
||||||
|
buildPhases = (
|
||||||
|
26132D2C2774C87D004F0228 /* Sources */,
|
||||||
|
26132D2D2774C87D004F0228 /* Frameworks */,
|
||||||
|
26132D2E2774C87D004F0228 /* CopyFiles */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = Day23;
|
||||||
|
productName = Day23;
|
||||||
|
productReference = 26132D302774C87D004F0228 /* Day23 */;
|
||||||
|
productType = "com.apple.product-type.tool";
|
||||||
|
};
|
||||||
26155451276A6C1C00374D18 /* Day14 */ = {
|
26155451276A6C1C00374D18 /* Day14 */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 26155458276A6C1C00374D18 /* Build configuration list for PBXNativeTarget "Day14" */;
|
buildConfigurationList = 26155458276A6C1C00374D18 /* Build configuration list for PBXNativeTarget "Day14" */;
|
||||||
|
@ -712,6 +751,9 @@
|
||||||
LastUpgradeCheck = 1310;
|
LastUpgradeCheck = 1310;
|
||||||
ORGANIZATIONNAME = 5sw;
|
ORGANIZATIONNAME = 5sw;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
26132D2F2774C87D004F0228 = {
|
||||||
|
CreatedOnToolsVersion = 13.2.1;
|
||||||
|
};
|
||||||
26155451276A6C1C00374D18 = {
|
26155451276A6C1C00374D18 = {
|
||||||
CreatedOnToolsVersion = 13.1;
|
CreatedOnToolsVersion = 13.1;
|
||||||
LastSwiftMigration = 1310;
|
LastSwiftMigration = 1310;
|
||||||
|
@ -806,11 +848,21 @@
|
||||||
2680ECD72770A2E900CAB23C /* Day20 */,
|
2680ECD72770A2E900CAB23C /* Day20 */,
|
||||||
2680ECE62771D82F00CAB23C /* Day21 */,
|
2680ECE62771D82F00CAB23C /* Day21 */,
|
||||||
2680ECF327732A8300CAB23C /* Day22 */,
|
2680ECF327732A8300CAB23C /* Day22 */,
|
||||||
|
26132D2F2774C87D004F0228 /* Day23 */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
26132D2C2774C87D004F0228 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
26132D372774C886004F0228 /* day23.swift in Sources */,
|
||||||
|
26132D382774C886004F0228 /* common.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
2615544E276A6C1C00374D18 /* Sources */ = {
|
2615544E276A6C1C00374D18 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -967,6 +1019,30 @@
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
|
26132D352774C87D004F0228 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 722B335UM5;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 12.1;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
26132D362774C87D004F0228 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 722B335UM5;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 12.1;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
26155456276A6C1C00374D18 /* Debug */ = {
|
26155456276A6C1C00374D18 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
@ -1616,6 +1692,15 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
26132D342774C87D004F0228 /* Build configuration list for PBXNativeTarget "Day23" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
26132D352774C87D004F0228 /* Debug */,
|
||||||
|
26132D362774C87D004F0228 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
26155458276A6C1C00374D18 /* Build configuration list for PBXNativeTarget "Day14" */ = {
|
26155458276A6C1C00374D18 /* Build configuration list for PBXNativeTarget "Day14" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|
284
day23.swift
Normal file
284
day23.swift
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct Day23: Puzzle {
|
||||||
|
func run() {
|
||||||
|
part1()
|
||||||
|
part2()
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1() {
|
||||||
|
var board = Board(height: 3)
|
||||||
|
board.fillHomeRow(for: .a, pieces: [.c, .c])
|
||||||
|
board.fillHomeRow(for: .b, pieces: [.b, .d])
|
||||||
|
board.fillHomeRow(for: .c, pieces: [.a, .a])
|
||||||
|
board.fillHomeRow(for: .d, pieces: [.d, .b])
|
||||||
|
board.show()
|
||||||
|
print("Part 1:", find(start: board))
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2() {
|
||||||
|
var board = Board(height: 5)
|
||||||
|
board.fillHomeRow(for: .a, pieces: [.c, .d, .d, .c])
|
||||||
|
board.fillHomeRow(for: .b, pieces: [.b, .c, .b, .d])
|
||||||
|
board.fillHomeRow(for: .c, pieces: [.a, .b, .a, .a])
|
||||||
|
board.fillHomeRow(for: .d, pieces: [.d, .a, .c, .b])
|
||||||
|
board.show()
|
||||||
|
print("Part 2:", find(start: board))
|
||||||
|
}
|
||||||
|
|
||||||
|
func find(start: Board) -> Int {
|
||||||
|
let target = Board.makeGoal(height: start.height)
|
||||||
|
var current = start
|
||||||
|
var totalCost = 0
|
||||||
|
|
||||||
|
var possible: [Board: Int] = [:]
|
||||||
|
var visited: Set<Board> = []
|
||||||
|
|
||||||
|
|
||||||
|
while current != target {
|
||||||
|
visited.insert(current)
|
||||||
|
|
||||||
|
for (next, cost) in current.possibleMoves() where !visited.contains(next) {
|
||||||
|
possible[next] = min(possible[next, default: .max], totalCost + cost)
|
||||||
|
}
|
||||||
|
|
||||||
|
(current, totalCost) = possible.min { $0.value < $1.value }!
|
||||||
|
|
||||||
|
possible.removeValue(forKey: current)
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalCost
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Board: Hashable {
|
||||||
|
enum Piece: CaseIterable, Hashable, CustomStringConvertible {
|
||||||
|
case a, b, c, d
|
||||||
|
|
||||||
|
var homeColumn: Int {
|
||||||
|
switch self {
|
||||||
|
case .a:
|
||||||
|
return 2
|
||||||
|
case .b:
|
||||||
|
return 4
|
||||||
|
case .c:
|
||||||
|
return 6
|
||||||
|
case .d:
|
||||||
|
return 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cost: Int {
|
||||||
|
switch self {
|
||||||
|
case .a:
|
||||||
|
return 1
|
||||||
|
case .b:
|
||||||
|
return 10
|
||||||
|
case .c:
|
||||||
|
return 100
|
||||||
|
case .d:
|
||||||
|
return 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sign: Character {
|
||||||
|
switch self {
|
||||||
|
case .a:
|
||||||
|
return "A"
|
||||||
|
case .b:
|
||||||
|
return "B"
|
||||||
|
case .c:
|
||||||
|
return "C"
|
||||||
|
case .d:
|
||||||
|
return "D"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var description: String { String(sign) }
|
||||||
|
}
|
||||||
|
enum Cell: Hashable {
|
||||||
|
case piece(Piece)
|
||||||
|
case empty
|
||||||
|
case outside
|
||||||
|
}
|
||||||
|
|
||||||
|
var width = 11
|
||||||
|
var height = 3
|
||||||
|
|
||||||
|
var board: [Cell]
|
||||||
|
|
||||||
|
init(height: Int) {
|
||||||
|
self.height = height
|
||||||
|
board = Array(repeating: .outside, count: width * height)
|
||||||
|
for x in 0..<width {
|
||||||
|
self[x, 0] = .empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func fillHomeRow(for piece: Piece, pieces: [Piece]) {
|
||||||
|
precondition(pieces.count == height - 1)
|
||||||
|
let x = piece.homeColumn
|
||||||
|
for (y, piece) in pieces.enumerated() {
|
||||||
|
self[x, y + 1] = .piece(piece)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func makeGoal(height: Int) -> Self {
|
||||||
|
var board = Self(height: height)
|
||||||
|
for piece in Piece.allCases {
|
||||||
|
for y in 1..<board.height {
|
||||||
|
board[piece.homeColumn, y] = .piece(piece)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return board
|
||||||
|
}
|
||||||
|
|
||||||
|
func movablePieces() -> [(Piece, Int, Int)] {
|
||||||
|
var result: [(Piece, Int, Int)] = []
|
||||||
|
for x in 0..<width {
|
||||||
|
if case .piece(let piece) = self[x, 0] {
|
||||||
|
result.append((piece, x, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for home in Piece.allCases {
|
||||||
|
let x = home.homeColumn
|
||||||
|
var y = 1
|
||||||
|
while y < height, case .empty = self[x, y] {
|
||||||
|
y += 1
|
||||||
|
}
|
||||||
|
if y < height, case let .piece(piece) = self[x, y] {
|
||||||
|
result.append((piece, x, y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func possibleMoves() -> [(Board, Int)] {
|
||||||
|
let pieces = movablePieces()
|
||||||
|
.filter { !isHome(piece: $0.0, x: $0.1, y: $0.2) }
|
||||||
|
|
||||||
|
var result: [(Board, Int)] = []
|
||||||
|
for (piece, x, y) in pieces {
|
||||||
|
if let newY = freeHomeRowPosition(piece: piece), freeCorridor(from: x, to: piece.homeColumn) {
|
||||||
|
result.append(move(piece: piece, from: (x, y), to: (piece.homeColumn, newY)))
|
||||||
|
}
|
||||||
|
|
||||||
|
for newX in openCorridorPositions(x: x) {
|
||||||
|
result.append(move(piece: piece, from: (x, y), to: (newX, 0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func freeCorridor(from x0: Int, to x1: Int) -> Bool {
|
||||||
|
let minX: Int
|
||||||
|
let maxX: Int
|
||||||
|
|
||||||
|
if x0 < x1 { (minX, maxX) = (x0 + 1, x1) }
|
||||||
|
else { (minX, maxX) = (x1, x0 - 1) }
|
||||||
|
|
||||||
|
for x in minX...maxX {
|
||||||
|
if self[x, 0] != .empty {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func move(piece: Piece, from: (Int, Int), to: (Int, Int)) -> (Board, Int) {
|
||||||
|
let (x, y) = from
|
||||||
|
let (newX, newY) = to
|
||||||
|
|
||||||
|
precondition(self[newX,newY] == .empty)
|
||||||
|
|
||||||
|
let cost = (y + distance((x, 0), (newX, newY))) * piece.cost
|
||||||
|
var board = self
|
||||||
|
board[x, y] = .empty
|
||||||
|
board[newX, newY] = .piece(piece)
|
||||||
|
|
||||||
|
return (board, cost)
|
||||||
|
}
|
||||||
|
|
||||||
|
func freeHomeRowPosition(piece: Piece) -> Int? {
|
||||||
|
let x = piece.homeColumn
|
||||||
|
var depth = height - 1
|
||||||
|
|
||||||
|
loop: while depth > 0 {
|
||||||
|
switch self[x, depth] {
|
||||||
|
case .piece(piece): break
|
||||||
|
case .piece: return nil
|
||||||
|
case .empty: break loop
|
||||||
|
case .outside: preconditionFailure("Invalid board")
|
||||||
|
}
|
||||||
|
depth -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return depth
|
||||||
|
}
|
||||||
|
|
||||||
|
static let homeColumns = Set(Piece.allCases.map(\.homeColumn))
|
||||||
|
|
||||||
|
func openCorridorPositions(x: Int) -> [Int] {
|
||||||
|
var xmin = x
|
||||||
|
var xmax = x
|
||||||
|
|
||||||
|
while xmin > 0 && self[xmin, 0] == .empty {
|
||||||
|
xmin -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
while xmax < width && self[xmax, 0] == .empty {
|
||||||
|
xmax += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = (xmin..<xmax).filter { !Self.homeColumns.contains($0) && self[$0,0] == .empty }
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func distance(_ a: (Int, Int), _ b: (Int, Int)) -> Int {
|
||||||
|
let (x0, y0) = a
|
||||||
|
let (x1, y1) = b
|
||||||
|
|
||||||
|
return abs(x1 - x0) + abs(y1 - y0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isHome(piece: Piece, x: Int, y: Int) -> Bool {
|
||||||
|
guard x == piece.homeColumn && y > 0 else { return false }
|
||||||
|
for otherY in (y + 1)..<height {
|
||||||
|
if self[x, otherY] != .piece(piece) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func show() {
|
||||||
|
print(String(repeating: "#", count: width + 2))
|
||||||
|
for y in 0..<height {
|
||||||
|
var line = ""
|
||||||
|
for x in 0..<width {
|
||||||
|
switch self[x, y] {
|
||||||
|
case .outside:
|
||||||
|
line += "#"
|
||||||
|
case .empty: line += "."
|
||||||
|
case .piece(let piece): line.append(piece.sign)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print("#\(line)#")
|
||||||
|
}
|
||||||
|
print(String(repeating: "#", count: width + 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
subscript(x: Int, y: Int) -> Cell {
|
||||||
|
get {
|
||||||
|
board[x + width * y]
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
board[x + width * y] = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue