68 lines
1.4 KiB
Swift
68 lines
1.4 KiB
Swift
struct CUSIP {
|
|
var value: String
|
|
|
|
private static let alphabet = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
|
|
init?(value: String) {
|
|
if value.count == 9 && String(value.last!) == CUSIP.checkDigit(cusipString: String(value.dropLast())) {
|
|
self.value = value
|
|
} else if value.count == 8, let checkDigit = CUSIP.checkDigit(cusipString: value) {
|
|
self.value = value + checkDigit
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
static func checkDigit(cusipString: String) -> String? {
|
|
guard cusipString.count == 8, cusipString.allSatisfy({ $0.isASCII }) else {
|
|
return nil
|
|
}
|
|
|
|
let sum = cusipString.uppercased().enumerated().reduce(0, {sum, pair in
|
|
let (i, char) = pair
|
|
var v: Int
|
|
|
|
switch char {
|
|
case "*":
|
|
v = 36
|
|
case "@":
|
|
v = 37
|
|
case "#":
|
|
v = 38
|
|
case _ where char.isNumber:
|
|
v = char.wholeNumberValue!
|
|
case _:
|
|
v = Int(char.asciiValue! - 65) + 10
|
|
}
|
|
|
|
if i & 1 == 1 {
|
|
v *= 2
|
|
}
|
|
|
|
return sum + (v / 10) + (v % 10)
|
|
})
|
|
|
|
return String((10 - (sum % 10)) % 10)
|
|
}
|
|
}
|
|
|
|
let testCases = [
|
|
"037833100",
|
|
"17275R102",
|
|
"38259P508",
|
|
"594918104",
|
|
"68389X106",
|
|
"68389X105"
|
|
]
|
|
|
|
for potentialCUSIP in testCases {
|
|
print("\(potentialCUSIP) -> ", terminator: "")
|
|
|
|
switch CUSIP(value: potentialCUSIP) {
|
|
case nil:
|
|
print("Invalid")
|
|
case _:
|
|
print("Valid")
|
|
}
|
|
}
|