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

# vuinguyen's solution

## to Transpose in the Objective-C Track

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

Given an input text output it transposed.

Roughly explained, the transpose of a matrix:

``````ABC
DEF
``````

is given by:

``````AD
BE
CF
``````

Rows become columns and columns become rows. See https://en.wikipedia.org/wiki/Transpose.

If the input has rows of different lengths, this is to be solved as follows:

• Pad to the left with spaces.
• Don't pad to the right.

Therefore, transposing this matrix:

``````ABC
DE
``````

results in:

``````AD
BE
C
``````

And transposing:

``````AB
DEF
``````

results in:

``````AD
BE
F
``````

In general, all characters from the input should also be present in the transposed output. That means that if a column in the input text contains only spaces on its bottom-most row(s), the corresponding output row should contain the spaces in its right-most column(s).

## 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/transpose/Transpose.m
``````

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

## Source

Reddit r/dailyprogrammer challenge #270 [Easy]. https://www.reddit.com/r/dailyprogrammer/comments/4msu2x/challenge_270_easy_transpose_the_input_text

## Submitting Incomplete Solutions

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

### TransposeTest.m

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

#if __has_include("TransposeExample.h")
# import "TransposeExample.h"
# else
# import "Transpose.h"
#endif

@interface TransposeTest : XCTestCase

@end

@implementation TransposeTest

- (void)testEmptyInput {
XCTAssertEqualObjects([Transpose transpose:@[]], @[]);
}

- (void)testTwoCharactersInARow {
NSArray<NSString *> *input = @[@"A1"];
NSArray<NSString *> *expected = @[@"A", @"1"];
XCTAssertEqualObjects([Transpose transpose:input], expected);
}

- (void)testTwoCharactersInAColumn {
NSArray<NSString *> *input = @[@"A", @"1"];
NSArray<NSString *> *expected = @[@"A1"];
XCTAssertEqualObjects([Transpose transpose:input], expected);
}

- (void)testSimple {
NSArray<NSString *> *input = @[@"ABC", @"123"];
NSArray<NSString *> *expected = @[@"A1", @"B2", @"C3"];
XCTAssertEqualObjects([Transpose transpose:input], expected);
}

- (void)testSingleLine {
NSArray<NSString *> *input = @[@"Single line."];
NSArray<NSString *> *expected = @[@"S", @"i", @"n", @"g", @"l", @"e", @"", @"l", @"i", @"n", @"e", @"."];
XCTAssertEqualObjects([Transpose transpose:input], expected);
}

- (void)testFirstLineLongerThanSecondLine {
NSArray<NSString *> *input = @[@"The fourth line.", @"The fifth line."];
NSArray<NSString *> *expected = @[@"TT", @"hh", @"ee", @"", @"ff", @"oi", @"uf", @"rt", @"th", @"h", @" l", @"li", @"in", @"ne", @"e.", @"."];
XCTAssertEqualObjects([Transpose transpose:input], expected);
}

- (void)testSecondLineLongerThanFirstLine {
NSArray<NSString *> *input = @[@"The first line.", @"The second line."];
NSArray<NSString *> *expected = @[@"TT", @"hh", @"ee", @"", @"fs", @"ie", @"rc", @"so", @"tn", @" d", @"l", @"il", @"ni", @"en", @".e", @" ."];
XCTAssertEqualObjects([Transpose transpose:input], expected);
}

- (void)testSquare {
NSArray<NSString *> *input = @[@"HEART", @"EMBER", @"ABUSE", @"RESIN", @"TREND"];
NSArray<NSString *> *expected = @[@"HEART", @"EMBER", @"ABUSE", @"RESIN", @"TREND"];
XCTAssertEqualObjects([Transpose transpose:input], expected);
}

- (void)testRectangle {
NSArray<NSString *> *input = @[@"FRACTURE", @"OUTLINED", @"BLOOMING", @"SEPTETTE"];
NSArray<NSString *> *expected = @[@"FOBS", @"RULE", @"ATOP", @"CLOT", @"TIME", @"UNIT", @"RENT", @"EDGE"];
XCTAssertEqualObjects([Transpose transpose:input], expected);
}

- (void)testTriangle {
NSArray<NSString *> *input = @[@"T", @"EE", @"AAA", @"SSSS", @"EEEEE", @"RRRRRR"];
NSArray<NSString *> *expected = @[@"TEASER", @" EASER", @"  ASER", @"   SER", @"    ER", @"     R"];
XCTAssertEqualObjects([Transpose transpose:input], expected);
}

- (void)testManyLines { //!OCLINT
NSArray<NSString *> *input = @[@"Chor. Two households, both alike in dignity,",
@"In fair Verona, where we lay our scene,",
@"From ancient grudge break to new mutiny,",
@"Where civil blood makes civil hands unclean.",
@"From forth the fatal loins of these two foes",
@"A pair of star-cross'd lovers take their life;",
@"Doth with their death bury their parents' strife.",
@"The fearful passage of their death-mark'd love,",
@"And the continuance of their parents' rage,",
@"Which, but their children's end, naught could remove,",
@"Is now the two hours' traffic of our stage;",
@"The which if you with patient ears attend,",
@"What here shall miss, our toil shall strive to mend."
];

NSArray<NSString *> *expected = @[
@"CIFWFAWDTAWITW",
@"hnrhr hohnhshh",
@"o oeopotedi ea",
@"rfmrmash  cn t",
@".a e ie fthow",
@" ia fr weh,whh",
@"Trnco miae  ie",
@"w ciroitr btcr",
@"oVivtfshfcuhhe",
@" eeih a uote",
@"hrnl sdtln  is",
@"oot ttvh tttfh",
@"un bhaeepihw a",
@"saglernianeoyl",
@"e,ro -trsui ol",
@"h uofcu sarhu",
@"owddarrdan o m",
@"lhg to'egccuwi",
@"deemasdaeehris",
@"sr als t  ists",
@",ebk 'phool'h,",
@"  reldi ffd",
@"bweso tb  rtpo",
@"oea ileutterau",
@"t kcnoorhhnatr",
@"hl isvuyee'fi",
@" atv es iisfet",
@"ayoior trr ino",
@"l  lfsoh  ecti",
@"ion   vedpn  l",
@"erwaharrar,fas",
@"   nekt te  rh",
@"ismdsehphnnosa",
@"ncuse ra-tau l",
@" et  tormsural",
@"dniuthwea'g t",
@"iennwesnr hsts",
@"g,ycoi tkrttet",
@"n ,l r s'a anr",
@"i  ef  'dgcgdi",
@"t  aol   eoe,v",
@"y  nei sl,u; e",
@",  .sf to l",
@"     e rv d  t",
@"     ; ie    o",
@"       f, r",
@"       e  e  m",
@"       .  m  e",
@"          o  n",
@"          v  d",
@"          e  .",
@"          ,"
];

XCTAssertEqualObjects([Transpose transpose:input], expected);
}

@end``````
``````//
//  Transpose.m
//  Transpose
//
//  Created by Vui Nguyen on 1/8/17.
//

#import "Transpose.h"

@implementation Transpose

// Function that, given an input matrix, returns the matrix, transposed.
// For example, given the matrix["ABC", "123"], it will give us the matrix["A1", "B2", C3"].
// We will use this input matrix example in the comments throughout this function.
+(NSArray*) transpose: (NSArray*)inputMatrix
{
NSLog(@"inputMatrix: @%@", inputMatrix);

// The outputMatrix to return, which will be the inputMatrix, transposed
NSMutableArray * outputMatrix = [[NSMutableArray alloc] init];

// This is an NSInteger to prevent loss of precision when we do a calculation
// later with singleString.length, which returns an NSInteger
NSInteger maxStringLengthInputMatrix = 0;

// Create an Enumerator to make it easier to loop through the inputMatrix
NSEnumerator * inputMatrixEnumerator = [inputMatrix objectEnumerator];

// find the largest string (longest row) in inputMatrix
int index = 0;
NSString * singleString = @"";
while (singleString = [inputMatrixEnumerator nextObject])
{
if (singleString.length > maxStringLengthInputMatrix)
{
maxStringLengthInputMatrix = singleString.length;
}
index = index + 1;
}

// initialize strings for outputMatrix
for (index = 0; index < maxStringLengthInputMatrix; index++)
{
outputMatrix[index] = @"";
}
// When working with input rows of different lengths, we
// need a way to pad to the left of the transposed row with spaces,
// but NOT pad to the right. This array helps us with keeping
// track of rows that have spaces to the right, so that the spaces
// can be removed, but leave padding spaces to the left alone.
// For example, a transposed row like this is okay: "   E" (several spaces
// to the left of E). But this is NOT okay: "E    " (several spaces to the
// right of E)
NSMutableArray * lastNonSpaceIndexArray = [[NSMutableArray alloc] init];

// initialize array of "last nonspace character indices"
for (index = 0; index < maxStringLengthInputMatrix; index++)
{
}

// character from the inputMatrix that will be inserted into the transposed
// outputMatrix at the correct index
NSString * singleCharInputMatrix;

// This nested for-loop takes a row from the inputMatrix and inserts it into the
// corresponding column in the outputMatrix.
// For example, the string "ABC" in row 0 of the inputMatrix, will be inserted as
// "A" in row 0, column 0; "B" in row 1, column 0, and "C" in row 2, column 0 of
// the outputMatrix.
int indexInputMatrix  = 0;
int indexOutputMatrix = 0;
for (indexInputMatrix = 0; indexInputMatrix < inputMatrix.count; indexInputMatrix++)
{
for (indexOutputMatrix = 0; indexOutputMatrix < outputMatrix.count; indexOutputMatrix++)
{
// If the current row/string in the inputMatrix is shorter
// than the other rows in the inputMatrix, then we don't want
// to access the index beyond the valid string in that row, otherwise
// we'll throw an error. So, we say the "character" at that index is
// a space even though there's nothing there. Later on, we will add
// this space character to the outputMatrix
// at the correct, corresponding index in outputMatrix.
if (indexOutputMatrix >= [inputMatrix[indexInputMatrix] length])
{
singleCharInputMatrix = @" ";
}
else
{
// All we're trying to do here is get the character from the current row of inputMatrix,
// so that later we can append it to the right spot in the outputMatrix
const unichar singleChar = [inputMatrix[indexInputMatrix] characterAtIndex:indexOutputMatrix];
singleCharInputMatrix = [NSString stringWithCharacters: &singleChar length:1];

// if the character from the inputMatrix is NOT a space, we're going to update
// the lastNonSpaceIndexArray with its position, to help keep track of spaces
// to the RIGHT of a valid transposed row, so we can remove those extra spaces
// later
if (![singleCharInputMatrix isEqual: @" "])
{
lastNonSpaceIndexArray[indexOutputMatrix] = [NSNumber numberWithInteger:indexInputMatrix];
}
}

// Finally, this is where we append the character from inputMatrix into
// the transposed outputMatrix at the correct index
// For example, if "ABC" is row 0 of our inputMatrix, and we just grabbed
// the letter A, then we will now insert A into row 0, column 0 of outputMatrix
outputMatrix[indexOutputMatrix] = [outputMatrix[indexOutputMatrix] stringByAppendingString:singleCharInputMatrix];
}   // end outputMatrix loop
}   // end outermost loop of nested for loop (inputMatrix loop)

// After filling out the outputMatrix, we have to do some cleanup. That's because
// some rows may have padded spaces to the right, which we will remove here
// in this for-loop.
for (indexOutputMatrix = 0; indexOutputMatrix < outputMatrix.count; indexOutputMatrix++)
{
// if a row in outputMatrix has padded spaces to the right, remove those extra spaces
if (( [lastNonSpaceIndexArray[indexOutputMatrix] integerValue] + 1) < [outputMatrix[indexOutputMatrix] length])
{
// Because String operations in Objective-C are so hard, we have this convoluted statement that
// takes the valid string to the left of the padded spaces, and returns the string. The
// padded spaces get left behind.  This will also blank output rows which contain only spaces.
NSString * cleanedUpString = [outputMatrix[indexOutputMatrix] substringToIndex:([lastNonSpaceIndexArray[indexOutputMatrix] integerValue] + 1)];

// set the row in the outputMatrix to the new and improved, cleaned up string
outputMatrix[indexOutputMatrix] = cleanedUpString;
}
}

NSLog(@"Final outputMatrix: @%@", outputMatrix);
return outputMatrix;
}

@end``````