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

# stevenhuey's solution

## to All Your Base in the Objective-C Track

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

Convert a number, represented as a sequence of digits in one base, to any other base.

Implement general base conversion. Given a number in base a, represented as a sequence of digits, convert it to base b.

## Note

• Try to implement the conversion yourself. Do not use something else to perform the conversion for you.

In positional notation, a number in base b can be understood as a linear combination of powers of b.

The number 42, in base 10, means:

(4 * 10^1) + (2 * 10^0)

The number 101010, in base 2, means:

(1 * 2^5) + (0 * 2^4) + (1 * 2^3) + (0 * 2^2) + (1 * 2^1) + (0 * 2^0)

The number 1120, in base 3, means:

(1 * 3^3) + (1 * 3^2) + (2 * 3^1) + (0 * 3^0)

I think you got the idea!

Yes. Those three numbers above are exactly the same. Congratulations!

## 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/all-your-base/AllYourBase.m
``````

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

## Submitting Incomplete Solutions

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

### AllYourBaseTest.m

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

#if __has_include("AllYourBaseExample.h")
# import "AllYourBaseExample.h"
# else
# import "AllYourBase.h"
#endif

@interface AllYourBaseTest : XCTestCase

@end

@implementation AllYourBaseTest

- (void)testSingleBitOneToDecimal {
NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:2 inputDigits:@[@1] outputBase:10];
NSArray<NSNumber *> *expected = @[@1];
XCTAssertEqualObjects(result, expected);
}

- (void)testBinaryToSingleDecimal {
NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:2 inputDigits:@[@1, @0, @1] outputBase:10];
NSArray<NSNumber *> *expected = @[@5];
XCTAssertEqualObjects(result, expected);
}

- (void)testSingleDecimalToBinary {
NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:10 inputDigits:@[@5] outputBase:2];
NSArray<NSNumber *> *expected = @[@1, @0, @1];
XCTAssertEqualObjects(result, expected);
}

- (void)testBinaryToMultipleDecimal {
NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:2 inputDigits:@[@1, @0, @1, @0, @1, @0] outputBase:10];
NSArray<NSNumber *> *expected = @[@4, @2];
XCTAssertEqualObjects(result, expected);
}

- (void)testDecimalToBinary {
NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:10 inputDigits:@[@4, @2] outputBase:2];
NSArray<NSNumber *> *expected = @[@1, @0, @1, @0, @1, @0];
XCTAssertEqualObjects(result, expected);
}

NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:3 inputDigits:@[@1, @1, @2, @0] outputBase:16];
NSArray<NSNumber *> *expected = @[@2, @10];
XCTAssertEqualObjects(result, expected);
}

NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:16 inputDigits:@[@2, @10] outputBase:3];
NSArray<NSNumber *> *expected = @[@1, @1, @2, @0];
XCTAssertEqualObjects(result, expected);
}

- (void)test15BitInteger {
NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:97 inputDigits:@[@3, @46, @60] outputBase:73];
NSArray<NSNumber *> *expected = @[@6, @10, @45];
XCTAssertEqualObjects(result, expected);
}

- (void)testEmptyList {
NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:2 inputDigits:@[] outputBase:10];
NSArray<NSNumber *> *expected = @[];
XCTAssertEqualObjects(result, expected);
}

- (void)testSingleZero {
NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:10 inputDigits:@[@0] outputBase:2];
NSArray<NSNumber *> *expected = @[];
XCTAssertEqualObjects(result, expected);
}

- (void)testMultipleZeros {
NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:10 inputDigits:@[@0, @0, @0] outputBase:2];
NSArray<NSNumber *> *expected = @[];
XCTAssertEqualObjects(result, expected);
}

NSArray<NSNumber *> *result = [AllYourBase outputDigitsForInputBase:7 inputDigits:@[@0, @6, @0] outputBase:10];
NSArray<NSNumber *> *expected = @[@4, @2];
XCTAssertEqualObjects(result, expected);
}

- (void)testNegativeDigit {
NSArray<NSNumber *> *inputDigits = @[@1, @(-1), @1, @0, @1, @0];
XCTAssertThrows([AllYourBase outputDigitsForInputBase:2 inputDigits:inputDigits outputBase:10]);
}

- (void)testInvalidPositiveDigit {
NSArray<NSNumber *> *inputDigits = @[@1, @2, @1, @0, @1, @0];
XCTAssertThrows([AllYourBase outputDigitsForInputBase:2 inputDigits:inputDigits outputBase:10]);
}

- (void)testFirstBaseIsOne {
NSArray<NSNumber *> *inputDigits = @[];
XCTAssertThrows([AllYourBase outputDigitsForInputBase:1 inputDigits:inputDigits outputBase:10]);
}

- (void)testSecondBaseIsOne {
NSArray<NSNumber *> *inputDigits = @[@1, @0, @1, @0, @1, @0];
XCTAssertThrows([AllYourBase outputDigitsForInputBase:2 inputDigits:inputDigits outputBase:1]);
}

- (void)testFirstBaseIsZero {
NSArray<NSNumber *> *inputDigits = @[];
XCTAssertThrows([AllYourBase outputDigitsForInputBase:0 inputDigits:inputDigits outputBase:10]);
}

- (void)testSecondBaseIsZero {
NSArray<NSNumber *> *inputDigits = @[@7];
XCTAssertThrows([AllYourBase outputDigitsForInputBase:10 inputDigits:inputDigits outputBase:0]);
}

- (void)testFirstBaseIsNegative {
NSArray<NSNumber *> *inputDigits = @[@1];
XCTAssertThrows([AllYourBase outputDigitsForInputBase:-2 inputDigits:inputDigits outputBase:10]);
}

- (void)testSecondBaseIsNegative {
NSArray<NSNumber *> *inputDigits = @[@1];
XCTAssertThrows([AllYourBase outputDigitsForInputBase:2 inputDigits:inputDigits outputBase:-7]);
}

@end``````
``````//
//  AllYourBase.m
//  AllYourBase
//
//  Created by Steve Huey on 7/10/17.
//

#import "AllYourBase.h"

@interface AllYourBase ()
+ (NSUInteger)decimalValueOf:(ArrayOfNumbers)inputDigits
inBase:(NSUInteger)base;

+ (ArrayOfNumbers)powersOf:(NSUInteger)n upTo:(NSUInteger)max;
+ (ArrayOfNumbers)convert:(NSUInteger)n toBase:(NSUInteger)base;
@end

@implementation AllYourBase
+ (ArrayOfNumbers)outputDigitsForInputBase:(NSInteger)base
inputDigits:(ArrayOfNumbers)inputDigits
outputBase:(NSInteger)outputBase
{
// Throw exceptions for invalid input digits
for (NSNumber* n in inputDigits) {
if ([n integerValue] < 0) {
[NSException raise:@"InvalidInputError" format:@"Input digits can't be negative"];
return @[];
}

if ([n integerValue] >= base) {
[NSException raise:@"InvalidInputError" format:@"Input digits can't be >= base"];
return @[];
}
}

if (base < 2 || outputBase < 2) { // Make sure the base values are valid
[NSException raise:@"InvalidBaseError" format:@"Bases have to be >= 2"];
return @[];
}
else if (0 == [inputDigits count]) // Return early for empty input
{
return @[];
}
else { // Otherwise, convert
NSUInteger decimalValue = [[self class] decimalValueOf:inputDigits
inBase:base];

return [[self class] convert:decimalValue toBase:outputBase];
}
}

+ (NSUInteger)decimalValueOf:(ArrayOfNumbers)inputDigits inBase:(NSUInteger)base
{
NSUInteger result = 0;

NSUInteger e = [inputDigits count] - 1;
for (NSNumber* n in inputDigits) {
result += (NSInteger)([n doubleValue] * pow((double)base, (double)e));
e -= 1;
}

return result;
}

+ (ArrayOfNumbers)powersOf:(NSUInteger)n upTo:(NSUInteger)max
{
NSMutableArray* powers = [NSMutableArray arrayWithCapacity:0];

NSUInteger e = 0;
NSUInteger v = 0;

while (v <= max) {
v = (NSUInteger)pow((double)n, (double)e);

if (v <= max) {
e += 1;
}
}

return [NSArray arrayWithArray:powers];
}

+ (ArrayOfNumbers)convert:(NSUInteger)n toBase:(NSUInteger)base
{
ArrayOfNumbers powers = [[self class] powersOf:base upTo:n];

NSMutableArray* result = [NSMutableArray arrayWithCapacity:0];
NSUInteger remainder = n;

for (NSNumber* p in [[powers reverseObjectEnumerator] allObjects]) {
if (0 == remainder) {
break;
}

NSUInteger pValue = [p unsignedIntegerValue];
NSUInteger quotient = remainder / pValue;

remainder -= (quotient * pValue);
}

return [NSArray arrayWithArray:result];
}
@end``````