// // File.swift // // // Created by Max Nuding on 05.12.21. // import Foundation import Runner import Collections struct Coord { let row: Int let col: Int func getLeft() -> Coord? { guard col > 0 else { return nil } return Coord(row: row, col: col - 1) } func getRight() -> Coord { Coord(row: row, col: col + 1) } func getAbove() -> Coord? { guard row > 0 else { return nil } return Coord(row: row - 1, col: col) } func getBelow() -> Coord { Coord(row: row + 1, col: col) } } struct Field:Sequence, IteratorProtocol { let numbers: [[Int]] let numCols: Int let numRows: Int var current: Coord? = Coord(row: 0, col: 0) init(numbers: [[Int]]) { self.numbers = numbers numCols = numbers.first!.count numRows = numbers.count } func getNeighborsCoordsFor(coord: Coord) -> [Coord] { return [coord.getAbove(), coord.getRight(), coord.getBelow(), coord.getLeft()] .compactMap { $0 } .filter { $0.row < numRows && $0.col < numCols } } func lowPointValueAt(coord: Coord) -> Int? { let value = numbers[coord.row][coord.col] return getNeighborsCoordsFor(coord: coord) .map { numbers[$0.row][$0.col] } .allSatisfy { $0 > value } ? value : nil } private func getNextCoord() -> Coord? { guard let current = current else { return nil } if current.col == numCols - 1 && current.row == numRows - 1 { return nil } if current.col == numCols - 1 { return Coord(row: current.row + 1, col: 0) } return Coord(row: current.row, col: current.col + 1) } mutating func next() -> Coord? { defer { current = getNextCoord() } return current } } struct Day09: Runnable { let inputPath: String func run() { let input = try! String(contentsOfFile: inputPath) let entries = input .trimmingCharacters(in: .newlines) .components(separatedBy: .newlines) .map { line in line.map { $0.wholeNumberValue! } } let field = Field(numbers: entries) let sum = field.compactMap { field.lowPointValueAt(coord: $0) }.reduce(0, { $0 + $1 + 1 }) print(sum) } }