Skip to content

Instantly share code, notes, and snippets.

@rjstelling
Last active January 24, 2020 12:49

Revisions

  1. rjstelling revised this gist Jan 24, 2020. 1 changed file with 28 additions and 29 deletions.
    57 changes: 28 additions & 29 deletions BaseFunctions.swift
    Original file line number Diff line number Diff line change
    @@ -1,41 +1,56 @@
    import Foundation

    enum StringSearchError: Swift.Error {
    public enum StringSearchError: Swift.Error {
    case didNotFind(Character)
    }

    extension String {

    fileprivate static let DefaultDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    fileprivate static let DefaultEmoji = "πŸ€–β€οΈβ˜ οΈπŸ€“πŸ¦πŸ†πŸ§€πŸ˜ŽπŸ™„πŸ€’πŸ§ πŸ§ΆπŸ™ˆπŸ™‰πŸ™ŠπŸ”₯πŸ₯•βš½οΈπŸ’ŠπŸŽΆπŸ§Ά"
    static let ReducedDigits = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789"
    static let DefaultBase36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    static let DefaultDigits = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    static let DefaultEmoji = "πŸ€–β€οΈβ˜ οΈπŸ€“πŸ¦πŸ†πŸ§€πŸ˜ŽπŸ™„πŸ€’πŸ§ πŸ§ΆπŸ™ˆπŸ™‰πŸ™ŠπŸ”₯πŸ₯•βš½οΈπŸ’ŠπŸŽΆπŸ§Ά"

    func character<T>(at index: T) -> String where T: FixedWidthInteger {
    internal func character<T>(at index: T) -> String where T: FixedWidthInteger {
    return String(self[self.index(self.startIndex, offsetBy: Int(index))])
    }

    func position(of char: Character) throws -> Int {
    fileprivate func position(of char: Character) throws -> Int {
    guard let idx = self.firstIndex(of: char) else { throw StringSearchError.didNotFind(char) }
    return Int( self.distance(from: self.startIndex, to: idx) )
    }
    }

    enum BaseError: Swift.Error {
    extension String {

    public func decode<T: FixedWidthInteger & UnsignedInteger>() throws -> T { return try self.decode(T(String.ReducedDigits.count), using: .ReducedDigits) }

    private func decode<T>(_ redux: T, using digits: String = .DefaultDigits) throws -> T where T: FixedWidthInteger & UnsignedInteger {

    let decoded = try self.reduce(T(0)) {
    let value = T( try digits.position(of: $1) )
    return ($0 * redux) + value
    }

    return decoded
    }
    }

    public enum BaseError: Swift.Error {
    case outOfRange
    }

    extension FixedWidthInteger where Self.Magnitude : UnsignedInteger {

    func base36() -> String { return try! self.base(36) }
    func base62() -> String { return try! self.base(62) }
    func baseEmoji() -> String { return try! self.base(String.DefaultEmoji.count, using: String.DefaultEmoji) }

    func base<T>(_ redux: T, using digits: String = .DefaultDigits) throws -> String where T: FixedWidthInteger {
    public func encode() throws -> String { return try self.base(String.ReducedDigits.count, using: .ReducedDigits) }

    private func encode<T>(_ redux: T, using digits: String = .DefaultDigits) throws -> String where T: FixedWidthInteger {

    guard 1...digits.count ~= Int(redux) else { throw BaseError.outOfRange }

    var result = ""
    var value = Int(self)
    let rdx = Int(redux)
    var value = T(self)
    let rdx = redux

    repeat {
    result = digits.character(at: value % rdx) + result
    @@ -44,20 +59,4 @@ extension FixedWidthInteger where Self.Magnitude : UnsignedInteger {

    return result
    }
    }

    extension String {

    func decode36() -> Int { return try! self.decode(36) }
    func decode62() -> Int { return try! self.decode(62) }

    func decode(_ redux: Int, using digits: String = .DefaultDigits) throws -> Int {

    let decoded = try self.reduce(0) {
    let value = Double( try digits.position(of: $1) )
    return Int( Double($0) * Double(redux) + value )
    }

    return decoded
    }
    }
  2. rjstelling revised this gist Jan 9, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion BaseFunctions.swift
    Original file line number Diff line number Diff line change
    @@ -55,7 +55,7 @@ extension String {

    let decoded = try self.reduce(0) {
    let value = Double( try digits.position(of: $1) )
    return Int( ( Double($0) + (value/Double(redux)) ) * Double(redux) )
    return Int( Double($0) * Double(redux) + value )
    }

    return decoded
  3. rjstelling created this gist Jan 4, 2019.
    63 changes: 63 additions & 0 deletions BaseFunctions.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    import Foundation

    enum StringSearchError: Swift.Error {
    case didNotFind(Character)
    }

    extension String {

    fileprivate static let DefaultDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    fileprivate static let DefaultEmoji = "πŸ€–β€οΈβ˜ οΈπŸ€“πŸ¦πŸ†πŸ§€πŸ˜ŽπŸ™„πŸ€’πŸ§ πŸ§ΆπŸ™ˆπŸ™‰πŸ™ŠπŸ”₯πŸ₯•βš½οΈπŸ’ŠπŸŽΆπŸ§Ά"

    func character<T>(at index: T) -> String where T: FixedWidthInteger {
    return String(self[self.index(self.startIndex, offsetBy: Int(index))])
    }

    func position(of char: Character) throws -> Int {
    guard let idx = self.firstIndex(of: char) else { throw StringSearchError.didNotFind(char) }
    return Int( self.distance(from: self.startIndex, to: idx) )
    }
    }

    enum BaseError: Swift.Error {
    case outOfRange
    }

    extension FixedWidthInteger where Self.Magnitude : UnsignedInteger {

    func base36() -> String { return try! self.base(36) }
    func base62() -> String { return try! self.base(62) }
    func baseEmoji() -> String { return try! self.base(String.DefaultEmoji.count, using: String.DefaultEmoji) }

    func base<T>(_ redux: T, using digits: String = .DefaultDigits) throws -> String where T: FixedWidthInteger {

    guard 1...digits.count ~= Int(redux) else { throw BaseError.outOfRange }

    var result = ""
    var value = Int(self)
    let rdx = Int(redux)

    repeat {
    result = digits.character(at: value % rdx) + result
    value /= rdx
    } while (value > 0)

    return result
    }
    }

    extension String {

    func decode36() -> Int { return try! self.decode(36) }
    func decode62() -> Int { return try! self.decode(62) }

    func decode(_ redux: Int, using digits: String = .DefaultDigits) throws -> Int {

    let decoded = try self.reduce(0) {
    let value = Double( try digits.position(of: $1) )
    return Int( ( Double($0) + (value/Double(redux)) ) * Double(redux) )
    }

    return decoded
    }
    }