iPhone radix sort

今日は、radix sortっぽく動くiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@interface ViewController ()

@property (nonatomic, strong) NSMutableArray *cards;

@property int state;

@property int timeCounter;

@property (nonatomic, copy) NSNumber* (^simpleBlock)(id);

@property (nonatomic, weak) UIView *marker;

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor greenColor];

    

    [self createTitle];

    [self createCards];

    [self createButton];

}

– (void)createTitle

{

    UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 320, 60)];

    title.text = @”radix sort?”;

    title.textAlignment = NSTextAlignmentCenter;

    title.font = [UIFont boldSystemFontOfSize:40];

    title.textColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7];

    [self.view addSubview:title];

    

    CALayer *line = [CALayer layer];

    line.frame = CGRectMake(0, CGRectGetMaxY(title.frame), 320, 10);

    line.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8].CGColor;

    [self.view.layer addSublayer:line];

}

– (void)createCards

{

    self.cards = [NSMutableArray array];

    for (int i=0; i<9; i++) {

        UIView *card = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 30)];

        card.tag = i + 1;

        card.center = CGPointMake(160, i * 35 + 120);

        card.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.9];

        [self.view addSubview:card];

        

        for (int j=0; j<3; j++) {

            UILabel *number = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 20, 30)];

            number.tag = j + 10; // i != j

            number.text = [NSString stringWithFormat:@”%d”, (arc4random() % 8) + 1];

            number.center = CGPointMake(j * 10 + 20, 15);

            number.font = [UIFont boldSystemFontOfSize:18];

            [card addSubview:number];

        }

        

        [self.cards addObject:card];

    }

}

– (void)createButton

{

    CALayer *line = [CALayer layer];

    line.frame = CGRectMake(0, 470, 320, 10);

    line.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8].CGColor;

    [self.view.layer addSublayer:line];

    

    UIButton *sortButton = [UIButton buttonWithType:UIButtonTypeSystem];

    [sortButton setTitle:@”sort” forState:UIControlStateNormal];

    [sortButton setTitleColor:[[UIColor whiteColor] colorWithAlphaComponent:0.8] forState:UIControlStateNormal];

    sortButton.titleLabel.font = [UIFont boldSystemFontOfSize:40];

    [sortButton sizeToFit];

    sortButton.center = CGPointMake(160, 520);

    

    [sortButton addTarget:self action:@selector(sort) forControlEvents:UIControlEventTouchUpInside];

    

    [self.view addSubview:sortButton];

}

– (void)sort

{

    if (!self.marker) {

        UIView *marker = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 320)];

        marker.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.6];

        [self.view addSubview:marker];

        marker.center = CGPointMake(200, 260);

        self.marker = marker;

    }

    

    CGPoint mp = self.marker.center;

    int tag = 0;

    if (self.state == 0) {

        // sort one

        tag = 12;

        mp = CGPointMake(170, 260);

    } else if (self.state == 1) {

        // sort ten

        tag = 11;

        mp = CGPointMake(160, 260);

    } else {

        // sort hundred

        tag = 10;

        mp = CGPointMake(150, 260);

    }

    

    [UIView animateWithDuration:0.5 animations:^{

        self.marker.center = mp;

    }];

    

    self.simpleBlock = ^(id card) {

        if ([card isKindOfClass:[UIView class]]) {

            return @(((UILabel *)[card viewWithTag:tag]).text.intValue);

        }

        return (NSNumber *)card;

    };

    

    [self mergeSort:self.cards indexP:0 indexR:(int)self.cards.count1];

    

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        [UIView animateWithDuration:0.2 animations:^{

            int idx = 0;

            for (UIView *v in self.cards) {

                v.center = CGPointMake(v.center.x, idx * 35 + 120);

                idx++;

            }

        }];

    });

    

    self.state++;

}

– (void)mergeSort:(NSMutableArray *)a indexP:(int)p indexR:(int)r

{

    if (p < r) {

        int q = (p + r) / 2;

        [self mergeSort:a indexP:p indexR:q];

        [self mergeSort:a indexP:q+1 indexR:r];

        [self mergeSort:a indexP:p indexQ:q indexR:r];

    }

    

}

– (void)mergeSort:(NSMutableArray *)a indexP:(int)p indexQ:(int)q  indexR:(int)r

{

    int n1 = q – p + 1;

    int n2 = r – q;

    

    NSMutableArray *L = [[a subarrayWithRange:NSMakeRange(p, n1)] mutableCopy];

    NSMutableArray *R = [[a subarrayWithRange:NSMakeRange(q+1, n2)] mutableCopy];

    [L addObject:@(HUGE_VAL)];

    [R addObject:@(HUGE_VAL)];

    

    int i=0;

    int j=0;

    for (int k=p; k<=r; k++) {

        NSNumber *ln = self.simpleBlock(L[i]);

        NSNumber *rn = self.simpleBlock(R[j]);

        if ([ln doubleValue] <= [rn doubleValue]) {

            a[k] = L[i];

            i++;

        } else {

            a[k] = R[j];

            j++;

        }

        self.timeCounter++;

    }

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end