Skip to content

Instantly share code, notes, and snippets.

@JoshuaSullivan
Last active November 21, 2020 17:13
Show Gist options
  • Save JoshuaSullivan/096f3d8a3f6950e9093f8bf363c5ba64 to your computer and use it in GitHub Desktop.
Save JoshuaSullivan/096f3d8a3f6950e9093f8bf363c5ba64 to your computer and use it in GitHub Desktop.
A helper for translating Advent of Code puzzle input into usable values.
//: # 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)
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