Last active
November 21, 2020 17:13
-
-
Save JoshuaSullivan/096f3d8a3f6950e9093f8bf363c5ba64 to your computer and use it in GitHub Desktop.
A helper for translating Advent of Code puzzle input into usable values.
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
//: # Advent of Code 2019 | |
//: ### Day 3 - Crossed Wires | |
//: | |
//: [Prev](@prev) <---> [Next](@next) | |
import Foundation | |
struct Wire: StringInitable, CustomStringConvertible { | |
enum Direction: String { | |
case up = "U" | |
case down = "D" | |
case right = "R" | |
case left = "L" | |
} | |
let direction: Direction | |
let length: Int | |
init?(_ string: String) { | |
guard | |
let dirChar = string.first, | |
let dir = Direction(rawValue: String(dirChar)), | |
let len = Int(string.dropFirst()) | |
else { return nil } | |
self.direction = dir | |
self.length = len | |
} | |
var description: String { | |
"Wire[\(direction.rawValue), \(length)]" | |
} | |
} | |
//: Load data. | |
let parser = DataParser<Wire>() | |
guard let parseResult = try? parser.parseCSVLines(fileName: "input") else { | |
fatalError("Could not read in data.") | |
} | |
print(parseResult) |
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 | |
/// A type that can be initialized from a string value. | |
/// | |
public protocol StringInitable { | |
/// Initialize the object with a string. | |
/// | |
/// - Note: This operation can fail if the string is not valid for this object type. | |
/// | |
init?(_ string: String) | |
} | |
extension Int: StringInitable {} | |
extension String: StringInitable {} | |
/// A helper object that can parse raw string data into structured values. | |
/// | |
public struct DataParser<T: StringInitable> { | |
/// Parsing-specific errors. | |
public enum Error: Swift.Error { | |
/// Unable to load or parse the input. | |
case unableToReadInput | |
} | |
public init() {} | |
/// Parse where input values are separated by newlines. | |
/// | |
public func parseLines(fileName: String) throws -> [T] { | |
return try loadDataString(from: fileName) | |
.split(separator: "\n") | |
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } | |
.compactMap { T($0) } | |
} | |
/// Parse where input values are separated by commas. | |
/// | |
public func parseCSV(fileName: String) throws -> [T] { | |
return try loadDataString(from: fileName) | |
.split(separator: ",") | |
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } | |
.compactMap { T($0) } | |
} | |
/// Parse where there are multiple lines and each line is comma-separated. | |
/// | |
public func parseCSVLines(fileName: String) throws -> [[T]] { | |
return try loadDataString(from: fileName) | |
.split(separator: "\n") | |
.map { line in | |
line | |
.split(separator: ",") | |
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } | |
.compactMap { T($0) } | |
} | |
} | |
/// Attempt to load the input file from the Resources folder. | |
/// | |
private func loadDataString(from fileName: String) throws -> String { | |
guard let dataURL = Bundle.main.url(forResource: fileName, withExtension: nil) else { | |
throw Error.unableToReadInput | |
} | |
return try String(contentsOf: dataURL) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment