Skip to content

Instantly share code, notes, and snippets.

@zrzka
Created October 30, 2015 12:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zrzka/723ea6e900c90b91ca3f to your computer and use it in GitHub Desktop.
Save zrzka/723ea6e900c90b91ca3f to your computer and use it in GitHub Desktop.
Swift - OptionSetType - single option random generator
//: Playground - noun: a place where people can play
import Foundation
struct MathOperation : OptionSetType {
let rawValue: Int
init(rawValue: Int) {
self.rawValue = rawValue
}
static let Addition = MathOperation(rawValue: 1)
static let Subtraction = MathOperation(rawValue: 2)
static let Multiplication = MathOperation(rawValue: 4)
static let Division = MathOperation(rawValue: 8)
static let All: MathOperation = [.Addition, .Subtraction, .Multiplication, .Division]
}
extension MathOperation : CustomStringConvertible {
var description: String {
var result = [String]()
if contains(.Addition) { result.append("+") }
if contains(.Subtraction) { result.append("-") }
if contains(.Multiplication) { result.append("*") }
if contains(.Division) { result.append("/") }
return "<MathOperation: \(result.joinWithSeparator(" "))>"
}
}
/// Same associativity & precedence as `<<`
infix operator <<? {
associativity none
precedence 160
}
/// Return `lhs` with left shift applied or `nil` if overflow happens
func <<? <T: IntegerType>(lhs: T, var rhs: Int) -> T? {
guard rhs != 0 else { return lhs }
guard rhs > 0 else { return nil }
// Implementation with `&*`
var result = (lhs, lhs) // (previous, current)
while rhs-- > 0 {
result = (result.1, result.1 &* 2)
if result.1 < result.0 { return nil } // overflow
}
return result.1
// Implementation with `_IntegerArithmeticType.multiplyWithOverflow`
// var result = lhs
// var overflow: Bool
// while rhs-- > 0 {
// (result, overflow) = T.multiplyWithOverflow(result, 2)
// if overflow { return nil }
// }
// return result
}
class BitValuesGenerator<Element : IntegerType> : AnyGenerator<Element> {
var bitValue: Element? = 1
override func next() -> Element? {
guard let currentBitValue = bitValue else { return nil }
bitValue = currentBitValue <<? 1
return currentBitValue
}
}
extension OptionSetType where RawValue : IntegerType {
var array: [Self] {
return AnySequence(BitValuesGenerator<RawValue>())
.filter({ $0 & self.rawValue == $0 })
.map({ Self(rawValue: $0) })
}
}
extension OptionSetType where RawValue : IntegerType {
func randomGenerator() -> AnyGenerator<Self> {
var singleOptions = array
return anyGenerator {
guard singleOptions.count > 0 else { return nil }
return singleOptions[Int(arc4random_uniform(UInt32(singleOptions.count)))]
}
}
}
let generator = MathOperation.All.randomGenerator()
generator.next()
generator.next()
generator.next()
generator.next()
generator.next()
generator.next()
let ui8 = AnySequence(BitValuesGenerator<UInt8>()).reduce("") { $0.isEmpty ? "\($1)" : "\($0) \($1)" }
let i8 = AnySequence(BitValuesGenerator<Int8>()).reduce("") { $0.isEmpty ? "\($1)" : "\($0) \($1)" }
print(ui8)
print(i8)
@zrzka
Copy link
Author

zrzka commented Oct 30, 2015

playground-screenshot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment