Skip to content

Instantly share code, notes, and snippets.

@congnd
Created February 21, 2020 00:17
Show Gist options
  • Save congnd/41e3a6ab127b49a980cd600951c00e3a to your computer and use it in GitHub Desktop.
Save congnd/41e3a6ab127b49a980cd600951c00e3a to your computer and use it in GitHub Desktop.
Swift solution for roman-to-integer challenge: https://leetcode.com/problems/roman-to-integer
class Solution {
func romanToInt(_ s: String) -> Int {
var iterator = s.utf8CString.makeIterator()
var result: Int = 0
var current: RomanCharacter?
current = iterator.getNext()
while let unwrappedCurrent = current {
if !unwrappedCurrent.isSubtract {
result += unwrappedCurrent.intValue
current = iterator.getNext()
continue
}
if let follower = iterator.getNext() {
if (unwrappedCurrent.canBeFollowedBy(follower)) {
result += unwrappedCurrent.intValueWhenCombined(with: follower)
current = iterator.getNext()
continue
} else {
result += unwrappedCurrent.intValue
current = follower
continue
}
}
result += unwrappedCurrent.intValue
current = iterator.getNext()
}
return result
}
}
extension IndexingIterator {
mutating func getNext() -> RomanCharacter? {
guard let n = next() else { return nil }
guard let character = RomanCharacter(rawValue: n as! CChar) else {
return nil
}
return character
}
}
enum RomanCharacter: CChar {
case I = 73
case V = 86
case X = 88
case L = 76
case C = 67
case D = 68
case M = 77
var intValue: Int {
switch self {
case .I: return 1
case .V: return 5
case .X: return 10
case .L: return 50
case .C: return 100
case .D: return 500
case .M: return 1000
}
}
func intValueWhenCombined(with c: RomanCharacter) -> Int {
switch (self, c) {
case (.I, .V): return 4
case (.I, .X): return 9
case (.X, .L): return 40
case (.X, .C): return 90
case (.C, .D): return 400
case (.C, .M): return 900
default: return 0
}
}
var isSubtract: Bool {
switch self {
case .I, .X, .C: return true
case .V, .L, .D, .M: return false
}
}
func canBeFollowedBy(_ character: RomanCharacter) -> Bool {
switch self {
case .V, .L, .D, .M: return false
case .I: return [RomanCharacter.V, RomanCharacter.X].contains(character)
case .X: return [RomanCharacter.L, RomanCharacter.C].contains(character)
case .C: return [RomanCharacter.D, RomanCharacter.M].contains(character)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment