@@ -142,12 +142,146 @@ func solveTSP<T>(cities: [T], distances: [T: [T: Int]]) -> (solution: [T], dista
142
142
let vtTSP = solveTSP ( cities: vtCities, distances: vtDistances)
143
143
print ( " The shortest path is \( vtTSP. solution) in \( vtTSP. distance) miles. " )
144
144
145
- //func dog(test: inout [String]) {
146
- // test.append("hello")
147
- //
148
- //}
145
+ /// Phone Number Mnemonics
146
+
147
+ let phoneMapping : [ Character : [ Character ] ] = [ " 1 " : [ " 1 " ] , " 2 " : [ " a " , " b " , " c " ] , " 3 " : [ " d " , " e " , " f " ] , " 4 " : [ " g " , " h " , " i " ] , " 5 " : [ " j " , " k " , " l " ] , " 6 " : [ " m " , " n " , " o " ] , " 7 " : [ " p " , " q " , " r " , " s " ] , " 8 " : [ " t " , " u " , " v " ] , " 9 " : [ " w " , " x " , " y " , " z " ] , " 0 " : [ " 0 " ] ]
148
+
149
+
150
+ // return all of the possible characters combos, given a mapping, for a given number
151
+ func stringToPossibilities( _ s: String , mapping: [ Character : [ Character ] ] ) -> [ [ Character ] ] {
152
+ let possibilities = s. characters. flatMap { mapping [ 0ドル] }
153
+ print ( possibilities)
154
+ return combineAllPossibilities ( possibilities)
155
+ }
156
+
157
+ // takes a set of possible characters for each position and finds all possible permutations
158
+ func combineAllPossibilities( _ possibilities: [ [ Character ] ] ) -> [ [ Character ] ] {
159
+ guard let possibility = possibilities. first else { return [ [ ] ] }
160
+ var permutations : [ [ Character ] ] = possibility. map { [ 0ドル] } // turn each into an array
161
+ for possibility in possibilities [ 1 ..< possibilities. count] where possibility != [ ] {
162
+ let toRemove = permutations. count // temp
163
+ for permutation in permutations {
164
+ for c in possibility { // try adding every letter
165
+ var newPermutation : [ Character ] = permutation // need a mutable copy
166
+ newPermutation. append ( c) // add character on the end
167
+ permutations. append ( newPermutation) // new combo ready
168
+ }
169
+ }
170
+ permutations. removeFirst ( toRemove) // remove combos missing new last letter
171
+ }
172
+ return permutations
173
+ }
174
+
175
+ let permutations = stringToPossibilities ( " 1440787 " , mapping: phoneMapping)
176
+
177
+ /// Tic-tac-toe
178
+
179
+ enum Piece : String {
180
+ case X = " X "
181
+ case O = " O "
182
+ case E = " "
183
+ var opposite : Piece {
184
+ switch self {
185
+ case . X:
186
+ return . O
187
+ case . O:
188
+ return . X
189
+ case . E:
190
+ return . E
191
+ }
192
+ }
193
+ }
194
+
195
+ // a move is an integer 0-9 indicating a place to put a piece
196
+ typealias Move = Int
197
+
198
+ struct Board {
199
+ let position : [ Piece ]
200
+ let turn : Piece
201
+ let lastMove : Move
202
+
203
+ // the legal moves in a position are all of the empty squares
204
+ var legalMoves : [ Move ] {
205
+ return position. indices. filter { position [ 0ドル] == . E }
206
+ }
207
+
208
+ // by default the board is empty and X goes first
209
+ // lastMove being -1 is a marker of a start position
210
+ init ( position: [ Piece ] = [ . E, . E, . E, . E, . E, . E, . E, . E, . E] , turn: Piece = . X, lastMove: Int = - 1 ) {
211
+ self . position = position
212
+ self . turn = turn
213
+ self . lastMove = lastMove
214
+ }
215
+
216
+ // location can be 0-8, indicating where to move
217
+ // return a new board with the move played
218
+ func move( _ location: Move ) -> Board {
219
+ var tempPosition = position
220
+ tempPosition [ location] = turn
221
+ return Board ( position: tempPosition, turn: turn. opposite, lastMove: location)
222
+ }
223
+
224
+ var isWin : Bool {
225
+ return
226
+ position [ 0 ] == position [ 1 ] && position [ 0 ] == position [ 2 ] && position [ 0 ] != . E || // row 0
227
+ position [ 3 ] == position [ 4 ] && position [ 3 ] == position [ 5 ] && position [ 3 ] != . E || // row 1
228
+ position [ 6 ] == position [ 7 ] && position [ 6 ] == position [ 8 ] && position [ 6 ] != . E || // row 2
229
+ position [ 0 ] == position [ 3 ] && position [ 0 ] == position [ 6 ] && position [ 0 ] != . E || // col 0
230
+ position [ 1 ] == position [ 4 ] && position [ 1 ] == position [ 7 ] && position [ 1 ] != . E || // col 1
231
+ position [ 2 ] == position [ 5 ] && position [ 2 ] == position [ 8 ] && position [ 2 ] != . E || // col 2
232
+ position [ 0 ] == position [ 4 ] && position [ 0 ] == position [ 8 ] && position [ 0 ] != . E || // diag 0
233
+ position [ 2 ] == position [ 4 ] && position [ 2 ] == position [ 6 ] && position [ 2 ] != . E // diag 1
234
+
235
+ }
236
+
237
+ var isDraw : Bool {
238
+ return !isWin && legalMoves. count == 0
239
+ }
240
+ }
241
+
242
+ func minimax( _ board: Board , maximizing: Bool ) -> ( eval: Int , bestMove: Move ) {
243
+ if board. isWin { return ( 1 , board. lastMove) }
244
+ else if board. isDraw { return ( 0 , board. lastMove) }
245
+
246
+ if maximizing {
247
+ var bestEval : ( eval: Int , bestMove: Move ) = ( Int . min, - 1 )
248
+ for move in board. legalMoves {
249
+ let result = minimax ( board. move ( move) , maximizing: false )
250
+ if result. eval > bestEval. eval { bestEval = result }
251
+ }
252
+ return bestEval
253
+ } else { // minimizing
254
+ var worstEval : ( eval: Int , bestMove: Move ) = ( Int . max, - 1 )
255
+ for move in board. legalMoves {
256
+ let result = minimax ( board. move ( move) , maximizing: true )
257
+ if result. eval < worstEval. eval { worstEval = result }
258
+ }
259
+ return worstEval
260
+ }
261
+ }
262
+
263
+ // win in 1 move
264
+ let toWinEasyPosition : [ Piece ] = [ . X, . O, . X,
265
+ . X, . E, . O,
266
+ . E, . E, . O]
267
+ let testBoard1 : Board = Board ( position: toWinEasyPosition, turn: . X, lastMove: 8 )
268
+ let answer1 = minimax ( testBoard1, maximizing: true )
269
+ print ( answer1. bestMove)
149
270
150
- // City 0
271
+ // must block O's win
272
+ let toBlockPosition : [ Piece ] = [ . X, . E, . E,
273
+ . E, . E, . O,
274
+ . E, . X, . O]
275
+ let testBoard2 : Board = Board ( position: toBlockPosition, turn: . X, lastMove: 8 )
276
+ let answer2 = minimax ( testBoard2, maximizing: true )
277
+ print ( answer2. bestMove)
151
278
279
+ // find the best move to win in 2 moves
280
+ let toWinHardPosition : [ Piece ] = [ . X, . E, . E,
281
+ . E, . E, . O,
282
+ . O, . X, . E]
283
+ let testBoard3 : Board = Board ( position: toWinHardPosition, turn: . X, lastMove: 6 )
284
+ let answer3 = minimax ( testBoard3, maximizing: true )
285
+ print ( answer3. bestMove)
152
286
//: [Next](@next)
153
287
0 commit comments