CUSIP: Difference between revisions
Content deleted Content added
Add Swift |
|||
Line 2,327: | Line 2,327: | ||
68389X1059 not valid. |
68389X1059 not valid. |
||
68389x105 not valid.</pre> |
68389x105 not valid.</pre> |
||
=={{header|Swift}}== |
|||
<lang 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") |
|||
} |
|||
}</lang> |
|||
{{out}} |
|||
<pre>037833100 -> Valid |
|||
17275R102 -> Valid |
|||
38259P508 -> Valid |
|||
594918104 -> Valid |
|||
68389X106 -> Invalid |
|||
68389X105 -> Valid</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |