Skip to content

Instantly share code, notes, and snippets.

@bnickel
Last active August 29, 2015 14:02
Show Gist options
  • Save bnickel/7e070ab65dd5cdee621a to your computer and use it in GitHub Desktop.
Save bnickel/7e070ab65dd5cdee621a to your computer and use it in GitHub Desktop.
Infinite prime sequences in Objective-C and Swift
@import Foundation;
@interface PrimeEnumerator : NSObject<NSFastEnumeration>
- (NSArray *)knownPrimes;
@end
@interface PrimeEnumerator ()
@property (nonatomic, strong) NSMutableArray *primes;
@end
@implementation PrimeEnumerator
- (instancetype)init
{
self = [super init];
if (self) {
_primes = [NSMutableArray arrayWithObject:@2];
}
return self;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id [])buffer count:(NSUInteger)len
{
if (state->state == 0) {
state->extra[0] = 0;
state->state = 1;
state->mutationsPtr = &(state->state);
}
unsigned long index = state->extra[0];
unsigned long lastKnownPrime = state->extra[1];
for (NSUInteger i = 0; i < len; i ++) {
if (index < self.primes.count) {
lastKnownPrime = [(buffer[i] = self.primes[index++]) unsignedLongValue];
continue;
}
while ([self isDivisibleByKnownPrimes:++lastKnownPrime]) ;
NSNumber *primeNumber = @(lastKnownPrime);
buffer[i] = primeNumber;
[self.primes addObject:primeNumber];
index = self.primes.count;
}
state->extra[0] = index;
state->extra[1] = lastKnownPrime;
state->itemsPtr = buffer;
return len;
}
- (BOOL)isDivisibleByKnownPrimes:(unsigned long)number
{
unsigned long limit = ceilf(sqrtf(number));
for (NSNumber *prime in self.primes) {
unsigned long primeValue = [prime unsignedIntegerValue];
if (number % primeValue == 0) {
return YES;
}
if (primeValue > limit) {
break;
}
}
return NO;
}
- (NSArray *)knownPrimes
{
return self.primes;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
for (NSNumber *prime in [[PrimeEnumerator alloc] init]) {
if ([prime isGreaterThan:@1000]) {
break;
}
NSLog(@"%@", prime);
}
}
return 0;
}
import Foundation
struct PrimeGenerator:GeneratorType {
let sequence:PrimeSequence
var index = 0
init (_ sequence:PrimeSequence) {
self.sequence = sequence
}
mutating func next() -> Int? {
if index == sequence.knownPrimes.count {
sequence.findNextPrime()
}
return sequence.knownPrimes[index++]
}
}
class PrimeSequence:SequenceType {
var knownPrimes = [2]
func generate() -> PrimeGenerator {
return PrimeGenerator(self)
}
func findNextPrime() {
var lastKnownPrime = knownPrimes[knownPrimes.count - 1]
while isDivisibleByKnownPrimes(++lastKnownPrime) { }
knownPrimes.append(lastKnownPrime)
}
func isDivisibleByKnownPrimes(number:Int) -> Bool {
let limit = Int(ceilf(sqrtf(CFloat(number))));
for prime in knownPrimes {
if number % prime == 0 { return true }
if prime > limit { break }
}
return false
}
}
for i in PrimeSequence() {
if i > 1000 { break }
println(i)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment