d12
This commit is contained in:
		
							
								
								
									
										78
									
								
								day12/d12p1.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								day12/d12p1.swift
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| 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 peri = 0 | ||||
|         var area = 0 | ||||
|         while !q.isEmpty { | ||||
|             let currentPlot = q.removeFirst() | ||||
|             let (newPeri, newNBs) = visit(currentPlot) | ||||
|             peri += newPeri | ||||
|             area += 1 | ||||
|             q.formUnion(newNBs) | ||||
|         } | ||||
|         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