d12
This commit is contained in:
		
							
								
								
									
										93
									
								
								day12/d12p2.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								day12/d12p2.swift
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| import Foundation | ||||
|  | ||||
| struct Plot : Hashable, CustomStringConvertible { | ||||
|     let x: Int | ||||
|     let y: Int | ||||
|     var description: String { return "Plot(\(x), \(y))" } | ||||
| } | ||||
|  | ||||
| struct Map : CustomStringConvertible { | ||||
|     let map: [[Character]] | ||||
|     let (w, h): (Int, Int) | ||||
|     var visited: [[Bool]] | ||||
|  | ||||
|     var description: String { | ||||
|         var ret: String = "\(w)x\(h):\n" | ||||
|         for i in 0..<map.count { | ||||
|             for j in 0..<map[i].count { | ||||
|                 ret.append(map[i][j]) | ||||
|                 ret.append(visited[i][j] ? "." : " ") | ||||
|             } | ||||
|             ret.append("\n") | ||||
|         } | ||||
|         return ret | ||||
|     } | ||||
|     init(_ map: [[Character]]) { | ||||
|         self.map = map | ||||
|         self.visited = map.map { $0.map { _ in false } } | ||||
|         self.h = map.count | ||||
|         self.w = map[0].count | ||||
|     } | ||||
|  | ||||
|     // visits a plot; returns its perimeter contribution & unvisited neighbors | ||||
|     mutating func visit(_ plot: Plot) -> (Int, [Plot]) { | ||||
|         let (x, y) = (plot.x, plot.y) | ||||
|         visited[x][y] = true | ||||
|         let all_nbs = [(x-1, y), (x+1, y), (x, y-1), (x, y+1)] | ||||
|         let peri = all_nbs.filter { i, j in | ||||
|             i < 0 || j < 0 || i >= h || j >= w || map[i][j] != map[x][y] | ||||
|         }.count | ||||
|         let nbs = all_nbs.filter { i, j in | ||||
|             i >= 0 && j >= 0 && i < h && j < w && | ||||
|             map[i][j] == map[x][y] && | ||||
|             !visited[i][j] | ||||
|         }.map { i, j in Plot(x: i, y: j) } | ||||
|         return (peri, nbs) | ||||
|     } | ||||
|  | ||||
|     mutating func visitAll(from plot: Plot) -> Int { | ||||
|         var q: Set<Plot> = [plot] | ||||
|         var region: Set<Plot> = [] | ||||
|         var peri = 0 | ||||
|         var area = 0 | ||||
|         while !q.isEmpty { | ||||
|             let currentPlot = q.removeFirst() | ||||
|             let (newPeri, newNBs) = visit(currentPlot) | ||||
|             region.insert(currentPlot) | ||||
|             peri += newPeri | ||||
|             area += 1 | ||||
|             q.formUnion(newNBs) | ||||
|         } | ||||
|         for i in -1..<h { | ||||
|             for j in -1..<w { | ||||
|                 let ul = region.contains(Plot(x: i, y: j)) | ||||
|                 let ur = region.contains(Plot(x: i, y: j+1)) | ||||
|                 let ll = region.contains(Plot(x: i+1, y: j)) | ||||
|                 let lr = region.contains(Plot(x: i+1, y: j+1)) | ||||
|                 if (ul && ur && !ll && !lr) || (ul && !ur && ll && !lr) || | ||||
|                    (!ul && ur && !ll && lr) || (!ul && !ur && ll && lr) { | ||||
|                     peri -= 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         print("\(map[plot.x][plot.y]): \(area)x\(peri)") | ||||
|         return peri * area | ||||
|     } | ||||
| } | ||||
|  | ||||
| func readInput(_ filePath: String) throws -> Map { | ||||
|     let content = try String(contentsOfFile: filePath, encoding: .ascii) | ||||
|     return Map(content.split(separator: "\n").map(Array.init)) | ||||
| } | ||||
|  | ||||
| var map = try readInput(CommandLine.arguments[1]) | ||||
| print(map) | ||||
| var answer = 0 | ||||
| for i in 0..<map.h { | ||||
|     for j in 0..<map.w { | ||||
|         if !map.visited[i][j] { | ||||
|             answer += map.visitAll(from: Plot(x: i, y: j)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| print(answer) | ||||
		Reference in New Issue
	
	Block a user