         
         return encrypt(from: text, key: newKey)
     }
-    
-    private func asciiIndex(withChar char: Character) -> UInt32 {
-        let unicodeScalars = String(char).unicodeScalars
-        
-        return unicodeScalars[unicodeScalars.startIndex].value
-    }
-    
-    private func encipherChar(char: Character, shiftBy shift: Int32, base: Character) -> Character {
-        let baseIndex = asciiIndex(withChar: base)
-        let charIndex = asciiIndex(withChar: char)
-        let resIndex = baseIndex + UInt32((Int32(charIndex) - Int32(baseIndex) + shift + 26) % 26)
-        
-        return Character(UnicodeScalar(resIndex)!)
-    }
-    
 }
 
 // MARK: - SubstitutionCipher

    }
}

// MARK: - Enigma
struct Enigma: Cryptography {
    var name = "Enigma"
    var defaultKey = "default key"
    
    func encrypt(from text: String, key: String) -> String? {
        guard let shift = Int(key) else {
            return nil
        }
        
        let newCharacters = text.characters.map { ch -> Character in
            let res: Character
            switch ch {
            case "a"..."z": res = encipherChar(char: ch, shiftBy: shift, base: "a")
            case "A"..."Z": res = encipherChar(char: ch, shiftBy: shift, base: "A")
            default: res = ch
            }
            return res
        }
        
        return String(newCharacters)
    }
    
    func decrypt(from text: String, key: String) -> String? {
        guard let newKey = key.reversedIntString() else {
            return nil
        }
        
        return encrypt(from: text, key: newKey)
    }
    
    private func encipherChar(char: Character, shiftBy: Int, base: Character) -> Character {
        let start = String(base).unicodeScalars
        
        let value = start[start.startIndex].value
        
        let index = (Int(value) + shiftBy) % 26
        
        return Character(UnicodeScalar(index)!)
    }
    
}


// MARK: - vigenère
struct Vigenere: Cryptography {
    var name = "Enigma"
    var defaultKey = "default key"
    
    func encrypt(from text: String, key: String) -> String? {
        guard let shift = Int(key) else {
            return nil
        }
        
        let newCharacters = text.characters.map { ch -> Character in
            let res: Character
            switch ch {
            case "a"..."z": res = encipherChar(char: ch, shiftBy: shift, base: "a")
            case "A"..."Z": res = encipherChar(char: ch, shiftBy: shift, base: "A")
            default: res = ch
            }
            return res
        }
        
        return String(newCharacters)
    }
    
    func decrypt(from text: String, key: String) -> String? {
        guard let newKey = key.reversedIntString() else {
            return nil
        }
        
        return encrypt(from: text, key: newKey)
    }
    
    private func encipherChar(char: Character, shiftBy: Int, base: Character) -> Character {
        let start = String(base).unicodeScalars
        
        let value = start[start.startIndex].value
        
        let index = (Int(value) + shiftBy) % 26
        
        return Character(UnicodeScalar(index)!)
    }

}



    func decrypt(from text: String, key: String) -> String?
}

extension Cryptography {
    fileprivate func asciiIndex(ofChar char: Character) -> UInt32 {
        let unicodeScalars = String(char).unicodeScalars
        
        return unicodeScalars[unicodeScalars.startIndex].value
    }
    
    fileprivate func encipherChar(char: Character, shiftBy shift: Int32, base: Character) -> Character {
        let baseIndex = asciiIndex(ofChar: base)
        let charIndex = asciiIndex(ofChar: char)
        let resIndex = baseIndex + UInt32((Int32(charIndex) - Int32(baseIndex) + shift + 26) % 26)
        
        return Character(UnicodeScalar(resIndex)!)
    }
    
    fileprivate func shiftOffset(ofChar char: Character) -> Int32 {
        let start: Character
        switch char {
        case "a"..."z": start = "a"
        case "A"..."Z": start = "A"
        default: start = char
        }
        return Int32(asciiIndex(ofChar: char) - asciiIndex(ofChar: start))
    }
}


// MARK: - CaesarCipher
struct CaesarCipher: Cryptography {
