Last active
December 20, 2016 14:31
-
-
Save DeepFriedTwinkie/7b41797b9b7d9ff5fd901e6308da1778 to your computer and use it in GitHub Desktop.
AdventOfCode.com 2016/Day 7 Solution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
//: ## Helpers | |
func string(fromFile name:String, fileExtension:String) -> String? { | |
if let filePath = Bundle.main.path(forResource:name, ofType:fileExtension) { | |
if let inputData = FileManager.default.contents(atPath: filePath) { | |
return String(data: inputData, encoding: .utf8) | |
} | |
} | |
return nil | |
} | |
//: ## Solution Objects and Functions | |
enum ParseStatus { | |
case evaluatingBody | |
case evaluatingHypernet | |
} | |
extension String { | |
var supportsTLS: Bool { | |
guard characters.count >= 4 else { return false } | |
var status = ParseStatus.evaluatingBody | |
var __firstIndex = characters.startIndex | |
var __secondIndex: Index { return characters.index(after: __firstIndex) } | |
var __thirdIndex: Index { return characters.index(after: __secondIndex) } | |
var __lastIndex: Index { return characters.index(after: __thirdIndex) } | |
var hasABBA = false | |
while __lastIndex < characters.endIndex { | |
// If the last character is a [ or ], just jump to the next char after it | |
switch characters[__lastIndex] { | |
case "[": | |
status = .evaluatingHypernet | |
__firstIndex = characters.index(after: __lastIndex) | |
continue | |
case "]": | |
status = .evaluatingBody | |
__firstIndex = characters.index(after: __lastIndex) | |
continue | |
default: | |
break | |
} | |
// Look for an ABBA | |
if characters[__firstIndex] == characters[__lastIndex] | |
&& characters[__firstIndex] != characters[__secondIndex] | |
&& characters[__secondIndex] == characters[__thirdIndex] { | |
// We're inside of a "Hypernet" so an existing ABBA means it doesn't support TLS | |
if status == .evaluatingHypernet { return false } | |
// We've found one, but let's keep going | |
hasABBA = true | |
} | |
__firstIndex = characters.index(after: __firstIndex) | |
} | |
return hasABBA | |
} | |
var supportsSSL: Bool { | |
guard characters.count >= 8 else { return false } | |
var invertedABAs = Set<String>() | |
var BABs = Set<String>() | |
var status = ParseStatus.evaluatingBody | |
var __firstIndex = characters.startIndex | |
var __secondIndex: Index { return characters.index(after: __firstIndex) } | |
var __lastIndex: Index { return characters.index(after: __secondIndex) } | |
while __lastIndex < characters.endIndex { | |
// If the last character is a [ or ], just jump to the next char after it | |
switch characters[__lastIndex] { | |
case "[": | |
status = .evaluatingHypernet | |
__firstIndex = characters.index(after: __lastIndex) | |
continue | |
case "]": | |
status = .evaluatingBody | |
__firstIndex = characters.index(after: __lastIndex) | |
continue | |
default: | |
break | |
} | |
// Look for an ABA/BAB | |
if characters[__firstIndex] == characters[__lastIndex] | |
&& characters[__firstIndex] != characters[__secondIndex] { | |
if status == .evaluatingHypernet { | |
// Inside the "hypernet" so store the BAB as it was found | |
BABs.insert(String(characters[__firstIndex...__lastIndex])) | |
} else { | |
// Outside the hypernet, so store the ABA like a BAB (makes comparison easier later | |
let chars = [characters[__secondIndex], | |
characters[__firstIndex], | |
characters[__secondIndex] | |
] | |
invertedABAs.insert(String(chars)) | |
} | |
} | |
__firstIndex = characters.index(after: __firstIndex) | |
} | |
// A simple intersection of BABs and reversed ABAs will determine if it supports SSL | |
// At least one in common: supports it | |
return BABs.intersection(invertedABAs).count > 0 | |
} | |
} | |
//: ## Input Processing | |
let day = "Day7" | |
let testInput = "aba[bab]xyz\nxyx[xyx]xyx\naaa[kek]eke\nzazbz[bzb]cdb" | |
func prepareInput() -> [String] { | |
if let inputString = string(fromFile: day, fileExtension: "txt") { | |
return inputString.components(separatedBy: "\n") | |
} | |
return [String]() | |
} | |
let ips = prepareInput() | |
//let ips = testInput.components(separatedBy: "\n") | |
//: ## Solution Execution | |
//: ### Part 1 | |
let tlsIPs = ips.filter({ $0.supportsTLS }) | |
print("Part 1 Answer: \(tlsIPs.count)\n") | |
//: ### Part 2 | |
let sslIPs = ips.filter({ $0.supportsSSL }) | |
print("Part 2 Answer: \(sslIPs.count)\n") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment