ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# jaishreedhage's solution

## to Luhn in the Objective-C Track

Published at Jul 13 2018 · 0 comments
Instructions
Test suite
Solution

Given a number determine whether or not it is valid per the Luhn formula.

The Luhn algorithm is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers and Canadian Social Insurance Numbers.

The task is to check if a given string is valid.

## Validating a Number

Strings of length 1 or less are not valid. Spaces are allowed in the input, but they should be stripped before checking. All other non-digit characters are disallowed.

## Example 1: valid credit card number

``````4539 1488 0343 6467
``````

The first step of the Luhn algorithm is to double every second digit, starting from the right. We will be doubling

``````4_3_ 1_8_ 0_4_ 6_6_
``````

If doubling the number results in a number greater than 9 then subtract 9 from the product. The results of our doubling:

``````8569 2478 0383 3437
``````

Then sum all of the digits:

``````8+5+6+9+2+4+7+8+0+3+8+3+3+4+3+7 = 80
``````

If the sum is evenly divisible by 10, then the number is valid. This number is valid!

## Example 2: invalid credit card number

``````8273 1232 7352 0569
``````

Double the second digits, starting from the right

``````7253 2262 5312 0539
``````

Sum the digits

``````7+2+5+3+2+2+6+2+5+3+1+2+0+5+3+9 = 57
``````

57 is not evenly divisible by 10, so this number is not valid.

## Setup

There are two different methods of getting set up to run the tests with Objective-C:

• Create an Xcode project with a test target which will run the tests.
• Use the ruby gem `objc` as a test runner utility.

Both are described in more detail here: http://exercism.io/languages/objective-c

### Submitting Exercises

When submitting an exercise, make sure your solution file is in the same directory as the test code.

The submit command will look something like:

``````exercism submit <path-to-exercism-workspace>/objective-c/luhn/Luhn.m
``````

You can find the Exercism workspace by running `exercism debug` and looking for the line beginning with Workspace.

## Source

The Luhn Algorithm on Wikipedia http://en.wikipedia.org/wiki/Luhn_algorithm

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### LuhnTest.m

``````#import <XCTest/XCTest.h>

#if __has_include("LuhnExample.h")
# import "LuhnExample.h"
# else
# import "Luhn.h"
#endif

@interface LuhnTest : XCTestCase

@end

@implementation LuhnTest

- (void)testSingleDigitStringNotValid {
Luhn *luhn = [[Luhn alloc] initWithString:@"1"];
XCTAssertFalse(luhn.isValid);
}

- (void)testSingleZeroInvalid {
Luhn *luhn = [[Luhn alloc] initWithString:@"0"];
XCTAssertFalse(luhn.isValid);
}

- (void)testSimpleValidSINRemainsValidIfReversed {
Luhn *luhn = [[Luhn alloc] initWithString:@"059"];
XCTAssertTrue(luhn.isValid);
}

- (void)testSimpleValidSINInvalidIfReversed {
Luhn *luhn = [[Luhn alloc] initWithString:@"59"];
XCTAssertTrue(luhn.isValid);
}

Luhn *luhn = [[Luhn alloc] initWithString:@"055 444 285"];
XCTAssertTrue(luhn.isValid);
}

Luhn *luhn = [[Luhn alloc] initWithString:@"055 444 286"];
XCTAssertFalse(luhn.isValid);
}

- (void)testInvalidCreditCard {
Luhn *luhn = [[Luhn alloc] initWithString:@"8273 1232 7352 0569"];
XCTAssertFalse(luhn.isValid);
}

- (void)testValidStringsWithANonDigitInvalid {
Luhn *luhn = [[Luhn alloc] initWithString:@"055a 444 285"];
XCTAssertFalse(luhn.isValid);
}

- (void)testValidStringsWithPunctuationInvalid {
Luhn *luhn = [[Luhn alloc] initWithString:@"055-444-285"];
XCTAssertFalse(luhn.isValid);
}

- (void)testValidStringWithSymbolsInvalid {
Luhn *luhn = [[Luhn alloc] initWithString:@"055Â£ 444\$ 285"];
XCTAssertFalse(luhn.isValid);
}

- (void)testSingleZeroWithSpaceInvalid {
Luhn *luhn = [[Luhn alloc] initWithString:@" 0"];
XCTAssertFalse(luhn.isValid);
}

- (void)testMoreThanOneZeroValid {
Luhn *luhn = [[Luhn alloc] initWithString:@"0000 0"];
XCTAssertTrue(luhn.isValid);
}

- (void)testInputDigit9CorrectConverted {
Luhn *luhn = [[Luhn alloc] initWithString:@"091"];
XCTAssertTrue(luhn.isValid);
}

@end``````

### Luhn/LuhnTest/Luhn.h

``````//
//  Luhn.h
//  Luhn
//
//  Created by Jaishree Dhage on 12/12/17.
//

#import <Foundation/Foundation.h>

@interface Luhn : NSObject

@property (nonatomic,readonly) BOOL isValid;

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

@end``````

### Luhn/LuhnTest/Luhn.m

``````//
//  Luhn.m
//  Luhn
//
//  Created by Jaishree Dhage on 12/12/17.
//

#import "Luhn.h"

@interface Luhn ()

@property (nonatomic,readwrite) BOOL isValid;

@end

@implementation Luhn

-(instancetype)initWithString:(NSString *)string{
self = [super init];
if(self){
self.isValid = [self checkValidity:string];
}
return self;
}

-(BOOL) checkValidity:(NSString *) string{

string = [[string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] componentsJoinedByString:@""];

if(string.length <= 1)
return false;

NSMutableCharacterSet *set = [NSMutableCharacterSet letterCharacterSet];
[set formUnionWithCharacterSet:[NSMutableCharacterSet punctuationCharacterSet]];
if([string rangeOfCharacterFromSet:set].location!=NSNotFound)
return false;

for(int i=string.length-2;i>=0;i-=2){
NSInteger n = [string characterAtIndex:i] - '0';
n = n*2>9?(n*2-9):n*2;
string = [string stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:[NSString stringWithFormat:@"%lu",n]];
}

NSInteger sum = 0;
for(int i=0;i<string.length;i++){
sum += [string characterAtIndex:i] - '0';
}
if(sum%10!=0)
return false;
return true;

}

@end``````