From f4b39829868e171c710e58b7555598b5d227a386 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 18 Jul 2015 10:23:54 -0700 Subject: [PATCH] Rotor class --- Enigma.xcodeproj/project.pbxproj | 4 +++ Enigma/Rotor.swift | 50 ++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 Enigma/Rotor.swift diff --git a/Enigma.xcodeproj/project.pbxproj b/Enigma.xcodeproj/project.pbxproj index c6c0d5a..5e5edd2 100644 --- a/Enigma.xcodeproj/project.pbxproj +++ b/Enigma.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ C0DA3A9B1B5AACB300D8D68E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C0DA3A991B5AACB300D8D68E /* LaunchScreen.storyboard */; }; C0DA3AA61B5AACB300D8D68E /* EnigmaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DA3AA51B5AACB300D8D68E /* EnigmaTests.swift */; }; C0DA3AB11B5AACB300D8D68E /* EnigmaUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DA3AB01B5AACB300D8D68E /* EnigmaUITests.swift */; }; + C0DA3ABF1B5AB49200D8D68E /* Rotor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DA3ABE1B5AB49200D8D68E /* Rotor.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -47,6 +48,7 @@ C0DA3AAC1B5AACB300D8D68E /* EnigmaUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EnigmaUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C0DA3AB01B5AACB300D8D68E /* EnigmaUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnigmaUITests.swift; sourceTree = ""; }; C0DA3AB21B5AACB300D8D68E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C0DA3ABE1B5AB49200D8D68E /* Rotor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rotor.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -103,6 +105,7 @@ C0DA3A971B5AACB300D8D68E /* Assets.xcassets */, C0DA3A991B5AACB300D8D68E /* LaunchScreen.storyboard */, C0DA3A9C1B5AACB300D8D68E /* Info.plist */, + C0DA3ABE1B5AB49200D8D68E /* Rotor.swift */, ); path = Enigma; sourceTree = ""; @@ -255,6 +258,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C0DA3ABF1B5AB49200D8D68E /* Rotor.swift in Sources */, C0DA3A931B5AACB300D8D68E /* ViewController.swift in Sources */, C0DA3A911B5AACB300D8D68E /* AppDelegate.swift in Sources */, ); diff --git a/Enigma/Rotor.swift b/Enigma/Rotor.swift new file mode 100644 index 0000000..2516d76 --- /dev/null +++ b/Enigma/Rotor.swift @@ -0,0 +1,50 @@ +// +// Rotor.swift +// Enigma +// +// Created by Eryn Wells on 2015-07-18. +// Copyright © 2015 Eryn Wells. All rights reserved. +// + +import Foundation + + +class Rotor { + enum Error: ErrorType { + /** Thrown when the initializer is given an invalid series. */ + case InvalidSeries + case InvalidCharacter + } + + static let alphabet: [Character] = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters) + + /** The position of first letter in `series` in the `alphabet`. */ + var position: Int + /** The series of characters that this rotor cycles through. */ + let series: [Character]! + + convenience init(series: String) throws { + try self.init(series: Array(series.characters)) + } + + init(series: [Character]) throws { + self.position = 0 + guard series.count == Rotor.alphabet.count else { + self.series = nil + throw Error.InvalidSeries + } + self.series = series + } + + func advance() { + position = position.successor() % Rotor.alphabet.count + } + + func encode(c: Character) throws -> Character { + let offset: Int! = Rotor.alphabet.indexOf(c) + guard offset != nil else { + throw Error.InvalidCharacter + } + return series[(offset + position) % series.count] + } +} \ No newline at end of file