// // File.swift // // // Created by Max Nuding on 05.12.21. // import Foundation import Runner import Collections struct Day10: Runnable { let inputPath: String public func run() { let input = try! String(contentsOfFile: inputPath) let lines = input .trimmingCharacters(in: .newlines) .components(separatedBy: .newlines) //.map { line in line.map { $0.wholeNumberValue! } } var s = Deque() var illegalCharacters = [String.Element]() for (lineNumber, line) in lines.enumerated() { for char in line { if char.isClosing { if let popped = s.popFirst() { if let shouldBeClosedBy = popped.closedBy { if shouldBeClosedBy == char { continue // Valid chunk } print("Line: \(lineNumber): Expected \(shouldBeClosedBy), but found \(char) instead") illegalCharacters.append(char) break } else { print("\(popped) should be an opening character, but cannot find a fitting closing char. Line: \(lineNumber+1), char: \(char)") } } else { print("Found closing character \(char), but empty list!") } } s.prepend(char) } } print(illegalCharacters.map{$0.score!}.reduce(0,+)) } } extension String.Element { var isClosing: Bool { self == "]" || self == ")" || self == ">" || self == "}" } var closedBy: String.Element? { switch self { case "[": return "]" case "(": return ")" case "{": return "}" case "<": return ">" default: return nil } } var score: Int? { switch self { case ")": return 3 case "]": return 57 case "}": return 1197 case ">": return 25137 default: return nil } } }