Objective-C 练习题,题目来源 exercism.io,一共 50 题,见 GitHub

第三篇共 10 题。

(一)
(二)
(四)
(五)

# Scrabble Score

题目和测试用例见链接,下同。Scrabble Score
Given a word, compute the scrabble score for that word.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// ScrabbleScore.h
#import <Foundation/Foundation.h>

@interface ScrabbleScore : NSObject

@property (nonatomic, assign) NSInteger score;

- (instancetype)initWithWord:(NSString *)word;
+ (NSInteger)score:(NSString *)word;

@end

// ScrabbleScore.m
#import "ScrabbleScore.h"

static NSDictionary *letterValues;

@implementation ScrabbleScore

- (instancetype)initWithWord:(NSString *)word {
if (self = [super init]) {
if (!letterValues) {
letterValues = @{
@"A" : @1,
@"E" : @1,
@"I" : @1,
@"O" : @1,
@"U" : @1,
@"L" : @1,
@"N" : @1,
@"R" : @1,
@"S" : @1,
@"T" : @1,
@"D" : @2,
@"G" : @2,
@"B" : @3,
@"C" : @3,
@"M" : @3,
@"P" : @3,
@"F" : @4,
@"H" : @4,
@"V" : @4,
@"W" : @4,
@"Y" : @4,
@"K" : @5,
@"J" : @8,
@"X" : @8,
@"Q" : @10,
@"Z" : @10
};
}
self.score = 0;
for (NSInteger i = 0; i < word.length; ++i) {
self.score += [letterValues[[[word substringWithRange:NSMakeRange(i, 1)] uppercaseString]] integerValue];
}
}
return self;
}

+ (NSInteger)score:(NSString *)word {
return [[[self alloc] initWithWord:word] score];
}

@end

# Phone Number

Phone Number
Clean up user-entered phone numbers so that they can be sent SMS messages.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// PhoneNumber.h
#import <Foundation/Foundation.h>

@interface PhoneNumber : NSObject

@property (nonatomic, copy) NSString *number;
@property (nonatomic, copy) NSString *areaCode;

- (instancetype)initWithString:(NSString *)string;

@end

// PhoneNumber.m
#import "PhoneNumber.h"

@implementation PhoneNumber

- (instancetype)initWithString:(NSString *)string {
if (self = [super init]) {
self.number = @"0000000000";
string = [string stringByReplacingOccurrencesOfString:@"\\D" withString:@"" options:(NSRegularExpressionSearch) range:NSMakeRange(0, string.length)];
if (string.length == 10) {
self.number = string;
} else if (string.length == 11 && [string hasPrefix:@"1"]) {
self.number = [string substringFromIndex:1];
}
self.areaCode = [self.number substringToIndex:3];
}
return self;
}

- (NSString *)description {
return [NSString stringWithFormat:@"(%@) %@-%@", [self.number substringToIndex:3], [self.number substringWithRange:NSMakeRange(3, 3)], [self.number substringFromIndex:6]];
}

@end

# Perfect Numbers

Perfect Numbers
Determine if a number is perfect, abundant, or deficient based on Nicomachus’ (60 - 120 CE) classification scheme for natural numbers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// NumberClassifier.h
#import <Foundation/Foundation.h>

typedef NS_ENUM(NSUInteger, NumberClassification) {
NumberClassificationPerfect,
NumberClassificationDeficient,
NumberClassificationAbundant,
};

@interface NumberClassifier : NSObject

@property (nonatomic, assign) NumberClassification classification;

- (instancetype)initWithNumber:(NSInteger)number;

@end

// NumberClassifier.m
#import "PerfectNumbers.h"

@implementation NumberClassifier

- (instancetype)initWithNumber:(NSInteger)number {
if (self = [super init]) {
NSMutableSet *set = [NSMutableSet set];
for (NSInteger i = 2; i < number; ++i) {
if (number % i == 0) {
[set addObject:@(i)];
}
}
NSInteger sum = 1;
for (NSNumber *number in set) {
sum += [number integerValue];
}
if (sum == number) {
self.classification = NumberClassificationPerfect;
} else if (sum > number) {
self.classification = NumberClassificationAbundant;
} else {
self.classification = NumberClassificationDeficient;
}
}
return self;
}

@end

# Secret Handshake

Secret Handshake
Given a decimal number, convert it to the appropriate sequence of events for a secret handshake.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// SecretHandshake.h
#import <Foundation/Foundation.h>

@interface SecretHandshake : NSObject

@property (nonatomic, strong) NSArray *commands;

- (instancetype)initWithNumber:(NSInteger)number;

@end

// SecretHandshake.m
#import "SecretHandshake.h"

@implementation SecretHandshake

- (instancetype)initWithNumber:(NSInteger)number {
if (self = [super init]) {
NSMutableArray *array = [NSMutableArray array];
NSMutableArray *result = [NSMutableArray array];
do {
[array addObject:[@(number % 2) stringValue]];
number = number / 2;
} while (number > 0);
NSString *binaryString = [[[array reverseObjectEnumerator] allObjects] componentsJoinedByString:@""];
NSInteger binary = [binaryString integerValue];
BOOL reverse = NO;
if (binary >= 10000) {
reverse = YES;
binary = binary % 10000;
}
if (binary >= 1000) {
binary = binary % 1000;
[result insertObject:@"jump" atIndex:0];
}
if (binary >= 100) {
binary = binary % 100;
[result insertObject:@"close your eyes" atIndex:0];
}
if (binary >= 10) {
binary = binary % 10;
[result insertObject:@"double blink" atIndex:0];
}
if (binary == 1) {
[result insertObject:@"wink" atIndex:0];
}
if (reverse) {
self.commands = [NSMutableArray arrayWithArray:[[result reverseObjectEnumerator] allObjects]];
} else {
self.commands = result;
}
}
return self;
}

@end

# Atbash Cipher

Atbash Cipher
Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// AtbashCipher.h
#import <Foundation/Foundation.h>

@interface AtbashCipher : NSObject

+ (NSString *)encode:(NSString *)input;

@end

// AtbashCipher.m
#import "AtbashCipher.h"

static NSString *const plain = @"abcdefghijklmnopqrstuvwxyz";
static NSString *const cipher = @"zyxwvutsrqponmlkjihgfedcba";

@implementation AtbashCipher

+ (NSString *)encode:(NSString *)input {
NSString *result = @"";
input = [input stringByReplacingOccurrencesOfString:@"\\W" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, input.length)];
input = [input lowercaseString];
for (NSInteger i = 0; i < input.length; ++i) {
NSString *subStr = [input substringWithRange:NSMakeRange(i, 1)];
NSInteger index = [plain rangeOfString:subStr].location;
if (index != NSNotFound) {
result = [result stringByAppendingFormat:@"%c", [cipher characterAtIndex:index]];
} else {
result = [result stringByAppendingString:subStr];
}
if ((i + 1) % 5 == 0 && i != input.length - 1) {
result = [result stringByAppendingString:@" "];
}
}

return result;
}

@end

# Sieve

Sieve
Use the Sieve of Eratosthenes to find all the primes from 2 up to a given number.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Sieve.h
#import <Foundation/Foundation.h>

@interface Sieve : NSObject

+ (NSArray *)primesUpTo:(NSInteger)limit;

@end

// Sieve.m
#import "Sieve.h"

@implementation Sieve

+ (NSArray *)primesUpTo:(NSInteger)limit {
NSMutableArray *result = [NSMutableArray array];
for (NSInteger i = 2; i <= limit; ++i) {
[result addObject:@(i)];
}

NSInteger prime = 2;
NSInteger index = 0;
while ([[result lastObject] integerValue] >= prime * prime) {
for (NSInteger i = prime; i <= [result.lastObject integerValue] / prime; ++i) {
[result removeObject:@(i * prime)];
}
index++;
prime = [result[index] integerValue];
}

return result;
}

@end

# Collatz Conjecture

Collatz Conjecture
Calculate the number of steps to reach 1 using the Collatz conjecture

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// CollatzConjecture.h
#import <Foundation/Foundation.h>

@interface CollatzConjecture : NSObject

+ (NSInteger)stepsForNumber:(NSInteger)number;

@end

// CollatzConjecture.m
#import "CollatzConjecture.h"

@implementation CollatzConjecture

+ (NSInteger)stepsForNumber:(NSInteger)number {
if (number <= 0) {
return NSNotFound;
}

NSInteger steps = 0;
while (number != 1) {
if (number % 2 == 0) {
number /= 2;
} else {
number = number * 3 + 1;
}
steps++;
}

return steps;
}

@end

# Series

Series
Given a string of digits, output all the contiguous substrings of length n in that string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Series.h
#import <Foundation/Foundation.h>

@interface Series : NSObject

- (instancetype)initWithNumberString:(NSString *)input;
- (NSArray *)slicesWithSize:(NSInteger)size;

@end

// Series.m
#import "Series.h"

@implementation Series {
NSString *_kInput;
}

- (instancetype)initWithNumberString:(NSString *)input {
if (self = [super init]) {
_kInput = input;
}
return self;
}

- (NSArray *)slicesWithSize:(NSInteger)size {
if (size > _kInput.length) {
return nil;
}

NSMutableArray *inputArray = [NSMutableArray array];
for (NSInteger i = 0; i < _kInput.length; ++i) {
[inputArray addObject:@([[_kInput substringWithRange:NSMakeRange(i, 1)] integerValue])];
}

NSMutableArray *result = [NSMutableArray array];
for (NSInteger i = 0; i <= _kInput.length - size; ++i) {
[result addObject:[inputArray subarrayWithRange:NSMakeRange(i, size)]];
}
return result;
}

@end

# Beer Song

Beer Song
Produce the lyrics to that beloved classic, that field-trip favorite: 99 Bottles of Beer on the Wall.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// BeerSongExample.h
#import <Foundation/Foundation.h>

@interface BeerSongExample : NSObject

@property (nonatomic, copy) NSString *singBeerSong;

- (instancetype)initWithNumberOfBeerBottles:(NSInteger)bottles;

@end

// BeerSongExample.m
#import "BeerSongExample.h"

@implementation BeerSongExample

- (instancetype)initWithNumberOfBeerBottles:(NSInteger)bottles {
if (self = [super init]) {
NSString *verses = @"";
for (NSInteger i = bottles; i>= 0; --i) {
if (verses.length > 0) {
verses = [verses stringByAppendingString:@"\n\n"];
}
if (i == 1) {
verses = [verses stringByAppendingString:@"1 bottle of beer on the wall, 1 bottle of beer.\nTake one down and pass it around, no more bottles of beer on the wall."];
} else if (i == 0) {
verses = [verses stringByAppendingFormat:@"No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."];
} else {
verses = [verses stringByAppendingFormat:@"%ld bottles of beer on the wall, %ld bottles of beer.\nTake one down and pass it around, %ld bottle%@ of beer on the wall.", (long)i, (long)i, (long)(i - 1), (i - 1 > 1 ? @"s" : @"")];
}
}
self.singBeerSong = verses;
}
return self;
}

@end

# Word Count

Word Count
Given a phrase, count the occurrences of each word in that phrase.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// WordCount.h
#import <Foundation/Foundation.h>

@interface WordCount : NSObject

@property (nonatomic, strong) NSDictionary *count;

- (instancetype)initWithString:(NSString *)string;

@end

// WordCount.m
#import "WordCount.h"

@implementation WordCount

- (instancetype)initWithString:(NSString *)string {
if (self = [super init]) {
string = [[string lowercaseString] stringByReplacingOccurrencesOfString:@"[^a-z0-9 ]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, string.length)];
NSArray *array = [string componentsSeparatedByString:@" "];
NSMutableDictionary *count = [NSMutableDictionary dictionary];
[array enumerateObjectsUsingBlock:^(NSString *word, NSUInteger idx, BOOL * _Nonnull stop) {
if (word.length > 0) {
count[word] = @([count[word] integerValue] + 1);
}
}];
self.count = count;
}
return self;
}

@end