Rename Rotor.swift -> Components.swift
This commit is contained in:
parent
b7798d2dcd
commit
bb1ba6a1fc
2 changed files with 108 additions and 4 deletions
|
@ -15,7 +15,7 @@
|
||||||
C0DA3A9B1B5AACB300D8D68E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C0DA3A991B5AACB300D8D68E /* LaunchScreen.storyboard */; };
|
C0DA3A9B1B5AACB300D8D68E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C0DA3A991B5AACB300D8D68E /* LaunchScreen.storyboard */; };
|
||||||
C0DA3AA61B5AACB300D8D68E /* EnigmaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DA3AA51B5AACB300D8D68E /* EnigmaTests.swift */; };
|
C0DA3AA61B5AACB300D8D68E /* EnigmaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DA3AA51B5AACB300D8D68E /* EnigmaTests.swift */; };
|
||||||
C0DA3AB11B5AACB300D8D68E /* EnigmaUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DA3AB01B5AACB300D8D68E /* EnigmaUITests.swift */; };
|
C0DA3AB11B5AACB300D8D68E /* EnigmaUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DA3AB01B5AACB300D8D68E /* EnigmaUITests.swift */; };
|
||||||
C0DA3ABF1B5AB49200D8D68E /* Rotor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DA3ABE1B5AB49200D8D68E /* Rotor.swift */; };
|
C0DA3ABF1B5AB49200D8D68E /* Components.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DA3ABE1B5AB49200D8D68E /* Components.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
C0DA3AAC1B5AACB300D8D68E /* EnigmaUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EnigmaUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
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 = "<group>"; };
|
C0DA3AB01B5AACB300D8D68E /* EnigmaUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnigmaUITests.swift; sourceTree = "<group>"; };
|
||||||
C0DA3AB21B5AACB300D8D68E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
C0DA3AB21B5AACB300D8D68E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
C0DA3ABE1B5AB49200D8D68E /* Rotor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rotor.swift; sourceTree = "<group>"; };
|
C0DA3ABE1B5AB49200D8D68E /* Components.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Components.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
C0DA3A971B5AACB300D8D68E /* Assets.xcassets */,
|
C0DA3A971B5AACB300D8D68E /* Assets.xcassets */,
|
||||||
C0DA3A991B5AACB300D8D68E /* LaunchScreen.storyboard */,
|
C0DA3A991B5AACB300D8D68E /* LaunchScreen.storyboard */,
|
||||||
C0DA3A9C1B5AACB300D8D68E /* Info.plist */,
|
C0DA3A9C1B5AACB300D8D68E /* Info.plist */,
|
||||||
C0DA3ABE1B5AB49200D8D68E /* Rotor.swift */,
|
C0DA3ABE1B5AB49200D8D68E /* Components.swift */,
|
||||||
C04D337E1B5B3F6100E2888E /* Enigma.swift */,
|
C04D337E1B5B3F6100E2888E /* Enigma.swift */,
|
||||||
);
|
);
|
||||||
path = Enigma;
|
path = Enigma;
|
||||||
|
@ -262,7 +262,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
C04D337F1B5B3F6100E2888E /* Enigma.swift in Sources */,
|
C04D337F1B5B3F6100E2888E /* Enigma.swift in Sources */,
|
||||||
C0DA3ABF1B5AB49200D8D68E /* Rotor.swift in Sources */,
|
C0DA3ABF1B5AB49200D8D68E /* Components.swift in Sources */,
|
||||||
C0DA3A931B5AACB300D8D68E /* ViewController.swift in Sources */,
|
C0DA3A931B5AACB300D8D68E /* ViewController.swift in Sources */,
|
||||||
C0DA3A911B5AACB300D8D68E /* AppDelegate.swift in Sources */,
|
C0DA3A911B5AACB300D8D68E /* AppDelegate.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|
104
Enigma/Components.swift
Normal file
104
Enigma/Components.swift
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
//
|
||||||
|
// Components.swift
|
||||||
|
// Enigma
|
||||||
|
//
|
||||||
|
// Created by Eryn Wells on 2015-07-18.
|
||||||
|
// Copyright © 2015 Eryn Wells. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
enum EncoderError: ErrorType {
|
||||||
|
/** Thrown when an input character is found that is not in the alphabet. */
|
||||||
|
case InvalidCharacter(ch: Character)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protocol Encoder {
|
||||||
|
func encode(c: Character) throws -> Character
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Cryptor {
|
||||||
|
/** Array of all possible characters to encrypt. */
|
||||||
|
static let alphabet: [Character] = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FixedRotor: Cryptor, Encoder {
|
||||||
|
enum Error: ErrorType {
|
||||||
|
/** Thrown when the initializer is given an invalid series. */
|
||||||
|
case InvalidSeries
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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.series = series
|
||||||
|
super.init()
|
||||||
|
guard series.count == Cryptor.alphabet.count else {
|
||||||
|
throw Error.InvalidSeries
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(c: Character) throws -> Character {
|
||||||
|
if let offset = FixedRotor.alphabet.indexOf(c) {
|
||||||
|
return series[offset]
|
||||||
|
} else {
|
||||||
|
throw EncoderError.InvalidCharacter(ch: c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Rotors are FixedRotors that have a variable position, which offsets the alphabet from the series and changes which character is substituted for a given input. */
|
||||||
|
class Rotor: FixedRotor {
|
||||||
|
/** The position of first letter in `series` in the `alphabet`. */
|
||||||
|
var position: Int = 0 {
|
||||||
|
willSet {
|
||||||
|
self.position = newValue % Cryptor.alphabet.count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func advance(count: Int = 1) {
|
||||||
|
position = (position + count) % Rotor.alphabet.count
|
||||||
|
}
|
||||||
|
|
||||||
|
override func encode(c: Character) throws -> Character {
|
||||||
|
if let offset = Rotor.alphabet.indexOf(c) {
|
||||||
|
return series[(offset + position) % series.count]
|
||||||
|
} else {
|
||||||
|
throw EncoderError.InvalidCharacter(ch: c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Reflector: FixedRotor { }
|
||||||
|
|
||||||
|
|
||||||
|
/** A Plugboard is a Cryptor that substitutes one character for another based on a set of pairs. A pair of characters is mutually exclusive of other pairs; that is, a character can only belong to one pair. Furthermore, the Plugboard always trades one character for the same character and vice versa. */
|
||||||
|
class Plugboard: Cryptor, Encoder {
|
||||||
|
private(set) var plugs: [Character: Character] = [:]
|
||||||
|
|
||||||
|
func addPlug(a: Character, b: Character) {
|
||||||
|
plugs[a] = b
|
||||||
|
plugs[b] = a
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(c: Character) throws -> Character {
|
||||||
|
if let output = plugs[c] {
|
||||||
|
return output
|
||||||
|
} else if Plugboard.alphabet.contains(c) {
|
||||||
|
return c
|
||||||
|
} else {
|
||||||
|
throw EncoderError.InvalidCharacter(ch: c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue